charmxi: Throw an error when declaring a constructor as [threaded]
[charm.git] / src / xlat-i / xi-Entry.C
blob5c42a75199293e0a784be581f9b3d78034ab8072
1 #include "xi-Chare.h"
2 #include "xi-Entry.h"
3 #include "xi-Parameter.h"
4 #include "xi-SdagCollection.h"
5 #include "xi-Value.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) {
22   if (isThreaded()) str << "threaded ";
23   if (isSync()) str << "sync ";
24   if (retType) {
25     retType->print(str);
26     str << " ";
27   }
28   str << name << "(";
29   if (param) param->print(str);
30   str << ")";
31   if (stacksize) {
32     str << " stacksize = ";
33     stacksize->print(str);
34   }
35   str << ";\n";
38 void Entry::check() {
39   if (!external) {
40     if (isConstructor() && retType && !retType->isVoid())
41       XLAT_ERROR_NOCOL("constructors cannot return a value", first_line_);
43     if (!isConstructor() && !retType)
44       XLAT_ERROR_NOCOL(
45           "non-constructor entry methods must specify a return type (probably void)",
46           first_line_);
48     if (isConstructor() && (isSync() || isIget())) {
49       XLAT_ERROR_NOCOL("constructors cannot have the 'sync' attribute", first_line_);
50       attribs ^= SSYNC;
51     }
53     if (param->isCkArgMsgPtr() && (!isConstructor() || !container->isMainChare()))
54       XLAT_ERROR_NOCOL("CkArgMsg can only be used in mainchare's constructor",
55                        first_line_);
57     if (isExclusive() && isConstructor())
58       XLAT_ERROR_NOCOL("constructors cannot be 'exclusive'", first_line_);
60     if (isImmediate() && !container->isNodeGroup())
61       XLAT_ERROR_NOCOL("[immediate] entry methods are only allowed on 'nodegroup' types",
62                        first_line_);
64     if (isLocal() && (container->isChare() || container->isNodeGroup()))
65       XLAT_ERROR_NOCOL(
66           "[local] entry methods are only allowed on 'array' and 'group' types",
67           first_line_);
68   }
70   if (!isThreaded() && stacksize)
71     XLAT_ERROR_NOCOL(
72         "the 'stacksize' attribute is only applicable to methods declared 'threaded'",
73         first_line_);
75   if (retType && !isSync() && !isIget() && !isLocal() && !retType->isVoid())
76     XLAT_ERROR_NOCOL(
77         "non-void return type in a non-sync/non-local entry method\n"
78         "To return non-void, you need to declare the method as [sync], which means it "
79         "has blocking semantics,"
80         " or [local].",
81         first_line_);
83   if (!isLocal() && param) param->checkParamList();
85   if (isPython() && !container->isPython())
86     XLAT_ERROR_NOCOL("python entry method declared in non-python chare", first_line_);
88   // check the parameter passed to the function, it must be only an integer
89   if (isPython() && (!param || param->next || !param->param->getType()->isBuiltin() ||
90                      !((BuiltinType*)param->param->getType())->isInt()))
91     XLAT_ERROR_NOCOL(
92         "python entry methods take only one parameter, which is of type 'int'",
93         first_line_);
95   if (isExclusive() && !container->isNodeGroup())
96     XLAT_ERROR_NOCOL("only nodegroup methods can be 'exclusive'", first_line_);
98   // (?) Check that every when statement has a corresponding entry method
99   // declaration. Otherwise, print all candidates tested (as in clang, gcc.)
100   if (isSdag()) {
101     list<CEntry*> whenEntryList;
102     sdagCon->generateEntryList(whenEntryList, NULL);
103     // containsWhenConstruct is used to prepend sdag entry method names with "_sdag_fnc_" when it contains one or more when clauses
104     containsWhenConstruct = !whenEntryList.empty();
106     for (list<CEntry*>::iterator en = whenEntryList.begin(); en != whenEntryList.end();
107          ++en) {
108       container->lookforCEntry(*en);
109       (*en)->check();
110     }
111   }
113   if (isTramTarget()) {
114     if (param && (!param->isMarshalled() || param->isVoid() || param->next != NULL))
115       XLAT_ERROR_NOCOL(
116           "'aggregate' entry methods must be parameter-marshalled "
117           "and take a single argument",
118           first_line_);
120     if (!external && !((container->isGroup() && !container->isNodeGroup()) || container->isArray()))
121       XLAT_ERROR_NOCOL(
122           "'aggregate' entry methods can only be used in regular groups and chare arrays",
123           first_line_);
124   }
127 void Entry::lookforCEntry(CEntry* centry) {
128   // compare name
129   if (strcmp(name, *centry->entry) != 0) return;
131   centry->addCandidate(this);
133   // compare param
134   if (param && !centry->paramlist) return;
135   if (!param && centry->paramlist) return;
136   if (param && !(*param == *centry->paramlist)) return;
138   isWhenEntry = 1;
139   centry->decl_entry = this;
142 Entry::Entry(int l, int a, Type* r, const char* n, ParamList* p, Value* sz,
143              SdagConstruct* sc, const char* e, int fl, int ll)
144     : attribs(a),
145       retType(r),
146       stacksize(sz),
147       sdagCon(sc),
148       name((char*)n),
149       targs(0),
150       intExpr(e),
151       param(p),
152       genClosureTypeName(0),
153       genClosureTypeNameProxy(0),
154       genClosureTypeNameProxyTemp(0),
155       entryPtr(0),
156       first_line_(fl),
157       last_line_(ll) {
158   line = l;
159   container = NULL;
160   entryCount = -1;
161   isWhenEntry = 0;
162   containsWhenConstruct = false;
163   if (param && param->isMarshalled() && !isThreaded()) attribs |= SNOKEEP;
165   if (isPython()) pythonDoc = python_doc;
166   ParamList* plist = p;
167   while (plist != NULL) {
168     plist->entry = this;
169     if (plist->param) plist->param->entry = this;
170     plist = plist->next;
171   }
174 void Entry::setChare(Chare* c) {
175   Member::setChare(c);
176   // mainchare constructor parameter is not allowed
177   /* ****************** REMOVED 10/8/2002 ************************
178   if (isConstructor()&&container->isMainChare() && param != NULL)
179     if (!param->isCkArgMsgPtr())
180      die("MainChare Constructor doesn't allow parameter!", line);
181   Removed old treatment for CkArgMsg to allow argc, argv or void
182   constructors for mainchares.
183   * **************************************************************/
184   if (isConstructor() && param->isVoid()) {
185     if (container->isMainChare()) {
186       // Main chare always magically takes CkArgMsg
187       Type* t = new PtrType(new NamedType("CkArgMsg"));
188       param = new ParamList(new Parameter(line, t));
189       std::cerr << "Charmxi> " << line
190                 << ": Deprecation warning: mainchare constructors should explicitly take "
191                    "CkArgMsg* if that's how they're implemented.\n";
192     }
193     if (container->isArray()) {
194       Array* a = dynamic_cast<Array*>(c);
195       a->hasVoidConstructor = true;
196     }
197   }
199   entryCount = c->nextEntry();
201   // Make a special "callmarshall" method, for communication optimizations to use:
202   hasCallMarshall = param->isMarshalled() && !isThreaded() && !isSync() &&
203                     !isExclusive() && !fortranMode;
204   if (isSdag()) {
205     container->setSdag(1);
207     list<CEntry*> whenEntryList;
208     sdagCon->generateEntryList(whenEntryList, NULL);
210     for (list<CEntry*>::iterator i = whenEntryList.begin(); i != whenEntryList.end();
211          ++i) {
212       container->lookforCEntry(*i);
213     }
214   }
217 void Entry::preprocessSDAG() {
218   if (isSdag() || isWhenEntry) {
219     if (container->isNodeGroup()) {
220       attribs |= SLOCKED;  // Make the method [exclusive] to preclude races on SDAG
221                            // control structures
222     }
223   }
226 // "parameterType *msg" or "void".
227 // Suitable for use as the only parameter
228 XStr Entry::paramType(int withDefaultVals, int withEO, int useConst, int rValue) {
229   XStr str;
230   param->print(str, withDefaultVals, useConst, rValue);
231   if (withEO) str << eo(withDefaultVals, !param->isVoid());
232   return str;
235 // "parameterType *msg," if there is a non-void parameter,
236 // else empty.  Suitable for use with another parameter following.
237 XStr Entry::paramComma(int withDefaultVals, int withEO) {
238   XStr str;
239   if (!param->isVoid()) {
240     str << paramType(withDefaultVals, withEO);
241     str << ", ";
242   }
243   return str;
245 XStr Entry::eo(int withDefaultVals, int priorComma) {
246   XStr str;
247   // Add CkEntryOptions for all non message params
248   // for param->isMarshalled() and param->isVoid()
249   if (!param->isMessage()) {
250     if (priorComma) str << ", ";
251     str << "const CkEntryOptions *impl_e_opts";
252     if (withDefaultVals) str << "=NULL";
253   }
254   return str;
257 void Entry::collectSdagCode(SdagCollection* sc) {
258   if (isSdag()) {
259     sc->addNode(this);
260   }
263 XStr Entry::marshallMsg(void) {
264   XStr ret;
265   XStr epName = epStr();
266   param->marshall(ret, epName);
267   return ret;
270 XStr Entry::epStr(bool isForRedn, bool templateCall) {
271   XStr str;
272   if (isForRedn) str << "redn_wrapper_";
273   str << name << "_";
275   if (param->isMessage()) {
276     str << param->getBaseName();
277     str.replace(':', '_');
278   } else if (param->isVoid())
279     str << "void";
280   else
281     str << "marshall" << entryCount;
283   if (tspec && templateCall) {
284     str << "<";
285     tspec->genShort(str);
286     str << ">";
287   }
289   return str;
292 XStr Entry::epIdx(int fromProxy, bool isForRedn) {
293   XStr str;
294   if (fromProxy) {
295     str << indexName() << "::";
296     // If the chare is also templated, then we must avoid a parsing ambiguity
297     if (tspec) str << "template ";
298   }
299   str << "idx_" << epStr(isForRedn, true) << "()";
300   return str;
303 XStr Entry::epRegFn(int fromProxy, bool isForRedn) {
304   XStr str;
305   if (fromProxy) str << indexName() << "::";
306   str << "reg_" << epStr(isForRedn, true) << "()";
307   return str;
310 XStr Entry::chareIdx(int fromProxy) {
311   XStr str;
312   if (fromProxy) str << indexName() << "::";
313   str << "__idx";
314   return str;
317 XStr Entry::syncPreCall(void) {
318   XStr str;
319   if (retType->isVoid())
320     str << "  void *impl_msg_typed_ret = ";
321   else if (retType->isMessage())
322     str << "  " << retType << " impl_msg_typed_ret = (" << retType << ")";
323   else
324     str << "  CkMarshallMsg *impl_msg_typed_ret = (CkMarshallMsg *)";
325   return str;
328 XStr Entry::syncPostCall(void) {
329   XStr str;
330   if (retType->isVoid())
331     str << "  CkFreeSysMsg(impl_msg_typed_ret); \n";
332   else if (!retType->isMessage()) {
333     str << "  char *impl_buf_ret=impl_msg_typed_ret->msgBuf; \n";
334     str << "  PUP::fromMem implPS(impl_buf_ret); \n";
335     str << "  " << retType << " retval; implPS|retval; \n";
336     str << "  CkFreeMsg(impl_msg_typed_ret); \n";
337     str << "  return retval; \n";
338   } else {
339     str << "  return impl_msg_typed_ret;\n";
340   }
341   return str;
344 /*************************** Chare Entry Points ******************************/
346 void Entry::genChareDecl(XStr& str) {
347   if (isConstructor()) {
348     genChareStaticConstructorDecl(str);
349   } else {
350     // entry method declaration
351     str << "    " << generateTemplateSpec(tspec) << "\n"
352         << "    " << retType << " " << name << "(" << paramType(1, 1) << ");\n";
353   }
356 void Entry::genChareDefs(XStr& str) {
357   if (isConstructor()) {
358     genChareStaticConstructorDefs(str);
359   } else {
360     XStr params;
361     params << epIdx() << ", impl_msg, &ckGetChareID()";
362     // entry method definition
363     XStr retStr;
364     retStr << retType;
365     str << makeDecl(retStr, 1) << "::" << name << "(" << paramType(0, 1) << ")\n";
366     str << "{\n  ckCheck();\n";
367     str << marshallMsg();
368     if (isSync()) {
369       str << syncPreCall() << "CkRemoteCall(" << params << ");\n";
370       str << syncPostCall();
371     } else {  // Regular, non-sync message
372       str << "  if (ckIsDelegated()) {\n";
373       if (param->hasRdma()) {
374         str << "  CkAbort(\"Entry methods with nocopy parameters not supported when "
375                "called with delegation managers\");\n";
376       } else {
377         str << "    int destPE=CkChareMsgPrep(" << params << ");\n";
378         str << "    if (destPE!=-1) ckDelegatedTo()->ChareSend(ckDelegatedPtr(),"
379             << params << ",destPE);\n";
380       }
381       str << "  } else {\n";
382       XStr opts;
383       opts << ",0";
384       if (isSkipscheduler()) opts << "+CK_MSG_EXPEDITED";
385       if (isInline()) opts << "+CK_MSG_INLINE";
386       str << "    CkSendMsg(" << params << opts << ");\n";
387       str << "  }\n";
388     }
389     str << "}\n";
390   }
393 void Entry::genChareStaticConstructorDecl(XStr& str) {
394   str << "    static CkChareID ckNew(" << paramComma(1) << "int onPE=CK_PE_ANY" << eo(1)
395       << ");\n";
396   str << "    static void ckNew(" << paramComma(1)
397       << "CkChareID* pcid, int onPE=CK_PE_ANY" << eo(1) << ");\n";
398   if (!param->isVoid())
399     str << "    " << container->proxyName(0) << "(" << paramComma(1)
400         << "int onPE=CK_PE_ANY" << eo(1) << ");\n";
403 void Entry::genChareStaticConstructorDefs(XStr& str) {
404   str << makeDecl("CkChareID", 1) << "::ckNew(" << paramComma(0) << "int impl_onPE"
405       << eo(0) << ")\n";
406   str << "{\n";
407   str << marshallMsg();
408   str << "  CkChareID impl_ret;\n";
409   str << "  CkCreateChare(" << chareIdx() << ", " << epIdx()
410       << ", impl_msg, &impl_ret, impl_onPE);\n";
411   str << "  return impl_ret;\n";
412   str << "}\n";
414   str << makeDecl("void", 1) << "::ckNew(" << paramComma(0)
415       << "CkChareID* pcid, int impl_onPE" << eo(0) << ")\n";
416   str << "{\n";
417   str << marshallMsg();
418   str << "  CkCreateChare(" << chareIdx() << ", " << epIdx()
419       << ", impl_msg, pcid, impl_onPE);\n";
420   str << "}\n";
422   if (!param->isVoid()) {
423     str << makeDecl(" ", 1) << "::" << container->proxyName(0) << "(" << paramComma(0)
424         << "int impl_onPE" << eo(0) << ")\n";
425     str << "{\n";
426     str << marshallMsg();
427     str << "  CkChareID impl_ret;\n";
428     str << "  CkCreateChare(" << chareIdx() << ", " << epIdx()
429         << ", impl_msg, &impl_ret, impl_onPE);\n";
430     str << "  ckSetChareID(impl_ret);\n";
431     str << "}\n";
432   }
435 /***************************** Array Entry Points **************************/
437 void Entry::genArrayDecl(XStr& str) {
438   if (isConstructor()) {
439     str << "    " << generateTemplateSpec(tspec) << "\n";
440     genArrayStaticConstructorDecl(str);
441   } else {
442     if ((isSync() || isLocal()) && !container->isForElement())
443       return;  // No sync broadcast
444     if (isIget()) {
445       str << "    " << generateTemplateSpec(tspec) << "\n";
446       str << "    "
447           << "CkFutureID"
448           << " " << name << "(" << paramType(1, 1) << ") ;\n";  // no const
449     } else if ((isLocal() || isInline()) && container->isForElement()) {
450       XStr fwdStr;
451       int fwdNum = 1;
452       ParamList *pl = param;
453       while (pl) {
454         Parameter *p = pl->param;
455         if (!p->isRdma() && p->arrLen == NULL && !p->conditional && p->byReference) {
456           if (fwdNum > 1)
457             fwdStr << ", ";
458           fwdStr << "typename Fwd" << fwdNum++ << " = " << p->type;
459         }
460         pl = pl->next;
461       }
462       const bool doFwd = fwdNum > 1;
463       if (tspec || doFwd) {
464         str << "    template <";
465         if (tspec) {
466           tspec->genLong(str);
467           if (doFwd)
468             str << ", ";
469         }
470         if (doFwd)
471           str << fwdStr;
472         str << ">\n";
473       }
474       str << "    " << retType << " " << name << "(" << paramType(1, 1, 0, 1) << ") ;\n";
475     } else if (isLocal()) {
476       str << "    " << generateTemplateSpec(tspec) << "\n";
477       str << "    " << retType << " " << name << "(" << paramType(1, 1, 0) << ") ;\n";
478     } else if (isTramTarget() && container->isForElement()) {
479       str << "    " << generateTemplateSpec(tspec) << "\n";
480       str << "    " << retType << " " << name << "(" << paramType(0, 1) << ") = delete;\n";
481       str << "    " << retType << " " << name << "(" << paramType(1, 0) << ") ;\n";
482     } else {
483       str << "    " << generateTemplateSpec(tspec) << "\n";
484       str << "    " << retType << " " << name << "(" << paramType(1, 1)
485           << ") ;\n";  // no const
486     }
487   }
490 void Entry::genArrayDefs(XStr& str) {
491   if (isIget() && !container->isForElement()) return;
493   if (isConstructor())
494     genArrayStaticConstructorDefs(str);
495   else {  // Define array entry method
496     const char* ifNot = "CkArray_IfNotThere_buffer";
497     if (isCreateHere()) ifNot = "CkArray_IfNotThere_createhere";
498     if (isCreateHome()) ifNot = "CkArray_IfNotThere_createhome";
500     if ((isSync() || isLocal()) && !container->isForElement())
501       return;  // No sync broadcast
503     XStr retStr;
504     retStr << retType;
505     if (isIget())
506       str << makeDecl("CkFutureID ", 1) << "::" << name << "(" << paramType(0, 1)
507           << ") \n";  // no const
508     else if ((isLocal() || isInline()) && container->isForElement()) {
509       XStr fwdStr;
510       int fwdNum = 1;
511       ParamList *pl = param;
512       while (pl) {
513         Parameter *p = pl->param;
514         if (!p->isRdma() && p->arrLen == NULL && !p->conditional && p->byReference) {
515           if (fwdNum > 1)
516             fwdStr << ", ";
517           fwdStr << "typename Fwd" << fwdNum++; // << " = " << p->type;
518         }
519         pl = pl->next;
520       }
521       str << makeDecl(retStr, 1, false, fwdStr) << "::" << name << "(" << paramType(0, 1, 0, 1) << ") \n";
522     } else if (isLocal())
523       str << makeDecl(retStr, 1) << "::" << name << "(" << paramType(0, 1, 0) << ") \n";
524     else
525       str << makeDecl(retStr, 1) << "::" << name << "(" << paramType(0, 1)
526           << ") \n";  // no const
527     str << "{\n";
528     // regular broadcast and section broadcast for an entry method with rdma
529     if (param->hasRdma() && !container->isForElement()) {
530       str << "  CkAbort(\"Broadcast not supported for entry methods with nocopy "
531              "parameters\");\n";
532     } else {
533       str << "  ckCheck();\n";
534       XStr inlineCall;
535       if (!isNoTrace())
536         // Create a dummy envelope to represent the "message send" to the local/inline method
537         // so that Projections can trace the method back to its caller
538         inlineCall
539             << "    envelope env;\n"
540             << "    env.setMsgtype(ForArrayEltMsg);\n"
541             << "    env.setTotalsize(0);\n"
542             // NOTE: extra parentheses around the second argument to _TRACE_CREATION_DETAILED here
543             //       are needed for templated entry methods
544             << "    _TRACE_CREATION_DETAILED(&env, (" << epIdx() << "));\n"
545             << "    _TRACE_CREATION_DONE(1);\n"
546             << "    _TRACE_BEGIN_EXECUTE_DETAILED(CpvAccess(curPeEvent),ForArrayEltMsg,(" << epIdx()
547             << "),CkMyPe(), 0, ((CkArrayIndex&)ckGetIndex()).getProjectionID(), obj);\n";
548       if (isAppWork()) inlineCall << "    _TRACE_BEGIN_APPWORK();\n";
549       inlineCall << "#if CMK_LBDB_ON\n"
550                  << "    LDObjHandle objHandle;\n"
551                  << "    int objstopped=0;\n"
552                  << "    objHandle = obj->timingBeforeCall(&objstopped);\n"
553                  << "#endif\n";
554       inlineCall << "#if CMK_CHARMDEBUG\n"
555                     "    CpdBeforeEp("
556                  << epIdx()
557                  << ", obj, NULL);\n"
558                     "#endif\n";
559       inlineCall << "    ";
560       if (!retType->isVoid()) inlineCall << retType << " retValue = ";
561       inlineCall << "obj->" << (tspec ? "template " : "") << name;
562       if (tspec) {
563         inlineCall << "<";
564         tspec->genShort(inlineCall);
565         inlineCall << ">";
566       }
567       inlineCall << "(";
568       param->unmarshallForward(inlineCall, true);
569       inlineCall << ");\n";
570       inlineCall << "#if CMK_CHARMDEBUG\n"
571                     "    CpdAfterEp("
572                  << epIdx()
573                  << ");\n"
574                     "#endif\n";
575       inlineCall << "#if CMK_LBDB_ON\n    "
576                     "obj->timingAfterCall(objHandle,&objstopped);\n#endif\n";
577       if (isAppWork()) inlineCall << "    _TRACE_END_APPWORK();\n";
578       if (!isNoTrace()) inlineCall << "    _TRACE_END_EXECUTE();\n";
579       if (!retType->isVoid()) {
580         inlineCall << "    return retValue;\n";
581       } else {
582         inlineCall << "    return;\n";
583       }
585       XStr prepareMsg;
586       prepareMsg << marshallMsg();
587       prepareMsg << "  UsrToEnv(impl_msg)->setMsgtype(ForArrayEltMsg);\n";
588       prepareMsg << "  CkArrayMessage *impl_amsg=(CkArrayMessage *)impl_msg;\n";
589       prepareMsg << "  impl_amsg->array_setIfNotThere(" << ifNot << ");\n";
591       if (!isLocal()) {
592         if (isInline() && container->isForElement()) {
593           str << "  " << container->baseName() << " *obj = ckLocal();\n";
594           str << "  if (obj) {\n" << inlineCall << "  }\n";
595         }
596         str << prepareMsg;
597       } else {
598         str << "  " << container->baseName() << " *obj = ckLocal();\n";
599         str << "#if CMK_ERROR_CHECKING\n";
600         str << "  if (obj==NULL) CkAbort(\"Trying to call a LOCAL entry method on a "
601                "non-local element\");\n";
602         str << "#endif\n";
603         str << inlineCall;
604       }
605       if (isIget()) {
606         str << "  CkFutureID f=CkCreateAttachedFutureSend(impl_amsg," << epIdx()
607             << ",ckGetArrayID(),ckGetIndex(),&CProxyElement_ArrayBase::ckSendWrapper);"
608             << "\n";
609       }
611       if (isSync()) {
612         str << syncPreCall() << "ckSendSync(impl_amsg, " << epIdx() << ");\n";
613         str << syncPostCall();
614       } else if (!isLocal()) {
615         XStr opts;
616         opts << ",0";
617         if (isSkipscheduler()) opts << "+CK_MSG_EXPEDITED";
618         if (isInline()) opts << "+CK_MSG_INLINE";
619         if (!isIget()) {
620           if (container->isForElement() || container->isForSection()) {
621             str << "  ckSend(impl_amsg, " << epIdx() << opts << ");\n";
622           } else
623             str << "  ckBroadcast(impl_amsg, " << epIdx() << opts << ");\n";
624         }
625       }
626       if (isIget()) {
627         str << "  return f;\n";
628       }
629     }
630     str << "}\n";
632     if (!tspec && !container->isTemplated() && !isIget() && (isLocal() || isInline()) && container->isForElement()) {
633       XStr fwdStr;
634       int fwdNum = 1;
635       ParamList *pl = param;
636       while (pl) {
637         Parameter *p = pl->param;
638         if (!p->isRdma() && p->arrLen == NULL && !p->conditional && p->byReference) {
639           if (fwdNum > 1)
640             fwdStr << ", ";
641           ++fwdNum;
642           if (p->byConst) fwdStr << "const ";
643           fwdStr << p->type << " &";
644         }
645         pl = pl->next;
646       }
647       const bool doFwd = fwdNum > 1;
648       if (doFwd) {
649         str << "// explicit instantiation for compatibility\n";
650         str << "template " << makeDecl(retStr, 1) << "::" << name << "<" << fwdStr << ">(" << paramType(0, 1, 0) << ");\n";
651       }
652     }
653   }
656 void Entry::genArrayStaticConstructorDecl(XStr& str) {
657   if (!container->isArray())
658     die("Internal error - array declarations called for on non-array Chare type");
660   if (container->getForWhom() == forIndividual)
661     str <<  // Element insertion routine
662         "    void insert(" << paramComma(1, 0) << "int onPE=-1" << eo(1) << ");";
663   else if (container->getForWhom() == forAll) {
664     // With options to specify size (including potentially empty, covering the
665     // param->isVoid() case)
666     str << "    static CkArrayID ckNew(" << paramComma(1, 0)
667         << "const CkArrayOptions &opts = CkArrayOptions()" << eo(1) << ");\n";
668     str << "    static void      ckNew(" << paramComma(1, 0)
669         << "const CkArrayOptions &opts, CkCallback _ck_array_creation_cb" << eo(1)
670         << ");\n";
672     XStr dim = ((Array*)container)->dim();
673     if (dim == (const char*)"1D") {
674       str << "    static CkArrayID ckNew(" << paramComma(1, 0) << "const int s1" << eo(1)
675           << ");\n";
676       str << "    static void ckNew(" << paramComma(1, 0)
677           << "const int s1, CkCallback _ck_array_creation_cb" << eo(1) << ");\n";
678     } else if (dim == (const char*)"2D") {
679       str << "    static CkArrayID ckNew(" << paramComma(1, 0)
680           << "const int s1, const int s2" << eo(1) << ");\n";
681       str << "    static void ckNew(" << paramComma(1, 0)
682           << "const int s1, const int s2, CkCallback _ck_array_creation_cb" << eo(1)
683           << ");\n";
684     } else if (dim == (const char*)"3D") {
685       str << "    static CkArrayID ckNew(" << paramComma(1, 0)
686           << "const int s1, const int s2, const int s3" << eo(1) << ");\n";
687       str << "    static void ckNew(" << paramComma(1, 0)
688           << "const int s1, const int s2, const int s3, CkCallback _ck_array_creation_cb"
689           << eo(1) << ");\n";
690       /*} else if (dim==(const char*)"4D") {
691         str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short
692       s2, const short s3, const short s4"<<eo(1)<<");\n"; } else if (dim==(const
693       char*)"5D") { str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1,
694       const short s2, const short s3, const short s4, const short s5"<<eo(1)<<");\n"; }
695       else if (dim==(const char*)"6D") { str<<"    static CkArrayID
696       ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const
697       short s4, const short s5, const short s6"<<eo(1)<<");\n"; */
698     }
699   } else if (container->getForWhom() == forSection) {
700   }
703 void Entry::genArrayStaticConstructorDefs(XStr& str) {
704   if (!container->isArray())
705     die("Internal error - array definitions called for on non-array Chare type");
707   if (container->getForWhom() == forIndividual)
708     str << makeDecl("void", 1) << "::insert(" << paramComma(0, 0) << "int onPE" << eo(0)
709         << ")\n"
710            "{ \n "
711         << marshallMsg()
712         << "   UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
713            "   ckInsert((CkArrayMessage *)impl_msg,"
714         << epIdx() << ",onPE);\n}\n";
715   else if (container->getForWhom() == forAll) {
716     XStr syncPrototype, asyncPrototype, head, syncTail, asyncTail;
717     syncPrototype << makeDecl("CkArrayID", 1) << "::ckNew";
718     asyncPrototype << makeDecl("void", 1) << "::ckNew";
720     head << "{\n" << marshallMsg();
722     syncTail << "  UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
723              << "  CkArrayID gId = ckCreateArray((CkArrayMessage *)impl_msg, " << epIdx()
724              << ", opts);\n";
726     genTramInstantiation(syncTail);
727     syncTail << "  return gId;\n}\n";
729     asyncTail << "  UsrToEnv(impl_msg)->setMsgtype(ArrayEltInitMsg);\n"
730               << "  CkSendAsyncCreateArray(" << epIdx()
731               << ", _ck_array_creation_cb, opts, impl_msg);\n"
732               << "}\n";
734     str << syncPrototype << "(" << paramComma(0) << "const CkArrayOptions &opts" << eo(0)
735         << ")\n"
736         << head << syncTail;
737     str << asyncPrototype << "(" << paramComma(0)
738         << "const CkArrayOptions &opts, CkCallback _ck_array_creation_cb" << eo(0)
739         << ")\n"
740         << head << asyncTail;
742     XStr dim = ((Array*)container)->dim();
743     XStr sizeParams, sizeArgs;
744     bool emit = true;
746     if (dim == (const char*)"1D") {
747       sizeParams << "const int s1";
748       sizeArgs << "s1";
749     } else if (dim == (const char*)"2D") {
750       sizeParams << "const int s1, const int s2";
751       sizeArgs << "s1, s2";
752     } else if (dim == (const char*)"3D") {
753       sizeParams << "const int s1, const int s2, const int s3";
754       sizeArgs << "s1, s2, s3";
755     }
756 #if 0
757     else if (dim==(const char*)"4D") {
758       sizeParams << "const short s1, const short s2, const short s3, const short s4";
759       sizeArgs << "s1, s2, s3, s4";
760     } else if (dim==(const char*)"5D") {
761       sizeParams << "const short s1, const short s2, const short s3, const short s4, "
762                  << "const short s5";
763       sizeArgs << "s1, s2, s3, s4, s5";
764     } else if (dim==(const char*)"6D") {
765       sizeParams << "const short s1, const short s2, const short s3, const short s4, "
766                  << "const short s5, const short s6";
767       sizeArgs << "s1, s2, s3, s4, s5, s6";
768     }
769 #endif
770     else {
771       emit = false;
772     }
774     if (emit) {
775       str << syncPrototype << "(" << paramComma(0) << sizeParams << eo(0) << ")\n"
776           << head << "  CkArrayOptions opts(" << sizeArgs << ");\n"
777           << syncTail;
778       str << asyncPrototype << "(" << paramComma(0) << sizeParams
779           << ", CkCallback _ck_array_creation_cb" << eo(0) << ")\n"
780           << head << "  CkArrayOptions opts(" << sizeArgs << ");\n"
781           << asyncTail;
782     }
783   }
786 /******************************** Group Entry Points *********************************/
788 void Entry::genGroupDecl(XStr& str) {
789   if (isConstructor()) {
790     str << "    " << generateTemplateSpec(tspec) << "\n";
791     genGroupStaticConstructorDecl(str);
792   } else {
793     if ((isSync() || isLocal()) && !container->isForElement())
794       return;  // No sync broadcast
795     str << "    " << generateTemplateSpec(tspec) << "\n";
796     if (isLocal()) {
797       str << "    " << retType << " " << name << "(" << paramType(1, 1, 0) << ");\n";
798     } else if (isTramTarget() && container->isForElement()) {
799       str << "    " << retType << " " << name << "(" << paramType(0, 1) << ") = delete;\n";
800       str << "    " << retType << " " << name << "(" << paramType(1, 0) << ");\n";
801     } else {
802       str << "    " << retType << " " << name << "(" << paramType(1, 1) << ");\n";
803     }
804     // entry method on multiple PEs declaration
805     if (!container->isForElement() && !container->isForSection() && !isSync() &&
806         !isLocal() && !container->isNodeGroup()) {
807       str << "    " << generateTemplateSpec(tspec) << "\n";
808       str << "    " << retType << " " << name << "(" << paramComma(0, 0)
809           << "int npes, int *pes" << eo(1) << ");\n";
810       str << "    " << generateTemplateSpec(tspec) << "\n";
811       str << "    " << retType << " " << name << "(" << paramComma(0, 0)
812           << "CmiGroup &grp" << eo(1) << ");\n";
813     }
814   }
817 void Entry::genGroupDefs(XStr& str) {
818   if(isConstructor()) {
819     genGroupStaticConstructorDefs(str);
820     return;
821   }
823   // Selects between NodeGroup and Group
824   char* node = (char*)(container->isNodeGroup() ? "Node" : "");
826   int forElement = container->isForElement();
827   XStr params;
828   params << epIdx() << ", impl_msg";
829   XStr paramg;
830   paramg << epIdx() << ", impl_msg, ckGetGroupID()";
831   XStr parampg;
832   parampg << epIdx() << ", impl_msg, ckGetGroupPe(), ckGetGroupID()";
833   // append options parameter
834   XStr opts;
835   opts << ",0";
836   if (isImmediate()) opts << "+CK_MSG_IMMEDIATE";
837   if (isInline()) opts << "+CK_MSG_INLINE";
838   if (isSkipscheduler()) opts << "+CK_MSG_EXPEDITED";
840   if ((isSync() || isLocal()) && !container->isForElement())
841     return;  // No sync broadcast
843   XStr retStr;
844   retStr << retType;
845   XStr msgTypeStr;
846   if (isLocal())
847     msgTypeStr << paramType(0, 1, 0);
848   else
849     msgTypeStr << paramType(0, 1);
850   str << makeDecl(retStr, 1) << "::" << name << "(" << msgTypeStr << ")\n";
851   str << "{\n";
852   // regular broadcast and section broadcast for an entry method with rdma
853   if (param->hasRdma() && !container->isForElement()) {
854     str << "  CkAbort(\"Broadcast not supported for entry methods with nocopy "
855            "parameters\");\n";
856   } else {
857     str << "  ckCheck();\n";
858     if (!isLocal()) str << marshallMsg();
860     if (isLocal()) {
861       XStr unmarshallStr;
862       param->unmarshall(unmarshallStr, true);
863       str << "  " << container->baseName() << " *obj = ckLocalBranch();\n";
864       str << "  CkAssert(obj);\n";
865       if (!isNoTrace())
866         // Create a dummy envelope to represent the "message send" to the local/inline method
867         // so that Projections can trace the method back to its caller
868         str << "  envelope env;\n"
869             << "  env.setMsgtype(ForBocMsg);\n"
870             << "  env.setTotalsize(0);\n"
871             << "  _TRACE_CREATION_DETAILED(&env, " << epIdx() << ");\n"
872             << "  _TRACE_CREATION_DONE(1);\n"
873             << "  _TRACE_BEGIN_EXECUTE_DETAILED(CpvAccess(curPeEvent),ForBocMsg,(" << epIdx()
874             << "),CkMyPe(),0,NULL, NULL);\n";
875       if (isAppWork()) str << " _TRACE_BEGIN_APPWORK();\n";
876       str << "#if CMK_LBDB_ON\n"
877              "  // if there is a running obj being measured, stop it temporarily\n"
878              "  LDObjHandle objHandle;\n"
879              "  int objstopped = 0;\n"
880              "  LBDatabase *the_lbdb = (LBDatabase *)CkLocalBranch(_lbdb);\n"
881              "  if (the_lbdb->RunningObject(&objHandle)) {\n"
882              "    objstopped = 1;\n"
883              "    the_lbdb->ObjectStop(objHandle);\n"
884              "  }\n"
885              "#endif\n";
886       str << "#if CMK_CHARMDEBUG\n"
887              "  CpdBeforeEp("
888           << epIdx()
889           << ", obj, NULL);\n"
890              "#endif\n  ";
891       if (!retType->isVoid()) str << retType << " retValue = ";
892       str << "obj->" << name << "(" << unmarshallStr << ");\n";
893       str << "#if CMK_CHARMDEBUG\n"
894              "  CpdAfterEp("
895           << epIdx()
896           << ");\n"
897              "#endif\n";
898       str << "#if CMK_LBDB_ON\n"
899              "  if (objstopped) the_lbdb->ObjectStart(objHandle);\n"
900              "#endif\n";
901       if (isAppWork()) str << " _TRACE_END_APPWORK();\n";
902       if (!isNoTrace()) str << "  _TRACE_END_EXECUTE();\n";
903       if (!retType->isVoid()) str << "  return retValue;\n";
904     } else if (isSync()) {
905       str << syncPreCall() << "CkRemote" << node << "BranchCall(" << paramg
906           << ", ckGetGroupPe());\n";
907       str << syncPostCall();
908     } else {             // Non-sync, non-local entry method
909       if (forElement) {  // Send
910         str << "  if (ckIsDelegated()) {\n";
911         if (param->hasRdma()) {
912           str << "    CkAbort(\"Entry methods with nocopy parameters not supported "
913                  "when called with delegation managers\");\n";
914         } else {
915           str << "     Ck" << node << "GroupMsgPrep(" << paramg << ");\n";
916           str << "     ckDelegatedTo()->" << node << "GroupSend(ckDelegatedPtr(),"
917               << parampg << ");\n";
918         }
919         str << "  } else {\n";
920         str << "    CkSendMsg" << node << "Branch"
921             << "(" << parampg << opts << ");\n";
922         str << "  }\n";
923       } else if (container->isForSection()) {  // Multicast
924         str << "  if (ckIsDelegated()) {\n";
925         str << "     ckDelegatedTo()->" << node << "GroupSectionSend(ckDelegatedPtr(),"
926             << params << ", ckGetNumSections(), ckGetSectionIDs());\n";
927         str << "  } else {\n";
928         str << "    void *impl_msg_tmp;\n";
929         str << "    for (int i=0; i<ckGetNumSections(); ++i) {\n";
930         str << "       impl_msg_tmp= (i<ckGetNumSections()-1) ? CkCopyMsg((void **) "
931                "&impl_msg):impl_msg;\n";
932         str << "       CkSendMsg" << node << "BranchMulti(" << epIdx()
933             << ", impl_msg_tmp, ckGetGroupIDn(i), ckGetNumElements(i), ckGetElements(i)"
934             << opts << ");\n";
935         str << "    }\n";
936         str << "  }\n";
937       } else {  // Broadcast
938         str << "  if (ckIsDelegated()) {\n";
939         str << "     Ck" << node << "GroupMsgPrep(" << paramg << ");\n";
940         str << "     ckDelegatedTo()->" << node << "GroupBroadcast(ckDelegatedPtr(),"
941             << paramg << ");\n";
942         str << "  } else CkBroadcastMsg" << node << "Branch(" << paramg << opts
943             << ");\n";
944       }
945     }
946   }
947   str << "}\n";
949   // entry method on multiple PEs declaration
950   if (!forElement && !container->isForSection() && !isSync() && !isLocal() &&
951       !container->isNodeGroup()) {
952     str << "" << makeDecl(retStr, 1) << "::" << name << "(" << paramComma(0, 0)
953         << "int npes, int *pes" << eo(0) << ") {\n";
954     if (param->hasRdma()) {
955       str << "  CkAbort(\"Broadcast not supported for entry methods with nocopy "
956              "parameters\");\n";
957     } else {
958       str << marshallMsg();
959       str << "  CkSendMsg" << node << "BranchMulti(" << paramg << ", npes, pes" << opts
960           << ");\n";
961     }
962     str << "}\n";
963     str << "" << makeDecl(retStr, 1) << "::" << name << "(" << paramComma(0, 0)
964         << "CmiGroup &grp" << eo(0) << ") {\n";
965     if (param->hasRdma()) {
966       str << "  CkAbort(\"Broadcast not supported for entry methods with nocopy "
967              "parameters\");\n";
968     } else {
969       str << marshallMsg();
970       str << "  CkSendMsg" << node << "BranchGroup(" << paramg << ", grp" << opts
971           << ");\n";
972     }
973     str << "}\n";
974   }
977 XStr Entry::aggregatorIndexType() {
978   XStr indexType;
979   if (container->isGroup()) {
980     indexType << "int";
981   } else if (container->isArray()) {
982     XStr dim, arrayIndexType;
983     dim << ((Array*)container)->dim();
984     if (dim == "1D") {
985       indexType << "int";
986     } else {
987       indexType << "CkArrayIndex";
988     }
989   }
990   return indexType;
993 XStr Entry::dataItemType() {
994   XStr itemType;
995   if (container->isGroup()) {
996     itemType << param->param->type;
997   } else if (container->isArray()) {
998     itemType << "ArrayDataItem<" << param->param->type << ", " << aggregatorIndexType()
999              << ">";
1000   }
1001   return itemType;
1004 XStr Entry::aggregatorType() {
1005   XStr groupType;
1006   if (container->isGroup()) {
1007     groupType << "GroupMeshStreamer<" << param->param->type << ", "
1008               << container->baseName() << ", SimpleMeshRouter"
1009               << ", " << container->indexName() << "::_callmarshall_" << epStr() << ">";
1010   } else if (container->isArray()) {
1011     groupType << "ArrayMeshStreamer<" << param->param->type << ", "
1012               << aggregatorIndexType() << ", " << container->baseName() << ", "
1013               << "SimpleMeshRouter, " << container->indexName() << "::_callmarshall_"
1014               << epStr() << ">";
1015   }
1016   return groupType;
1019 XStr Entry::aggregatorGlobalType(XStr& scope) {
1020   XStr groupType;
1021   if (container->isGroup()) {
1022     groupType << "GroupMeshStreamer<" << param->param->type << ", " << scope
1023               << container->baseName() << ", SimpleMeshRouter"
1024               << ", " << scope << container->indexName() << "::_callmarshall_" << epStr()
1025               << ">";
1026   } else if (container->isArray()) {
1027     groupType << "ArrayMeshStreamer<" << param->param->type << ", "
1028               << aggregatorIndexType() << ", " << scope << container->baseName() << ", "
1029               << "SimpleMeshRouter, " << scope << container->indexName()
1030               << "::_callmarshall_" << epStr() << ">";
1031   }
1032   return groupType;
1035 XStr Entry::aggregatorName() {
1036   XStr aggregatorName;
1037   aggregatorName << epStr() << "TramAggregator";
1038   return aggregatorName;
1041 void Entry::genTramTypes() {
1042   if (isTramTarget()) {
1043     XStr typeString, nameString, itemTypeString;
1044     typeString << aggregatorType();
1045     nameString << aggregatorName();
1046     itemTypeString << dataItemType();
1047 #if __cplusplus >= 201103L
1048     container->tramInstances.emplace_back(
1049         typeString.get_string(), nameString.get_string(), itemTypeString.get_string());
1050 #else
1051     container->tramInstances.push_back(TramInfo(
1052         typeString.get_string(), nameString.get_string(), itemTypeString.get_string()));
1053 #endif
1054     tramInstanceIndex = container->tramInstances.size();
1055   }
1058 void Entry::genTramDefs(XStr& str) {
1059   XStr retStr;
1060   retStr << retType;
1061   XStr msgTypeStr;
1063   if (isLocal())
1064     msgTypeStr << paramType(0, 0, 0);
1065   else
1066     msgTypeStr << paramType(0, 0);
1067   str << makeDecl(retStr, 1) << "::" << name << "(" << msgTypeStr << ") {\n"
1068       << "  if (" << aggregatorName() << " == NULL) {\n";
1070   if (container->isGroup()) {
1071     str << "    CkGroupID gId = ckGetGroupID();\n";
1072   } else if (container->isArray()) {
1073     str << "    CkArray *aMgr = ckLocalBranch();\n"
1074         << "    CkGroupID gId = aMgr->getGroupID();\n";
1075   }
1077   str << "    CkGroupID tramGid;\n"
1078       << "    tramGid.idx = gId.idx + " << tramInstanceIndex << ";\n"
1079       << "    " << aggregatorName() << " = (" << aggregatorType() << "*)"
1080       << " CkLocalBranch(tramGid);\n  }\n";
1082   if (container->isGroup()) {
1083     str << "  " << aggregatorName() << "->insertData(" << param->param->name << ", "
1084         << "ckGetGroupPe());\n}\n";
1085   } else if (container->isArray()) {
1086     XStr dim;
1087     dim << ((Array*)container)->dim();
1088     str << "  const CkArrayIndex &myIndex = ckGetIndex();\n"
1089         << "  " << aggregatorName() << "->insertData<" << (isInline() ? "true" : "false")
1090         << ">(" << param->param->name;
1091     if (dim == (const char*)"1D") {
1092       str << ", "
1093           << "myIndex.data()[0]);\n}\n";
1094     } else {
1095       str << ", "
1096           << "myIndex);\n}\n";
1097     }
1098   }
1101 // size of TRAM buffers in bytes
1102 const static int tramBufferSize = 16384;
1104 void Entry::genTramInstantiation(XStr& str) {
1105   if (!container->tramInstances.empty()) {
1106     str << "  int pesPerNode = CkMyNodeSize();\n"
1107         << "  if (pesPerNode == 1) {\n"
1108         << "    pesPerNode = CmiNumCores();\n"
1109         << "  }\n"
1110         << "  const int nDims = 2;\n"
1111         << "  int dims[nDims];\n"
1112         << "  dims[0] = CkNumPes() / pesPerNode;\n"
1113         << "  dims[1] = pesPerNode;\n"
1114         << "  if (dims[0] * dims[1] != CkNumPes()) {\n"
1115         << "    dims[0] = CkNumPes();\n"
1116         << "    dims[1] = 1;\n"
1117         << "  }\n"
1118         << "  int tramBufferSize = " << tramBufferSize << ";\n";
1119     for (int i = 0; i < container->tramInstances.size(); i++) {
1120       str << "  {\n"
1121           << "    int itemsPerBuffer = tramBufferSize / sizeof("
1122           << container->tramInstances[i].itemType.c_str() << ");\n"
1123           << "    if (itemsPerBuffer == 0) {\n"
1124           << "      itemsPerBuffer = 1;\n"
1125           << "    }\n"
1126           << "    CProxy_" << container->tramInstances[i].type.c_str() << " tramProxy =\n"
1127           << "    CProxy_" << container->tramInstances[i].type.c_str()
1128           << "::ckNew(2, dims, gId, itemsPerBuffer, false, 10.0);\n"
1129           << "    tramProxy.enablePeriodicFlushing();\n"
1130           << "  }\n";
1131     }
1132   }
1135 XStr Entry::tramBaseType() {
1136   XStr baseTypeString;
1137   baseTypeString << "MeshStreamer<" << dataItemType() << ", SimpleMeshRouter>";
1139   return baseTypeString;
1142 void Entry::genTramRegs(XStr& str) {
1143   if (isTramTarget()) {
1144     XStr messageTypeString;
1145     messageTypeString << "MeshStreamerMessage<" << dataItemType() << ">";
1147     XStr baseTypeString = tramBaseType();
1149     NamedType messageType(messageTypeString.get_string());
1150     Message helper(-1, &messageType);
1151     helper.genReg(str);
1153     str << "\n  /* REG: group " << aggregatorType() << ": IrrGroup;\n  */\n"
1154         << "  CkIndex_" << aggregatorType() << "::__register(\"" << aggregatorType()
1155         << "\", sizeof(" << aggregatorType() << "));\n"
1156         << "  /* REG: group " << baseTypeString << ": IrrGroup;\n  */\n"
1157         << "  CkIndex_" << baseTypeString << "::__register(\"" << baseTypeString
1158         << "\", sizeof(" << baseTypeString << "));\n";
1159   }
1162 void Entry::genTramPups(XStr& scope, XStr& decls, XStr& defs) {
1163   if (isTramTarget()) {
1164     XStr aggregatorTypeString = aggregatorGlobalType(scope);
1165     container->genRecursivePup(aggregatorTypeString, "template <>\n", decls, defs);
1166   }
1169 void Entry::genGroupStaticConstructorDecl(XStr& str) {
1170   if (container->isForElement()) return;
1171   if (container->isForSection()) return;
1173   str << "    static CkGroupID ckNew(" << paramType(1, 1) << ");\n";
1174   if (!param->isVoid()) {
1175     str << "    " << container->proxyName(0) << "(" << paramType(1, 1) << ");\n";
1176   }
1179 void Entry::genGroupStaticConstructorDefs(XStr& str) {
1180   if (container->isForElement()) return;
1181   if (container->isForSection()) return;
1183   // Selects between NodeGroup and Group
1184   char* node = (char*)(container->isNodeGroup() ? "Node" : "");
1185   str << makeDecl("CkGroupID", 1) << "::ckNew(" << paramType(0, 1) << ")\n";
1186   str << "{\n";
1187   str << marshallMsg();
1188   str << "  UsrToEnv(impl_msg)->setMsgtype(" << node << "BocInitMsg);\n";
1189   str << "  CkGroupID gId = CkCreate" << node << "Group(" << chareIdx() << ", " << epIdx()
1190       << ", impl_msg);\n";
1192   genTramInstantiation(str);
1194   str << "  return gId;\n";
1195   str << "}\n";
1197   if (!param->isVoid()) {
1198     str << makeDecl(" ", 1) << "::" << container->proxyName(0) << "(" << paramType(0, 1)
1199         << ")\n";
1200     str << "{\n";
1201     str << marshallMsg();
1202     str << "  UsrToEnv(impl_msg)->setMsgtype(" << node << "BocInitMsg);\n";
1203     str << "  ckSetGroupID(CkCreate" << node << "Group(" << chareIdx() << ", " << epIdx()
1204         << ", impl_msg));\n";
1205     str << "}\n";
1206   }
1209 /******************* Python Entry Point Code **************************/
1210 void Entry::genPythonDecls(XStr& str) {
1211   str << "/* STATIC DECLS: ";
1212   print(str);
1213   str << " */\n";
1214   if (isPython()) {
1215     str << "PyObject *_Python_" << container->baseName() << "_" << name
1216         << "(PyObject *self, PyObject *arg);\n";
1217   }
1220 void Entry::genPythonDefs(XStr& str) {
1221   str << "/* DEFS: ";
1222   print(str);
1223   str << " */\n";
1224   if (isPython()) {
1225     str << "PyObject *_Python_" << container->baseName() << "_" << name
1226         << "(PyObject *self, PyObject *arg) {\n";
1227     str << "  PyObject *dict = PyModule_GetDict(PyImport_AddModule(\"__main__\"));\n";
1228     str << "  int pyNumber = "
1229            "PyInt_AsLong(PyDict_GetItemString(dict,\"__charmNumber__\"));\n";
1230     str << "  PythonObject *pythonObj = (PythonObject "
1231            "*)PyLong_AsVoidPtr(PyDict_GetItemString(dict,\"__charmObject__\"));\n";
1232     str << "  " << container->baseName() << " *object = static_cast<"
1233         << container->baseName() << "*>(pythonObj);\n";
1234     str << "  object->pyWorkers[pyNumber].arg=arg;\n";
1235     str << "  object->pyWorkers[pyNumber].result=&CtvAccess(pythonReturnValue);\n";
1236     str << "  object->pyWorkers[pyNumber].pythread=PyThreadState_Get();\n";
1237     str << "  CtvAccess(pythonReturnValue) = 0;\n";
1239     str << "  //pyWorker->thisProxy." << name << "(pyNumber);\n";
1240     str << "  object->" << name << "(pyNumber);\n";
1242     str << "  //CthSuspend();\n";
1244     str << "  if (CtvAccess(pythonReturnValue)) {\n";
1245     str << "    return CtvAccess(pythonReturnValue);\n";
1246     str << "  } else {\n";
1247     str << "    Py_INCREF(Py_None); return Py_None;\n";
1248     str << "  }\n";
1249     str << "}\n";
1250   }
1253 void Entry::genPythonStaticDefs(XStr& str) {
1254   if (isPython()) {
1255     str << "  {\"" << name << "\",_Python_" << container->baseName() << "_" << name
1256         << ",METH_VARARGS},\n";
1257   }
1260 void Entry::genPythonStaticDocs(XStr& str) {
1261   if (isPython()) {
1262     str << "\n  \"" << name << " -- \"";
1263     if (pythonDoc) str << (char*)pythonDoc;
1264     str << "\"\\\\n\"";
1265   }
1268 /******************* Accelerator (Accel) Entry Point Code ********************/
1270 void Entry::genAccelFullParamList(XStr& str, int makeRefs) {
1271   if (!isAccel()) return;
1273   ParamList* curParam = NULL;
1274   int isFirst = 1;
1276   // Parameters (which are read only by default)
1277   curParam = param;
1278   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1279     curParam = curParam->next;
1280   }
1281   while (curParam != NULL) {
1282     if (!isFirst) {
1283       str << ", ";
1284     }
1286     Parameter* param = curParam->param;
1288     if (param->isArray()) {
1289       str << param->getType()->getBaseName() << "* " << param->getName();
1290     } else {
1291       str << param->getType()->getBaseName() << " " << param->getName();
1292     }
1294     isFirst = 0;
1295     curParam = curParam->next;
1296   }
1298   // Accel parameters
1299   curParam = accelParam;
1300   while (curParam != NULL) {
1301     if (!isFirst) {
1302       str << ", ";
1303     }
1305     Parameter* param = curParam->param;
1306     int bufType = param->getAccelBufferType();
1307     int needWrite = makeRefs && ((bufType == Parameter::ACCEL_BUFFER_TYPE_READWRITE) ||
1308                                  (bufType == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY));
1309     if (param->isArray()) {
1310       str << param->getType()->getBaseName() << "* " << param->getName();
1311     } else {
1312       str << param->getType()->getBaseName() << ((needWrite) ? (" &") : (" "))
1313           << param->getName();
1314     }
1316     isFirst = 0;
1317     curParam = curParam->next;
1318   }
1320   // Implied object pointer
1321   if (!isFirst) {
1322     str << ", ";
1323   }
1324   str << container->baseName() << "* impl_obj";
1327 void Entry::genAccelFullCallList(XStr& str) {
1328   if (!isAccel()) return;
1330   int isFirstFlag = 1;
1332   // Marshalled parameters to entry method
1333   ParamList* curParam = param;
1334   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1335     curParam = curParam->next;
1336   }
1337   while (curParam != NULL) {
1338     if (!isFirstFlag) str << ", ";
1339     isFirstFlag = 0;
1340     str << curParam->param->getName();
1341     curParam = curParam->next;
1342   }
1344   // General variables (prefix with "impl_obj->" for member variables of the current
1345   // object)
1346   curParam = accelParam;
1347   while (curParam != NULL) {
1348     if (!isFirstFlag) str << ", ";
1349     isFirstFlag = 0;
1350     str << (*(curParam->param->getAccelInstName()));
1351     curParam = curParam->next;
1352   }
1354   // Implied object
1355   if (!isFirstFlag) str << ", ";
1356   isFirstFlag = 0;
1357   str << "impl_obj";
1360 void Entry::genAccelIndexWrapperDecl_general(XStr& str) {
1361   str << "    static void _accelCall_general_" << epStr() << "(";
1362   genAccelFullParamList(str, 1);
1363   str << ");\n";
1366 void Entry::genAccelIndexWrapperDef_general(XStr& str) {
1367   str << makeDecl("void") << "::_accelCall_general_" << epStr() << "(";
1368   genAccelFullParamList(str, 1);
1369   str << ") {\n\n";
1371   //// DMK - DEBUG
1372   // str << "  // DMK - DEBUG\n";
1373   // str << "  CkPrintf(\"[DEBUG-ACCEL] :: [PPE] - "
1374   //    << makeDecl("void") << "::_accelCall_general_" << epStr()
1375   //    << "(...) - Called...\\n\");\n\n";
1377   str << (*accelCodeBody);
1379   str << "\n\n";
1380   str << "  impl_obj->" << (*accelCallbackName) << "();\n";
1381   str << "}\n";
1384 void Entry::genAccelIndexWrapperDecl_spe(XStr& str) {
1385   // Function to issue work request
1386   str << "    static void _accelCall_spe_" << epStr() << "(";
1387   genAccelFullParamList(str, 0);
1388   str << ");\n";
1390   // Callback function that is a member of CkIndex_xxx
1391   str << "    static void _accelCall_spe_callback_" << epStr() << "(void* userPtr);\n";
1394 // DMK - Accel Support
1395 #if CMK_CELL != 0
1396 #include "spert.h"
1397 #endif
1399 void Entry::genAccelIndexWrapperDef_spe(XStr& str) {
1400   XStr containerType = container->baseName();
1402   // Some blank space for readability
1403   str << "\n\n";
1405   ///// Generate struct that will be passed to callback function /////
1407   str << "typedef struct __spe_callback_struct_" << epStr() << " {\n"
1408       << "  " << containerType << "* impl_obj;\n"
1409       << "  WRHandle wrHandle;\n"
1410       << "  void* scalar_buf_ptr;\n";
1412   // Pointers for marshalled parameter buffers
1413   ParamList* curParam = param;
1414   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1415     curParam = curParam->next;
1416   }
1417   while (curParam != NULL) {
1418     if (curParam->param->isArray()) {
1419       str << "  void* param_buf_ptr_" << curParam->param->getName() << ";\n";
1420     }
1421     curParam = curParam->next;
1422   }
1423   curParam = accelParam;
1424   while (curParam != NULL) {
1425     if (curParam->param->isArray()) {
1426       str << "  void* accelParam_buf_ptr_" << curParam->param->getName() << ";\n";
1427     }
1428     curParam = curParam->next;
1429   }
1431   str << "} SpeCallbackStruct_" << epStr() << ";\n\n";
1433   ///// Generate callback function /////
1435   str << "void _accelCall_spe_callback_" << container->baseName() << "_" << epStr()
1436       << "(void* userPtr) {\n"
1437       << "  " << container->indexName() << "::_accelCall_spe_callback_" << epStr()
1438       << "(userPtr);\n"
1439       << "}\n";
1441   str << makeDecl("void") << "::_accelCall_spe_callback_" << epStr()
1442       << "(void* userPtr) {\n";
1443   str << "  SpeCallbackStruct_" << epStr() << "* cbStruct = (SpeCallbackStruct_"
1444       << epStr() << "*)userPtr;\n";
1445   str << "  " << containerType << "* impl_obj = cbStruct->impl_obj;\n";
1447   // Write scalars that are 'out' or 'inout' from the scalar buffer back into memory
1449   if (accel_numScalars > 0) {
1450     // Get the pointer to the scalar buffer
1451     int dmaList_scalarBufIndex = 0;
1452     if (accel_dmaList_scalarNeedsWrite) {
1453       dmaList_scalarBufIndex += accel_dmaList_numReadOnly;
1454     }
1455     str << "  char* __scalar_buf_offset = (char*)(cbStruct->scalar_buf_ptr);\n";
1457     // Parameters
1458     curParam = param;
1459     if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1460       curParam = curParam->next;
1461     }
1462     while (curParam != NULL) {
1463       if (!(curParam->param->isArray())) {
1464         str << "  __scalar_buf_offset += sizeof("
1465             << curParam->param->getType()->getBaseName() << ");\n";
1466       }
1467       curParam = curParam->next;
1468     }
1470     // Read only accel parameters
1471     curParam = accelParam;
1472     while (curParam != NULL) {
1473       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1474                                               Parameter::ACCEL_BUFFER_TYPE_READONLY)) {
1475         str << "  __scalar_buf_offset += sizeof("
1476             << curParam->param->getType()->getBaseName() << ");\n";
1477       }
1478       curParam = curParam->next;
1479     }
1481     // Read write accel parameters
1482     curParam = accelParam;
1483     while (curParam != NULL) {
1484       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1485                                               Parameter::ACCEL_BUFFER_TYPE_READWRITE)) {
1486         str << "  " << (*(curParam->param->getAccelInstName())) << " = *(("
1487             << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1488         str << "  __scalar_buf_offset += sizeof("
1489             << curParam->param->getType()->getBaseName() << ");\n";
1490       }
1491       curParam = curParam->next;
1492     }
1494     // Write only accel parameters
1495     curParam = accelParam;
1496     while (curParam != NULL) {
1497       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1498                                               Parameter::ACCEL_BUFFER_TYPE_WRITEONLY)) {
1499         str << "  " << (*(curParam->param->getAccelInstName())) << " = *(("
1500             << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1501         str << "  __scalar_buf_offset += sizeof("
1502             << curParam->param->getType()->getBaseName() << ");\n";
1503       }
1504       curParam = curParam->next;
1505     }
1506   }
1508   // Call the callback function
1509   str << "  (cbStruct->impl_obj)->" << (*accelCallbackName) << "();\n";
1511   // Free memory
1512   str << "  if (cbStruct->scalar_buf_ptr != NULL) { "
1513          "free_aligned(cbStruct->scalar_buf_ptr); }\n";
1514   curParam = param;
1515   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1516     curParam = curParam->next;
1517   }
1518   while (curParam != NULL) {
1519     if (curParam->param->isArray()) {
1520       str << "  if (cbStruct->param_buf_ptr_" << curParam->param->getName()
1521           << " != NULL) { "
1522           << "free_aligned(cbStruct->param_buf_ptr_" << curParam->param->getName()
1523           << "); "
1524           << "}\n";
1525     }
1526     curParam = curParam->next;
1527   }
1528   str << "  delete cbStruct;\n";
1530   str << "}\n\n";
1532   ///// Generate function to issue work request /////
1534   str << makeDecl("void") << "::_accelCall_spe_" << epStr() << "(";
1535   genAccelFullParamList(str, 0);
1536   str << ") {\n\n";
1538   //// DMK - DEBUG
1539   // str << "  // DMK - DEBUG\n"
1540   //    << "  CkPrintf(\"[DEBUG-ACCEL] :: [PPE] - "
1541   //    << makeDecl("void") << "::_accelCall_spe_" << epStr()
1542   //    << "(...) - Called... (funcIndex:%d)\\n\", accel_spe_func_index__" << epStr() <<
1543   //    ");\n\n";
1545   str << "  // Allocate a user structure to be passed to the callback function\n"
1546       << "  SpeCallbackStruct_" << epStr() << "* cbStruct = new SpeCallbackStruct_"
1547       << epStr() << ";\n"
1548       << "  cbStruct->impl_obj = impl_obj;\n"
1549       << "  cbStruct->wrHandle = INVALID_WRHandle;  // NOTE: Set actual value later...\n"
1550       << "  cbStruct->scalar_buf_ptr = NULL;\n";
1551   // Set all parameter buffer pointers in the callback structure to NULL
1552   curParam = param;
1553   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1554     curParam = curParam->next;
1555   }
1556   while (curParam != NULL) {
1557     if (curParam->param->isArray()) {
1558       str << "  cbStruct->param_buf_ptr_" << curParam->param->getName() << " = NULL;\n";
1559     }
1560     curParam = curParam->next;
1561   }
1562   curParam = accelParam;
1563   while (curParam != NULL) {
1564     if (curParam->param->isArray()) {
1565       str << "  cbStruct->accelParam_buf_ptr_" << curParam->param->getName()
1566           << " = NULL;\n";
1567     }
1568     curParam = curParam->next;
1569   }
1570   str << "\n";
1572   // Create the DMA list
1573   int dmaList_curIndex = 0;
1574   int numDMAListEntries = accel_numArrays;
1575   if (accel_numScalars > 0) {
1576     numDMAListEntries++;
1577   }
1578   if (numDMAListEntries <= 0) {
1579     XLAT_ERROR_NOCOL("accel entry with no parameters", first_line_);
1580   }
1582 // DMK - NOTE : TODO : FIXME - For now, force DMA lists to only be the static length or
1583 // less.
1584 //   Fix this in the future to handle any length supported by hardware.  Also, for now,
1585 //   #if this check since non-Cell architectures do not have SPE_DMA_LIST_LENGTH defined
1586 //   and this code should not be called unless this is a Cell architecture.
1587 #if CMK_CELL != 0
1588   if (numDMAListEntries > SPE_DMA_LIST_LENGTH) {
1589     die("Accel entries do not support parameter lists of length > SPE_DMA_LIST_LENGTH "
1590         "yet... fix me...");
1591   }
1592 #endif
1594   // Do a pass of all the parameters, determine the size of all scalars (to pack them)
1595   if (accel_numScalars > 0) {
1596     str << "  // Create a single buffer to hold all the scalar values\n";
1597     str << "  int scalar_buf_len = 0;\n";
1598     curParam = param;
1599     if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1600       curParam = curParam->next;
1601     }
1602     while (curParam != NULL) {
1603       if (!(curParam->param->isArray())) {
1604         str << "  scalar_buf_len += sizeof(" << curParam->param->getType()->getBaseName()
1605             << ");\n";
1606       }
1607       curParam = curParam->next;
1608     }
1609     curParam = accelParam;
1610     while (curParam != NULL) {
1611       if (!(curParam->param->isArray())) {
1612         str << "  scalar_buf_len += sizeof(" << curParam->param->getType()->getBaseName()
1613             << ");\n";
1614       }
1615       curParam = curParam->next;
1616     }
1617     str << "  scalar_buf_len = ROUNDUP_128(scalar_buf_len);\n"
1618         << "  cbStruct->scalar_buf_ptr = malloc_aligned(scalar_buf_len, 128);\n"
1619         << "  char* scalar_buf_offset = (char*)(cbStruct->scalar_buf_ptr);\n\n";
1620   }
1622   // Declare the DMA list
1623   str << "  // Declare and populate the DMA list for the work request\n";
1624   str << "  DMAListEntry dmaList[" << numDMAListEntries << "];\n\n";
1626   // Parameters: read only by default & arrays need to be copied since message will be
1627   // deleted
1628   curParam = param;
1629   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1630     curParam = curParam->next;
1631   }
1632   while (curParam != NULL) {
1633     // Check to see if the scalar buffer needs slipped into the dma list here
1634     if (accel_numScalars > 0) {
1635       if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1636           ((dmaList_curIndex == accel_dmaList_numReadOnly) &&
1637            (accel_dmaList_scalarNeedsWrite))) {
1638         str << "  /*** Scalar Buffer ***/\n"
1639             << "  dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1640             << "  dmaList[" << dmaList_curIndex
1641             << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1642         dmaList_curIndex++;
1643       }
1644     }
1646     // Add this parameter to the dma list (somehow)
1647     str << "  /*** Param: '" << curParam->param->getName() << "' ***/\n";
1648     if (curParam->param->isArray()) {
1649       str << "  {\n"
1650           << "    int bufSize = sizeof(" << curParam->param->getType()->getBaseName()
1651           << ") * (" << curParam->param->getArrayLen() << ");\n"
1652           << "    bufSize = ROUNDUP_128(bufSize);\n"
1653           << "    cbStruct->param_buf_ptr_" << curParam->param->getName()
1654           << " = malloc_aligned(bufSize, 128);\n"
1655           << "    memcpy(cbStruct->param_buf_ptr_" << curParam->param->getName() << ", "
1656           << curParam->param->getName() << ", bufSize);\n"
1657           << "    dmaList[" << dmaList_curIndex << "].size = bufSize;\n"
1658           << "    dmaList[" << dmaList_curIndex
1659           << "].ea = (unsigned int)(cbStruct->param_buf_ptr_"
1660           << curParam->param->getName() << ");\n"
1661           << "  }\n";
1662       dmaList_curIndex++;
1663     } else {
1664       str << "  *((" << curParam->param->getType()->getBaseName()
1665           << "*)scalar_buf_offset) = " << curParam->param->getName() << ";\n"
1666           << "  scalar_buf_offset += sizeof(" << curParam->param->getType()->getBaseName()
1667           << ");\n";
1668     }
1669     curParam = curParam->next;
1670     str << "\n";
1671   }
1673   // Read only accel params
1674   curParam = accelParam;
1675   while (curParam != NULL) {
1676     // Check to see if the scalar buffer needs slipped into the dma list here
1677     if (accel_numScalars > 0) {
1678       if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1679           ((dmaList_curIndex == accel_dmaList_numReadOnly) &&
1680            (accel_dmaList_scalarNeedsWrite))) {
1681         str << "  /*** Scalar Buffer ***/\n"
1682             << "  dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1683             << "  dmaList[" << dmaList_curIndex
1684             << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1685         dmaList_curIndex++;
1686       }
1687     }
1689     // Add this parameter
1690     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY) {
1691       str << "  /*** Accel Param: '" << curParam->param->getName() << " ("
1692           << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1693       if (curParam->param->isArray()) {
1694         str << "  dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1695             << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1696             << "(" << curParam->param->getArrayLen() << "));\n"
1697             << "  dmaList[" << dmaList_curIndex << "].ea = (unsigned int)("
1698             << (*(curParam->param->getAccelInstName())) << ");\n";
1699         dmaList_curIndex++;
1700       } else {
1701         str << "  *((" << curParam->param->getType()->getBaseName()
1702             << "*)scalar_buf_offset) = " << (*(curParam->param->getAccelInstName()))
1703             << ";\n"
1704             << "  scalar_buf_offset += sizeof("
1705             << curParam->param->getType()->getBaseName() << ");\n";
1706       }
1707       str << "\n";
1708     }
1710     curParam = curParam->next;
1711   }
1713   // Read/write accel params
1714   curParam = accelParam;
1715   while (curParam != NULL) {
1716     // Check to see if the scalar buffer needs slipped into the dma list here
1717     if (accel_numScalars > 0) {
1718       if (((dmaList_curIndex == 0) && (!(accel_dmaList_scalarNeedsWrite))) ||
1719           ((dmaList_curIndex == accel_dmaList_numReadOnly) &&
1720            (accel_dmaList_scalarNeedsWrite))) {
1721         str << "  /*** Scalar Buffer ***/\n"
1722             << "  dmaList[" << dmaList_curIndex << "].size = scalar_buf_len;\n"
1723             << "  dmaList[" << dmaList_curIndex
1724             << "].ea = (unsigned int)(cbStruct->scalar_buf_ptr);\n\n";
1725         dmaList_curIndex++;
1726       }
1727     }
1729     // Add this parameter
1730     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE) {
1731       str << "  /*** Accel Param: '" << curParam->param->getName() << " ("
1732           << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1733       if (curParam->param->isArray()) {
1734         str << "  dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1735             << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1736             << "(" << curParam->param->getArrayLen() << "));\n"
1737             << "  dmaList[" << dmaList_curIndex << "].ea = (unsigned int)("
1738             << (*(curParam->param->getAccelInstName())) << ");\n";
1739         dmaList_curIndex++;
1740       } else {
1741         str << "  *((" << curParam->param->getType()->getBaseName()
1742             << "*)scalar_buf_offset) = " << (*(curParam->param->getAccelInstName()))
1743             << ";\n"
1744             << "  scalar_buf_offset += sizeof("
1745             << curParam->param->getType()->getBaseName() << ");\n";
1746       }
1747       str << "\n";
1748     }
1750     curParam = curParam->next;
1751   }
1753   // Write only accel params
1754   curParam = accelParam;
1755   while (curParam != NULL) {
1756     // Add this parameter
1757     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY) {
1758       str << "  /*** Accel Param: '" << curParam->param->getName() << " ("
1759           << (*(curParam->param->getAccelInstName())) << ")' ***/\n";
1760       if (curParam->param->isArray()) {
1761         str << "  dmaList[" << dmaList_curIndex << "].size = ROUNDUP_128("
1762             << "sizeof(" << curParam->param->getType()->getBaseName() << ") * "
1763             << "(" << curParam->param->getArrayLen() << "));\n"
1764             << "  dmaList[" << dmaList_curIndex << "].ea = (unsigned int)("
1765             << (*(curParam->param->getAccelInstName())) << ");\n";
1766         dmaList_curIndex++;
1767       } else {
1768         str << "  *((" << curParam->param->getType()->getBaseName()
1769             << "*)scalar_buf_offset) = " << (*(curParam->param->getAccelInstName()))
1770             << ";\n"
1771             << "  scalar_buf_offset += sizeof("
1772             << curParam->param->getType()->getBaseName() << ");\n";
1773       }
1774       str << "\n";
1775     }
1777     curParam = curParam->next;
1778   }
1780   str << "  // Issue the work request\n";
1781   str << "  cbStruct->wrHandle = sendWorkRequest_list(accel_spe_func_index__" << epStr()
1782       << ",\n"
1783       << "                                            0,\n"
1784       << "                                            dmaList,\n"
1785       << "                                            " << accel_dmaList_numReadOnly
1786       << ",\n"
1787       << "                                            " << accel_dmaList_numReadWrite
1788       << ",\n"
1789       << "                                            " << accel_dmaList_numWriteOnly
1790       << ",\n"
1791       << "                                            cbStruct,\n"
1792       << "                                            WORK_REQUEST_FLAGS_NONE,\n"
1793       << "                                            _accelCall_spe_callback_"
1794       << container->baseName() << "_" << epStr() << "\n"
1795       << "                                           );\n";
1797   str << "}\n\n";
1799   // Some blank space for readability
1800   str << "\n";
1803 int Entry::genAccels_spe_c_funcBodies(XStr& str) {
1804   // Make sure this is an accelerated entry method (just return if not)
1805   if (!isAccel()) {
1806     return 0;
1807   }
1809   // Declare the spe function
1810   str << "void __speFunc__" << indexName() << "__" << epStr()
1811       << "(DMAListEntry* dmaList) {\n";
1813   ParamList* curParam = NULL;
1814   int dmaList_curIndex = 0;
1816   // Identify the scalar buffer if there is one
1817   if (accel_numScalars > 0) {
1818     if (accel_dmaList_scalarNeedsWrite) {
1819       str << "  void* __scalar_buf_ptr = (void*)(dmaList[" << accel_dmaList_numReadOnly
1820           << "].ea);\n";
1821     } else {
1822       str << "  void* __scalar_buf_ptr = (void*)(dmaList[0].ea);\n";
1823       dmaList_curIndex++;
1824     }
1825     str << "  char* __scalar_buf_offset = (char*)(__scalar_buf_ptr);\n";
1826   }
1828   // Pull out all the parameters
1829   curParam = param;
1830   if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1831     curParam = curParam->next;
1832   }
1833   while (curParam != NULL) {
1834     if (curParam->param->isArray()) {
1835       str << "  " << curParam->param->getType()->getBaseName() << "* "
1836           << curParam->param->getName() << " = ("
1837           << curParam->param->getType()->getBaseName() << "*)(dmaList["
1838           << dmaList_curIndex << "].ea);\n";
1839       dmaList_curIndex++;
1840     } else {
1841       str << "  " << curParam->param->getType()->getBaseName() << " "
1842           << curParam->param->getName() << " = *(("
1843           << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1844       str << "  __scalar_buf_offset += sizeof("
1845           << curParam->param->getType()->getBaseName() << ");\n";
1846     }
1847     curParam = curParam->next;
1848   }
1850   // Read only accel params
1851   curParam = accelParam;
1852   while (curParam != NULL) {
1853     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READONLY) {
1854       if (curParam->param->isArray()) {
1855         str << "  " << curParam->param->getType()->getBaseName() << "* "
1856             << curParam->param->getName() << " = ("
1857             << curParam->param->getType()->getBaseName() << "*)(dmaList["
1858             << dmaList_curIndex << "].ea);\n";
1859         dmaList_curIndex++;
1860       } else {
1861         str << "  " << curParam->param->getType()->getBaseName() << " "
1862             << curParam->param->getName() << " = *(("
1863             << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1864         str << "  __scalar_buf_offset += sizeof("
1865             << curParam->param->getType()->getBaseName() << ");\n";
1866       }
1867     }
1868     curParam = curParam->next;
1869   }
1871   // Reset the dmaList_curIndex to the read-write portion of the dmaList
1872   dmaList_curIndex = accel_dmaList_numReadOnly;
1873   if ((accel_numScalars > 0) && (accel_dmaList_scalarNeedsWrite)) {
1874     dmaList_curIndex++;
1875   }
1877   // Read-write accel params
1878   curParam = accelParam;
1879   while (curParam != NULL) {
1880     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_READWRITE) {
1881       if (curParam->param->isArray()) {
1882         str << "  " << curParam->param->getType()->getBaseName() << "* "
1883             << curParam->param->getName() << " = ("
1884             << curParam->param->getType()->getBaseName() << "*)(dmaList["
1885             << dmaList_curIndex << "].ea);\n";
1886         dmaList_curIndex++;
1887       } else {
1888         str << "  " << curParam->param->getType()->getBaseName() << " "
1889             << curParam->param->getName() << " = *(("
1890             << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1891         str << "  __scalar_buf_offset += sizeof("
1892             << curParam->param->getType()->getBaseName() << ");\n";
1893       }
1894     }
1895     curParam = curParam->next;
1896   }
1898   // Write only accel params
1899   curParam = accelParam;
1900   while (curParam != NULL) {
1901     if (curParam->param->getAccelBufferType() == Parameter::ACCEL_BUFFER_TYPE_WRITEONLY) {
1902       if (curParam->param->isArray()) {
1903         str << "  " << curParam->param->getType()->getBaseName() << "* "
1904             << curParam->param->getName() << " = ("
1905             << curParam->param->getType()->getBaseName() << "*)(dmaList["
1906             << dmaList_curIndex << "].ea);\n";
1907         dmaList_curIndex++;
1908       } else {
1909         str << "  " << curParam->param->getType()->getBaseName() << " "
1910             << curParam->param->getName() << " = *(("
1911             << curParam->param->getType()->getBaseName() << "*)__scalar_buf_offset);\n";
1912         str << "  __scalar_buf_offset += sizeof("
1913             << curParam->param->getType()->getBaseName() << ");\n";
1914       }
1915     }
1916     curParam = curParam->next;
1917   }
1919   // Function body from the interface file
1920   str << "  {\n    " << (*accelCodeBody) << "\n  }\n";
1922   // Write the scalar values that are not read only back into the scalar buffer
1923   if ((accel_numScalars > 0) && (accel_dmaList_scalarNeedsWrite)) {
1924     str << "  __scalar_buf_offset = (char*)(__scalar_buf_ptr);\n";
1926     // Parameters
1927     curParam = param;
1928     if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
1929       curParam = curParam->next;
1930     }
1931     while (curParam != NULL) {
1932       if (!(curParam->param->isArray())) {
1933         str << "  __scalar_buf_offset += sizeof("
1934             << curParam->param->getType()->getBaseName() << ");\n";
1935       }
1936       curParam = curParam->next;
1937     }
1939     // Read only accel parameters
1940     curParam = accelParam;
1941     while (curParam != NULL) {
1942       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1943                                               Parameter::ACCEL_BUFFER_TYPE_READONLY)) {
1944         str << "  __scalar_buf_offset += sizeof("
1945             << curParam->param->getType()->getBaseName() << ");\n";
1946       }
1947       curParam = curParam->next;
1948     }
1950     // Read only accel parameters
1951     curParam = accelParam;
1952     while (curParam != NULL) {
1953       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1954                                               Parameter::ACCEL_BUFFER_TYPE_READWRITE)) {
1955         str << "  *((" << curParam->param->getType()->getBaseName()
1956             << "*)__scalar_buf_offset) = " << curParam->param->getName() << ";\n";
1957         str << "  __scalar_buf_offset += sizeof("
1958             << curParam->param->getType()->getBaseName() << ");\n";
1959       }
1960       curParam = curParam->next;
1961     }
1963     // Read only accel parameters
1964     curParam = accelParam;
1965     while (curParam != NULL) {
1966       if ((!(curParam->param->isArray())) && (curParam->param->getAccelBufferType() ==
1967                                               Parameter::ACCEL_BUFFER_TYPE_WRITEONLY)) {
1968         str << "  *((" << curParam->param->getType()->getBaseName()
1969             << "*)__scalar_buf_offset) = " << curParam->param->getName() << ";\n";
1970         str << "  __scalar_buf_offset += sizeof("
1971             << curParam->param->getType()->getBaseName() << ");\n";
1972       }
1973       curParam = curParam->next;
1974     }
1975   }
1977   str << "}\n\n\n";
1979   return 1;
1982 void Entry::genAccels_spe_c_regFuncs(XStr& str) {
1983   if (isAccel()) {
1984     str << "  funcLookupTable[curIndex  ].funcIndex = curIndex;\n"
1985         << "  funcLookupTable[curIndex++].funcPtr = __speFunc__" << indexName() << "__"
1986         << epStr() << ";\n";
1987   }
1990 void Entry::genAccels_ppe_c_regFuncs(XStr& str) {
1991   if (isAccel()) {
1992     str << "  " << indexName() << "::accel_spe_func_index__" << epStr()
1993         << " = curIndex++;\n";
1994   }
1997 /******************* Shared Entry Point Code **************************/
1998 void Entry::genIndexDecls(XStr& str) {
1999   str << "    /* DECLS: ";
2000   print(str);
2001   str << "     */";
2003   XStr templateSpecLine;
2004   templateSpecLine << "\n    " << generateTemplateSpec(tspec);
2006   // Entry point index storage
2007   str << "\n    // Entry point registration at startup" << templateSpecLine
2008       << "\n    static int reg_" << epStr()
2009       << "();"  ///< @note: Should this be generated as private?
2010       << "\n    // Entry point index lookup" << templateSpecLine
2011       << "\n    inline static int idx_" << epStr() << "() {"
2012       << "\n      static int epidx = " << epRegFn(0) << ";"
2013       << "\n      return epidx;"
2014       << "\n    }\n";
2016   if (!isConstructor()) {
2017     str << templateSpecLine << "\n    inline static int idx_" << name << "(" << retType
2018         << " (" << container->baseName() << "::*)(";
2019     if (param) param->print(str);
2020     str << ") ) {"
2021         << "\n      return " << epIdx(0) << ";"
2022         << "\n    }\n\n";
2023   }
2025 // DMK - Accel Support - Also declare the function index for the Offload API call
2026 #if CMK_CELL != 0
2027   if (isAccel()) {
2028     str << "    static int accel_spe_func_index__" << epStr() << ";\n";
2029   }
2030 #endif
2032   // Index function, so user can find the entry point number
2033   str << templateSpecLine << "\n    static int ";
2034   if (isConstructor())
2035     str << "ckNew";
2036   else
2037     str << name;
2038   str << "(" << paramType(1, 0) << ") { return " << epIdx(0) << "; }";
2040   // DMK - Accel Support
2041   if (isAccel()) {
2042     genAccelIndexWrapperDecl_general(str);
2043 #if CMK_CELL != 0
2044     genAccelIndexWrapperDecl_spe(str);
2045 #endif
2046   }
2048   if (isReductionTarget()) {
2049     str << "\n    // Entry point registration at startup" << templateSpecLine
2050         << "\n    static int reg_" << epStr(true)
2051         << "();"  ///< @note: Should this be generated as private?
2052         << "\n    // Entry point index lookup" << templateSpecLine
2053         << "\n    inline static int idx_" << epStr(true) << "() {"
2054         << "\n      static int epidx = " << epRegFn(0, true) << ";"
2055         << "\n      return epidx;"
2056         << "\n    }" << templateSpecLine << "\n    static int "
2057         << "redn_wrapper_" << name << "(CkReductionMsg* impl_msg) { return "
2058         << epIdx(0, true) << "; }" << templateSpecLine << "\n    static void _call_"
2059         << epStr(true) << "(void* impl_msg, void* impl_obj_void);";
2060   }
2062   // call function declaration
2063   str << templateSpecLine << "\n    static void _call_" << epStr()
2064       << "(void* impl_msg, void* impl_obj);";
2065   str << templateSpecLine << "\n    static void _call_sdag_" << epStr()
2066       << "(void* impl_msg, void* impl_obj);";
2067   if (isThreaded()) {
2068     str << templateSpecLine << "\n    static void _callthr_" << epStr()
2069         << "(CkThrCallArg *);";
2070   }
2071   if (hasCallMarshall) {
2072     str << templateSpecLine << "\n    static int _callmarshall_" << epStr()
2073         << "(char* impl_buf, void* impl_obj_void);";
2074   }
2075   if (param->isMarshalled()) {
2076     str << templateSpecLine << "\n    static void _marshallmessagepup_" << epStr()
2077         << "(PUP::er &p,void *msg);";
2078   }
2079   str << "\n";
2082 void Entry::genDecls(XStr& str) {
2083   if (external) return;
2085   str << "/* DECLS: ";
2086   print(str);
2087   str << " */\n";
2089   if (isMigrationConstructor()) {
2090   }  // User cannot call the migration constructor
2091   else if (container->isGroup()) {
2092     genGroupDecl(str);
2093   } else if (container->isArray()) {
2094     if (!isIget())
2095       genArrayDecl(str);
2096     else if (container->isForElement())
2097       genArrayDecl(str);
2098   } else {  // chare or mainchare
2099     genChareDecl(str);
2100   }
2103 void Entry::genClosureEntryDecls(XStr& str) { genClosure(str, false); }
2105 void Entry::genClosureEntryDefs(XStr& str) {
2106   templateGuardBegin(tspec || container->isTemplated(), str);
2107   genClosure(str, true);
2108   templateGuardEnd(str);
2111 void Entry::genClosure(XStr& decls, bool isDef) {
2112   if (isConstructor() || (isLocal() && !sdagCon)) return;
2114   bool hasArray = false, isMessage = false, hasRdma = false;
2115   XStr messageType;
2116   int i = 0, addNumRdmaFields = 1;
2117   XStr structure, toPup, alloc, getter, dealloc;
2118   for (ParamList *pl = param; pl != NULL; pl = pl->next, i++) {
2119     Parameter* sv = pl->param;
2121     if (XStr(sv->type->getBaseName()) == "CkArrayOptions") continue;
2123     structure << "      ";
2124     getter << "      ";
2126     if ((sv->isMessage() != 1) && (sv->isVoid() != 1)) {
2127       if (sv->isRdma()) {
2128         hasRdma = hasRdma || true;
2129         structure << "\n#if CMK_ONESIDED_IMPL\n";
2130         if (sv->isFirstRdma())
2131           structure << "      "
2132                     << "int num_rdma_fields;\n";
2133         structure << "      "
2134                   << "CkNcpyBuffer "
2135                   << "ncpyBuffer_" << sv->name << ";\n";
2136         structure << "#else\n";
2137         structure << "      " << sv->type << " "
2138                   << "*" << sv->name << ";\n";
2139         structure << "#endif\n";
2140         getter << "#if CMK_ONESIDED_IMPL\n";
2141         if (sv->isFirstRdma()) {
2142           getter << "      "
2143                  << "int "
2144                  << "& "
2145                  << "getP" << i++ << "() { return "
2146                  << " num_rdma_fields;}\n";
2147         }
2148         getter << "      "
2149                << "CkNcpyBuffer "
2150                << "& "
2151                << "getP" << i << "() { return "
2152                << "ncpyBuffer_" << sv->name << ";}\n";
2153         getter << "#else\n";
2154         getter << sv->type << " "
2155                << "*";
2156         getter << "& "
2157                << "getP" << i << "() { return " << sv->name << ";}\n";
2158         getter << "#endif\n";
2159         toPup << "#if CMK_ONESIDED_IMPL\n";
2160         if (sv->isFirstRdma()) {
2161           toPup << "          char *impl_buf = _impl_marshall ? _impl_marshall->msgBuf : "
2162                    "_impl_buf_in;\n";
2163           toPup << "        "
2164                 << "__p | "
2165                 << "num_rdma_fields;\n";
2166         }
2167         /* The Rdmawrapper's pointer stores the offset to the actual buffer
2168          * from the beginning of the msgBuf while packing (as the pointer itself is
2169          * invalid upon migration). During unpacking (after migration), the offset is used
2170          * to adjust the pointer back to the actual buffer that exists within the message.
2171          */
2172         toPup << "        if (__p.isPacking()) {\n";
2173         toPup << "          ncpyBuffer_" << sv->name << ".ptr = ";
2174         toPup << "(void *)((char *)(ncpyBuffer_" << sv->name << ".ptr) - impl_buf);\n";
2175         toPup << "        }\n";
2176         toPup << "        "
2177               << "__p | "
2178               << "ncpyBuffer_" << sv->name << ";\n";
2179         toPup << "#endif\n";
2180       } else {
2181         structure << "      ";
2182         getter << "      ";
2183         structure << sv->type << " ";
2184         getter << sv->type << " ";
2185       }
2187       if (sv->isArray() != 0) {
2188         structure << "*";
2189         getter << "*";
2190       }
2191       if (sv->isArray() != 0) {
2192         hasArray = hasArray || true;
2193       } else if (!sv->isRdma()) {
2194         toPup << "        "
2195               << "__p | " << sv->name << ";\n";
2196         sv->podType = true;
2197       }
2199       if (sv->name != 0) {
2200         if (!sv->isRdma()) {
2201           structure << sv->name << ";\n";
2202           getter << "& "
2203                  << "getP" << i << "() { return " << sv->name << ";}\n";
2204         }
2205       }
2207     } else if (sv->isVoid() != 1) {
2208       if (sv->isMessage()) {
2209         isMessage = true;
2210         if (sv->isRdma()) {
2211           structure << "CkNcpyBuffer"
2212                     << " "
2213                     << "ncpyBuffer_" << sv->name << ";\n";
2214         } else {
2215           structure << sv->type << " " << sv->name << ";\n";
2216         }
2217         toPup << "        "
2218               << "CkPupMessage(__p, (void**)&" << sv->name << ");\n";
2219         messageType << sv->type->deref();
2220       }
2221     }
2222   }
2224   structure << "\n";
2226   toPup << "        packClosure(__p);\n";
2228   XStr initCode;
2229   initCode << "        init();\n";
2231   if (hasArray || hasRdma) {
2232     structure << "      "
2233               << "CkMarshallMsg* _impl_marshall;\n";
2234     structure << "      "
2235               << "char* _impl_buf_in;\n";
2236     structure << "      "
2237               << "int _impl_buf_size;\n";
2238     dealloc << "        if (_impl_marshall) CmiFree(UsrToEnv(_impl_marshall));\n";
2239     initCode << "        _impl_marshall = 0;\n";
2240     initCode << "        _impl_buf_in = 0;\n";
2241     initCode << "        _impl_buf_size = 0;\n";
2243     toPup << "        __p | _impl_buf_size;\n";
2244     toPup << "        bool hasMsg = (_impl_marshall != 0); __p | hasMsg;\n";
2245     toPup << "        "
2246           << "if (hasMsg) CkPupMessage(__p, (void**)&"
2247           << "_impl_marshall"
2248           << ");\n";
2249     toPup << "        "
2250           << "else PUParray(__p, _impl_buf_in, _impl_buf_size);\n";
2251     toPup << "        if (__p.isUnpacking()) {\n";
2252     toPup << "          char *impl_buf = _impl_marshall ? _impl_marshall->msgBuf : "
2253              "_impl_buf_in;\n";
2254     param->beginUnmarshallSDAG(toPup);
2255     toPup << "        }\n";
2256   }
2258   // Generate code for ensuring we don't migrate active local closures
2259   if (isLocal()) {
2260     toPup.clear();
2261     toPup
2262         << "        CkAbort(\"Can\'t migrate while a local SDAG method is active.\");\n";
2263   }
2265   if (!isMessage) {
2266     genClosureTypeName = new XStr();
2267     genClosureTypeNameProxy = new XStr();
2268     *genClosureTypeNameProxy << "Closure_" << container->baseName() << "::";
2269     *genClosureTypeNameProxy << name << "_" << entryCount << "_closure";
2270     *genClosureTypeName << name << "_" << entryCount << "_closure";
2272     container->sdagPUPReg << "  PUPable_reg(SINGLE_ARG(" << *genClosureTypeNameProxy
2273                           << "));\n";
2275     if (isDef) {
2276       if (container->isTemplated()) {
2277         decls << container->tspec(false) << "\n";
2278       }
2279       decls << generateTemplateSpec(tspec) << "\n";
2280       decls << "    struct " << *genClosureTypeNameProxy << " : public SDAG::Closure"
2281             << " {\n";
2282       decls << structure << "\n";
2283       decls << "      " << *genClosureTypeName << "() {\n";
2284       decls << initCode;
2285       decls << "      }\n";
2286       decls << "      " << *genClosureTypeName << "(CkMigrateMessage*) {\n";
2287       decls << initCode;
2288       decls << "      }\n";
2289       decls << getter;
2290       decls << "      void pup(PUP::er& __p) {\n";
2291       decls << toPup;
2292       decls << "      }\n";
2293       decls << "      virtual ~" << *genClosureTypeName << "() {\n";
2294       decls << dealloc;
2295       decls << "      }\n";
2296       decls << "      "
2297             << ((container->isTemplated() || tspec) ? "PUPable_decl_template"
2298                                                     : "PUPable_decl")
2299             << "(SINGLE_ARG(" << *genClosureTypeName;
2300       if (tspec) {
2301         decls << "<";
2302         tspec->genShort(decls);
2303         decls << ">";
2304       }
2305       decls << "));\n";
2306       decls << "    };\n";
2307     } else {
2308       decls << generateTemplateSpec(tspec) << "\n";
2309       decls << "    struct " << *genClosureTypeName << ";\n";
2310     }
2311   } else {
2312     genClosureTypeName = new XStr();
2313     genClosureTypeNameProxy = new XStr();
2314     *genClosureTypeNameProxy << messageType;
2315     *genClosureTypeName << messageType;
2316   }
2318   genClosureTypeNameProxyTemp = new XStr();
2319   *genClosureTypeNameProxyTemp << (container->isTemplated() ? "typename " : "")
2320                                << genClosureTypeNameProxy;
2323 // This routine is only used in Entry::genDefs.
2324 // It ends the current procedure with a call to awaken another thread,
2325 // and defines the thread function to handle that call.
2326 XStr Entry::callThread(const XStr& procName, int prependEntryName) {
2327   if (isConstructor() || isMigrationConstructor())
2328     die("Constructors may not be 'threaded'", first_line_);
2330   XStr str, procFull;
2331   procFull << "_callthr_";
2332   if (prependEntryName) procFull << name << "_";
2333   procFull << procName;
2335   str << "  CthThread tid = CthCreate((CthVoidFn)" << procFull
2336       << ", new CkThrCallArg(impl_msg,impl_obj), " << getStackSize() << ");\n";
2337   str << "  ((Chare *)impl_obj)->CkAddThreadListeners(tid,impl_msg);\n";
2338 // str << "  CkpvAccess(_traces)->CkAddThreadListeners(tid);\n";
2339 #if CMK_BIGSIM_CHARM
2340   str << "  BgAttach(tid);\n";
2341 #endif
2342   str << "  CthResume(tid);\n";
2343   str << "}\n";
2345   str << makeDecl("void") << "::" << procFull << "(CkThrCallArg *impl_arg)\n";
2346   str << "{\n";
2347   str << "  void *impl_msg = impl_arg->msg;\n";
2348   str << "  void *impl_obj_void = impl_arg->obj;\n";
2349   str << "  " << container->baseName() << " *impl_obj = static_cast<"
2350       << container->baseName() << " *>(impl_obj_void);\n";
2351   str << "  delete impl_arg;\n";
2352   return str;
2356   Generate the code to actually unmarshall the parameters and call
2357   the entry method.
2359 void Entry::genCall(XStr& str, const XStr& preCall, bool redn_wrapper, bool usesImplBuf) {
2360   bool isArgcArgv = false;
2361   bool isMigMain = false;
2362   bool isSDAGGen = sdagCon || isWhenEntry;
2363   bool needsClosure = isSDAGGen && (param->isMarshalled() ||
2364                                     (param->isVoid() && isWhenEntry && redn_wrapper));
2366   if (isConstructor() && container->isMainChare() && (!param->isVoid()) &&
2367       (!param->isCkArgMsgPtr())) {
2368     if (param->isCkMigMsgPtr())
2369       isMigMain = true;
2370     else
2371       isArgcArgv = true;
2372   } else {
2373     // Normal case: Unmarshall variables
2374     if (redn_wrapper)
2375       param->beginRednWrapperUnmarshall(str, needsClosure);
2376     else {
2377       if (isSDAGGen)
2378         param->beginUnmarshallSDAGCall(str, usesImplBuf);
2379       else
2380         param->beginUnmarshall(str);
2381     }
2382   }
2384   str << preCall;
2385   if (!isConstructor() && fortranMode && !isWhenEntry && !sdagCon) {
2386     if (!container->isArray()) {  // Currently, only arrays are supported
2387       cerr << (char*)container->baseName()
2388            << ": only chare arrays are currently supported\n";
2389       exit(1);
2390     }
2391     str << "/* FORTRAN */\n";
2392     XStr dim;
2393     dim << ((Array*)container)->dim();
2394     if (dim == (const char*)"1D")
2395       str << "  int index1 = impl_obj->thisIndex;\n";
2396     else if (dim == (const char*)"2D") {
2397       str << "  int index1 = impl_obj->thisIndex.x;\n";
2398       str << "  int index2 = impl_obj->thisIndex.y;\n";
2399     } else if (dim == (const char*)"3D") {
2400       str << "  int index1 = impl_obj->thisIndex.x;\n";
2401       str << "  int index2 = impl_obj->thisIndex.y;\n";
2402       str << "  int index3 = impl_obj->thisIndex.z;\n";
2403     }
2404     str << "  ::";
2405     str << fortranify(container->baseName(), "_Entry_", name);
2406     str << "((char **)(impl_obj->user_data)";
2407     str << ", &index1";
2408     if (dim == (const char*)"2D" || dim == (const char*)"3D") str << ", &index2";
2409     if (dim == (const char*)"3D") str << ", &index3";
2410     if (!param->isVoid()) {
2411       str << ", ";
2412       param->unmarshallAddress(str);
2413     }
2414     str << ");\n";
2415     str << "/* FORTRAN END */\n";
2416   }
2418   // DMK : Accel Support
2419   else if (isAccel()) {
2420 #if CMK_CELL != 0
2421     str << "  if (1) {   // DMK : TODO : For now, hardcode the condition (i.e. for now, "
2422            "do not dynamically load-balance between host and accelerator)\n";
2423     str << "    _accelCall_spe_" << epStr() << "(";
2424     genAccelFullCallList(str);
2425     str << ");\n";
2426     str << "  } else {\n  ";
2427 #endif
2429     str << "  _accelCall_general_" << epStr() << "(";
2430     genAccelFullCallList(str);
2431     str << ");\n";
2433 #if CMK_CELL != 0
2434     str << "  }\n";
2435 #endif
2437   }
2439   else {  // Normal case: call regular method
2440     if (isArgcArgv) str << "  CkArgMsg *m=(CkArgMsg *)impl_msg;\n";  // Hack!
2442     if (isMigrationConstructor() && container->isArray()) {
2443       // Make definition of CkMigrateMessage constructor optional for chare
2444       // array elements, but not for chare/group/nodegroup types that are
2445       // explicitly marked [migratable]
2446       str << "  call_migration_constructor<" << container->baseName()
2447           << "> c = impl_obj_void;\n"
2448           << "  c";
2449     } else if (isConstructor()) {  // Constructor: call "new (obj) foo(parameters)"
2450       str << "  new (impl_obj_void) " << container->baseName();
2451     } else {  // Regular entry method: call "obj->bar(parameters)"
2452       str << "  impl_obj->" << (tspec ? "template " : "") << (containsWhenConstruct ? "_sdag_fnc_" : "" ) << name;
2453       if (tspec) {
2454         str << "<";
2455         tspec->genShort(str);
2456         str << ">";
2457       }
2458     }
2460     if (isArgcArgv) {  // Extract parameters from CkArgMsg (should be parameter
2461                        // marshalled)
2462       str << "(m->argc,m->argv);\n";
2463       str << "  delete m;\n";
2464     } else if (isMigMain) {
2465       str << "((CkMigrateMessage*)impl_msg);\n";
2466     } else {  // Normal case: unmarshall parameters (or just pass message)
2467       if (isSDAGGen) {
2468         str << "(";
2469         if (param->isMessage()) {
2470           param->unmarshall(str);
2471         } else if (needsClosure) {
2472           str << "genClosure";
2473         }
2474         str << ");\n";
2475         if (needsClosure) {
2476           str << "  genClosure->deref();\n";
2477         }
2478       } else {
2479         str << "(";
2480         param->unmarshall(str);
2481         str << ");\n";
2482       }
2483     }
2484   }
2487 void Entry::genDefs(XStr& str) {
2488   if (external) return;
2489   XStr containerType = container->baseName();
2490   XStr preMarshall, preCall, postCall;
2492   templateGuardBegin(tspec || container->isTemplated(), str);
2493   str << "/* DEFS: ";
2494   print(str);
2495   str << " */\n";
2497   if (isMigrationConstructor()) {
2498   }  // User cannot call the migration constructor
2499   else if (isTramTarget() && container->isForElement()) {
2500     genTramDefs(str);
2501   } else if (container->isGroup()) {
2502     genGroupDefs(str);
2503   } else if (container->isArray()) {
2504     genArrayDefs(str);
2505   } else
2506     genChareDefs(str);
2508   if (!isConstructor() && fortranMode) {
2509     str << "/* FORTRAN SECTION */\n";
2511     // Declare the Fortran Entry Function
2512     // This is called from C++
2513     str << "extern \"C\" ";
2514     str << "void ";
2515     str << fortranify(container->baseName(), "_Entry_", name);
2516     str << "(char **";
2517     str << ", " << container->indexList();
2518     if (!param->isVoid()) {
2519       str << ", ";
2520       param->printAddress(str);
2521     }
2522     str << ");\n";
2524     str << "/* FORTRAN SECTION END */\n";
2525   }
2527   if (container->isMainChare() || container->isChare() || container->isForElement()) {
2528     if (isReductionTarget()) {
2529       XStr retStr;
2530       retStr << retType;
2531       str << makeDecl(retStr);
2532       // str << retType << " " << indexName(); //makeDecl(retStr, 1)
2533       str << "::_call_" << epStr(true) << "(void* impl_msg, void* impl_obj_void)"
2534           << "\n{"
2535           << "\n  " << container->baseName() << "* impl_obj = static_cast<"
2536           << container->baseName() << "*> (impl_obj_void);\n"
2537           << "  char* impl_buf = (char*)((CkReductionMsg*)impl_msg)->getData();\n";
2538       XStr precall;
2539       genCall(str, precall, true, false);
2540       if (!(sdagCon || isWhenEntry))
2541         str << "  delete (CkReductionMsg*)impl_msg;\n}\n\n";
2542       else
2543         str << "  \n}\n\n";
2544     }
2545   }
2547   // Prevents repeated call and __idx definitions:
2548   if (container->getForWhom() != forAll) {
2549     templateGuardEnd(str);
2550     return;
2551   }
2553   // Define the entry point registration functions
2554   str << "\n// Entry point registration function"
2555       << "\n"
2556       << makeDecl("int") << "::reg_" << epStr() << "() {"
2557       << "\n  int epidx = " << genRegEp() << ";";
2558   if (hasCallMarshall)
2559     str << "\n  CkRegisterMarshallUnpackFn(epidx, "
2560         << "_callmarshall_" << epStr(false, true) << ");";
2561   if (param->isMarshalled()) {
2562     str << "\n  CkRegisterMessagePupFn(epidx, "
2563         << "_marshallmessagepup_" << epStr(false, true) << ");\n";
2564   } else if (param->isMessage() && !isMigrationConstructor()) {
2565     str << "\n  CkRegisterMessagePupFn(epidx, (CkMessagePupFn)";
2566     param->param->getType()->deref()->print(str);
2567     str << "::ckDebugPup);";
2568   }
2569   str << "\n  return epidx;"
2570       << "\n}\n\n";
2572   if (isReductionTarget()) {
2573     str << "\n// Redn wrapper registration function"
2574         << "\n"
2575         << makeDecl("int") << "::reg_" << epStr(true) << "() {"
2576         << "\n  return " << genRegEp(true) << ";"
2577         << "\n}\n\n";
2578   }
2580 // DMK - Accel Support
2581 #if CMK_CELL != 0
2582   if (isAccel()) {
2583     str << "int " << indexName() << "::"
2584         << "accel_spe_func_index__" << epStr() << "=0;\n";
2585   }
2586 #endif
2588   // Add special pre- and post- call code
2589   if (isSync() || isIget()) {
2590     // A synchronous method can return a value, and must finish before
2591     // the caller can proceed.
2592     preMarshall
2593         << "  int impl_ref = CkGetRefNum(impl_msg), impl_src = CkGetSrcPe(impl_msg);\n";
2594     if (retType->isVoid() || retType->isMessage()) preCall << "  void *impl_retMsg=";
2595     if (retType->isVoid()) {
2596       preCall << "CkAllocSysMsg();\n  ";
2597     } else if (retType->isMessage()) {
2598       preCall << "(void *) ";
2599     } else {
2600       preCall << "  " << retType << " impl_ret_val= ";
2601       postCall << "  //Marshall: impl_ret_val\n";
2602       postCall << "  int impl_ret_size=0;\n";
2603       postCall << "  { //Find the size of the PUP'd data\n";
2604       postCall << "    PUP::sizer implPS;\n";
2605       postCall << "    implPS|impl_ret_val;\n";
2606       postCall << "    impl_ret_size+=implPS.size();\n";
2607       postCall << "  };\n";
2608       postCall
2609           << "  CkMarshallMsg *impl_retMsg=CkAllocateMarshallMsg(impl_ret_size, NULL);\n";
2610       postCall << "  { //Copy over the PUP'd data;\n";
2611       postCall << "    PUP::toMem implPS((void *)impl_retMsg->msgBuf);\n";
2612       postCall << "    implPS|impl_ret_val;\n";
2613       postCall << "  };\n";
2614     }
2615     postCall << "  CkSendToFutureID(impl_ref, impl_retMsg, impl_src);\n";
2616   } else if (isExclusive()) {
2617     // An exclusive method
2618     preMarshall
2619         << "  if(CmiTryLock(impl_obj->__nodelock)) {\n"; /*Resend msg. if lock busy*/
2620     /******* DANGER-- RESEND CODE UNTESTED **********/
2621     if (param->isMarshalled()) {
2622       preMarshall << "    impl_msg = CkCopyMsg(&impl_msg);\n";
2623     }
2624     preMarshall << "    CkSendMsgNodeBranch(" << epIdx()
2625                 << ",impl_msg,CkMyNode(),impl_obj->CkGetNodeGroupID());\n";
2626     preMarshall << "    return;\n";
2627     preMarshall << "  }\n";
2629     postCall << "  CmiUnlock(impl_obj->__nodelock);\n";
2630   }
2632   if (param->isVoid() && !isNoKeep()) {
2633     /* Reuse the message using CkFreeSysMsg by putting it in the msgpool if it is a fixed
2634      * sized message. The message is a fixed sized message if it has no priority bytes. A
2635      * message with priority bytes will not be reused and will be deallocated similar to
2636      * other marshalled messages.
2637      */
2638     postCall << "  if(UsrToEnv(impl_msg)->isVarSysMsg() == 0)\n";
2639     postCall << "    CkFreeSysMsg(impl_msg);\n";
2640   }
2642   if (!isConstructor() && fortranMode) {  // Fortran90
2643     str << "/* FORTRAN SECTION */\n";
2645     XStr dim;
2646     dim << ((Array*)container)->dim();
2648     // Define the Fortran interface function
2649     // This is called from Fortran to send the message to a chare.
2650     str << "extern \"C\" ";
2651     str << "void ";
2652     str << fortranify(container->baseName(), "_Invoke_", name);
2653     str << "(void** aindex";
2654     str << ", " << container->indexList();
2655     if (!param->isVoid()) {
2656       str << ", ";
2657       param->printAddress(str);
2658     }
2659     str << ")\n";
2660     str << "{\n";
2661     str << "  CkArrayID *aid = (CkArrayID *)*aindex;\n";
2662     str << "\n";
2663     str << "  " << container->proxyName() << " h(*aid);\n";
2664     if (dim == (const char*)"1D")
2665       str << "  h[*index1]." << name << "(";
2666     else if (dim == (const char*)"2D")
2667       str << "  h[CkArrayIndex2D(*index1, *index2)]." << name << "(";
2668     else if (dim == (const char*)"3D")
2669       str << "  h[CkArrayIndex3D(*index1, *index2, *index3)]." << name << "(";
2670     if (!param->isVoid()) param->printValue(str);
2671     str << ");\n";
2672     str << "}\n";
2674     if (container->isArray()) {
2675       str << "extern \"C\" ";
2676       str << "void ";
2677       str << fortranify(container->baseName(), "_Broadcast_", name);
2678       str << "(void** aindex";
2679       if (!param->isVoid()) {
2680         str << ", ";
2681         param->printAddress(str);
2682       }
2683       str << ")\n";
2684       str << "{\n";
2685       str << "  CkArrayID *aid = (CkArrayID *)*aindex;\n";
2686       str << "\n";
2687       str << "  " << container->proxyName() << " h(*aid);\n";
2688         str << "  h." << name << "(";
2689       if (!param->isVoid()) param->printValue(str);
2690       str << ");\n";
2691       str << "}\n";
2692     }
2694     if (isReductionTarget()) {
2695       str << "extern \"C\" ";
2696       str << "int ";
2697       str << fortranify(container->baseName(), "_ReductionTarget_", name);
2698       str << "(void)\n";
2699       str << "{\n";
2700       str << "  return CkReductionTarget(" << container->baseName() << ", " << name << ");\n";
2701       str << "}\n";
2702     }
2704     str << "/* FORTRAN SECTION END */\n";
2705   }
2707   // DMK - Accel Support
2708   //   Create the wrapper function for the acceleration call
2709   //   TODO : FIXME : For now, just use the standard C++ code... create OffloadAPI
2710   //   wrappers later
2711   if (isAccel()) {
2712     genAccelIndexWrapperDef_general(str);
2713 #if CMK_CELL != 0
2714     genAccelIndexWrapperDef_spe(str);
2715 #endif
2716   }
2718   // Generate the call-method body
2719   str << makeDecl("void") << "::_call_" << epStr()
2720       << "(void* impl_msg, void* impl_obj_void)\n";
2721   str << "{\n";
2722   // Do not create impl_obj for migration constructor as compiler throws an unused
2723   // variable warning otherwise
2724   if (!isMigrationConstructor()) {
2725     str << "  " << container->baseName() << "* impl_obj = static_cast<"
2726         << container->baseName() << "*>(impl_obj_void);\n";
2727   }
2728   if (!isLocal()) {
2729     if (isThreaded()) str << callThread(epStr());
2730     str << preMarshall;
2731     if (param->isMarshalled()) {
2732       if (param->hasConditional())
2733         str << "  MarshallMsg_" << epStr() << " *impl_msg_typed=(MarshallMsg_" << epStr()
2734             << " *)impl_msg;\n";
2735       else
2736         str << "  CkMarshallMsg *impl_msg_typed=(CkMarshallMsg *)impl_msg;\n";
2737       str << "  char *impl_buf=impl_msg_typed->msgBuf;\n";
2738     }
2739     genCall(str, preCall, false, false);
2740     param->endUnmarshall(str);
2741     str << postCall;
2742     if (isThreaded() && param->isMarshalled()) str << "  delete impl_msg_typed;\n";
2743   } else {
2744     str << "  CkAbort(\"This method should never be called as it refers to a LOCAL entry "
2745            "method!\");\n";
2746   }
2747   str << "}\n";
2749   if (hasCallMarshall) {
2750     str << makeDecl("int") << "::_callmarshall_" << epStr()
2751         << "(char* impl_buf, void* impl_obj_void) {\n";
2752     str << "  " << containerType << "* impl_obj = static_cast<" << containerType
2753         << "*>(impl_obj_void);\n";
2754     if (!isLocal()) {
2755       if (!param->hasConditional()) {
2756         genCall(str, preCall, false, true);
2757         /*FIXME: implP.size() is wrong if the parameter list contains arrays--
2758         need to add in the size of the arrays.
2759          */
2760         str << "  return implP.size();\n";
2761       } else {
2762         str << "  CkAbort(\"This method is not implemented for EPs using conditional "
2763                "packing\");\n";
2764         str << "  return 0;\n";
2765       }
2766     } else {
2767       str << "  CkAbort(\"This method should never be called as it refers to a LOCAL "
2768              "entry method!\");\n";
2769       str << "  return 0;\n";
2770     }
2771     str << "}\n";
2772   }
2773   if (param->isMarshalled()) {
2774     str << makeDecl("void") << "::_marshallmessagepup_" << epStr()
2775         << "(PUP::er &implDestP,void *impl_msg) {\n";
2776     if (!isLocal()) {
2777       if (param->hasConditional())
2778         str << "  MarshallMsg_" << epStr() << " *impl_msg_typed=(MarshallMsg_" << epStr()
2779             << " *)impl_msg;\n";
2780       else
2781         str << "  CkMarshallMsg *impl_msg_typed=(CkMarshallMsg *)impl_msg;\n";
2782       str << "  char *impl_buf=impl_msg_typed->msgBuf;\n";
2783       param->beginUnmarshall(str);
2784       param->pupAllValues(str);
2785     } else {
2786       str << "  /*Fake pupping since we don't really have a message */\n";
2787       str << "  int n=0;\n";
2788       str << "  if (implDestP.hasComments()) implDestP.comment(\"LOCAL message\");\n";
2789       str << "  implDestP|n;\n";
2790     }
2791     str << "}\n";
2792   }
2794   // to match the registry, generate register call even if there is no SDAG code
2795   // if ((param->isMarshalled() || param->isVoid()) /* && (sdagCon || isWhenEntry) */)
2796   if ((param->isMarshalled() || param->isVoid()) && genClosureTypeNameProxy) {
2797     if (container->isTemplated()) str << container->tspec(false);
2798     if (tspec) {
2799       str << "template <";
2800       tspec->genLong(str, false);
2801       str << "> ";
2802     }
2804     str << ((container->isTemplated() || tspec) ? "PUPable_def_template_nonInst"
2805                                                 : "PUPable_def")
2806         << "(SINGLE_ARG(" << *genClosureTypeNameProxy;
2807     if (tspec) {
2808       str << "<";
2809       tspec->genShort(str);
2810       str << ">";
2811     }
2812     str << "))\n";
2813   }
2815   templateGuardEnd(str);
2818 XStr Entry::genRegEp(bool isForRedn) {
2819   XStr str;
2820   str << "CkRegisterEp";
2821   if (tspec) {
2822     str << "<";
2823     tspec->genShort(str);
2824     str << ">";
2825   }
2826   str << "(\"";
2827   if (isForRedn)
2828     str << "redn_wrapper_" << name << "(CkReductionMsg *impl_msg)\",\n";
2829   else
2830     str << name << "(" << paramType(0) << ")\",\n";
2831   str << "      _call_" << epStr(isForRedn, true);
2832   str << ", ";
2833   /* messageIdx: */
2834   if (param->isMarshalled()) {
2835     if (param->hasConditional())
2836       str << "MarshallMsg_" << epStr() << "::__idx";
2837     else
2838       str << "CkMarshallMsg::__idx";
2839   } else if (!param->isVoid() && !isMigrationConstructor()) {
2840     param->genMsgProxyName(str);
2841     str << "::__idx";
2842   } else if (isForRedn) {
2843     str << "CMessage_CkReductionMsg::__idx";
2844   } else {
2845     str << "0";
2846   }
2847   /* chareIdx */
2848   str << ", __idx";
2849   /* attributes */
2850   str << ", 0";
2851   // reductiontarget variants should not be nokeep. The actual ep will be
2852   // parameter marshalled (and hence flagged as nokeep), but we'll delete the
2853   // CkReductionMsg in generated code, not runtime code. (so that we can cast
2854   // it to CkReductionMsg not CkMarshallMsg)
2855   if (!isForRedn && (attribs & SNOKEEP)) str << "+CK_EP_NOKEEP";
2856   if (attribs & SNOTRACE) str << "+CK_EP_TRACEDISABLE";
2857   if (attribs & SIMMEDIATE) {
2858      str << "+CK_EP_TRACEDISABLE";
2859      str << "+CK_EP_IMMEDIATE";
2860   }
2861   if (attribs & SAPPWORK) str << "+CK_EP_APPWORK";
2863   /*MEICHAO*/
2864   if (attribs & SMEM) str << "+CK_EP_MEMCRITICAL";
2866   if (internalMode) str << "+CK_EP_INTRINSIC";
2867   str << ")";
2868   return str;
2871 void Entry::genReg(XStr& str) {
2872   if (tspec) return;
2874   if (external) {
2875     str << "  CkIndex_" << label << "::idx_" << name;
2876     if (targs) str << "<" << targs << ">";
2877     str << "( static_cast<" << retType << " (" << label << "::*)(" << paramType(0, 0)
2878         << ")>(NULL) );\n";
2879     return;
2880   }
2882   str << "  // REG: " << *this;
2883   str << "  " << epIdx(0) << ";\n";
2884   if (isReductionTarget()) str << "  " << epIdx(0, true) << ";\n";
2885   if (isConstructor()) {
2886     if (container->isMainChare() && !isMigrationConstructor())
2887       str << "  CkRegisterMainChare(__idx, " << epIdx(0) << ");\n";
2888     if (param->isVoid()) str << "  CkRegisterDefaultCtor(__idx, " << epIdx(0) << ");\n";
2889     if (isMigrationConstructor())
2890       str << "  CkRegisterMigCtor(__idx, " << epIdx(0) << ");\n";
2891   }
2894 void Entry::preprocess() {
2895   ParamList* pl = param;
2896   if (pl != NULL && pl->hasConditional()) {
2897     XStr str;
2898     str << "MarshallMsg_" << epStr();
2899     NamedType* nt = new NamedType(strdup(str));
2900     MsgVar* var = new MsgVar(new BuiltinType("char"), "msgBuf", 0, 1);
2901     MsgVarList* list = new MsgVarList(var);
2902     do {
2903       if (pl->param->isConditional()) {
2904         var = new MsgVar(pl->param->getType(), pl->param->getName(), 1, 0);
2905         list = new MsgVarList(var, list);
2906       }
2907     } while (NULL != (pl = pl->next));
2908     Message* m = new Message(-1, nt, list);
2909     m->setModule(container->containerModule);
2910     container->containerModule->prependConstruct(m);
2911   }
2913   // DMK - Accel Support
2914   // Count the total number of scalar and array parameters if this is an accelerated entry
2915   accel_numScalars = 0;
2916   accel_numArrays = 0;
2917   accel_dmaList_numReadOnly = 0;
2918   accel_dmaList_numReadWrite = 0;
2919   accel_dmaList_numWriteOnly = 0;
2920   accel_dmaList_scalarNeedsWrite = 0;
2921   if (isAccel()) {
2922     ParamList* curParam = param;
2923     if ((curParam->param->getType()->isVoid()) && (curParam->param->getName() == NULL)) {
2924       curParam = curParam->next;
2925     }
2926     while (curParam != NULL) {
2927       if (curParam->param->isArray()) {
2928         accel_numArrays++;
2929         accel_dmaList_numReadOnly++;
2930       } else {
2931         accel_numScalars++;
2932       }
2933       curParam = curParam->next;
2934     }
2935     curParam = accelParam;
2936     while (curParam != NULL) {
2937       if (curParam->param->isArray()) {
2938         accel_numArrays++;
2939         switch (curParam->param->getAccelBufferType()) {
2940           case Parameter::ACCEL_BUFFER_TYPE_READWRITE:
2941             accel_dmaList_numReadWrite++;
2942             break;
2943           case Parameter::ACCEL_BUFFER_TYPE_READONLY:
2944             accel_dmaList_numReadOnly++;
2945             break;
2946           case Parameter::ACCEL_BUFFER_TYPE_WRITEONLY:
2947             accel_dmaList_numWriteOnly++;
2948             break;
2949           default:
2950             XLAT_ERROR_NOCOL("unknown accel param type", first_line_);
2951             break;
2952         }
2953       } else {
2954         accel_numScalars++;
2955         switch (curParam->param->getAccelBufferType()) {
2956           case Parameter::ACCEL_BUFFER_TYPE_READWRITE:
2957             accel_dmaList_scalarNeedsWrite++;
2958             break;
2959           case Parameter::ACCEL_BUFFER_TYPE_READONLY:
2960             break;
2961           case Parameter::ACCEL_BUFFER_TYPE_WRITEONLY:
2962             accel_dmaList_scalarNeedsWrite++;
2963             break;
2964           default:
2965             XLAT_ERROR_NOCOL("unknown accel param type", first_line_);
2966             break;
2967         }
2968       }
2969       curParam = curParam->next;
2970     }
2971     if (accel_numScalars > 0) {
2972       if (accel_dmaList_scalarNeedsWrite) {
2973         accel_dmaList_numReadWrite++;
2974       } else {
2975         accel_dmaList_numReadOnly++;
2976       }
2977     }
2978   }
2981 int Entry::paramIsMarshalled(void) { return param->isMarshalled(); }
2983 int Entry::getStackSize(void) { return (stacksize ? stacksize->getIntVal() : 0); }
2985 void Entry::setAccelParam(ParamList* apl) { accelParam = apl; }
2986 void Entry::setAccelCodeBody(XStr* acb) { accelCodeBody = acb; }
2987 void Entry::setAccelCallbackName(XStr* acbn) { accelCallbackName = acbn; }
2989 int Entry::isThreaded(void) { return (attribs & STHREADED); }
2990 int Entry::isSync(void) { return (attribs & SSYNC); }
2991 int Entry::isIget(void) { return (attribs & SIGET); }
2992 int Entry::isConstructor(void) {
2993   return !strcmp(name, container->baseName(0).get_string());
2995 bool Entry::isMigrationConstructor() { return isConstructor() && (attribs & SMIGRATE); }
2996 int Entry::isExclusive(void) { return (attribs & SLOCKED); }
2997 int Entry::isImmediate(void) { return (attribs & SIMMEDIATE); }
2998 int Entry::isSkipscheduler(void) { return (attribs & SSKIPSCHED); }
2999 int Entry::isInline(void) { return attribs & SINLINE; }
3000 int Entry::isLocal(void) { return attribs & SLOCAL; }
3001 int Entry::isCreate(void) { return (attribs & SCREATEHERE) || (attribs & SCREATEHOME); }
3002 int Entry::isCreateHome(void) { return (attribs & SCREATEHOME); }
3003 int Entry::isCreateHere(void) { return (attribs & SCREATEHERE); }
3004 int Entry::isPython(void) { return (attribs & SPYTHON); }
3005 int Entry::isNoTrace(void) { return (attribs & SNOTRACE); }
3006 int Entry::isAppWork(void) { return (attribs & SAPPWORK); }
3007 int Entry::isNoKeep(void) { return (attribs & SNOKEEP); }
3008 int Entry::isSdag(void) { return (sdagCon != 0); }
3009 bool Entry::isTramTarget(void) { return (attribs & SAGGREGATE) != 0; }
3011 // DMK - Accel support
3012 int Entry::isAccel(void) { return (attribs & SACCEL); }
3014 int Entry::isMemCritical(void) { return (attribs & SMEM); }
3015 int Entry::isReductionTarget(void) { return (attribs & SREDUCE); }
3017 char* Entry::getEntryName() { return name; }
3018 int Entry::getLine() { return line; }
3020 }  // namespace xi