Cleanup #1489: Delete GPU dummy mempool
[charm.git] / src / xlat-i / xi-Parameter.C
blob109a94679fbe2c0e997138048ecc638bcd2b9732
1 #include "xi-Entry.h"
2 #include "xi-Parameter.h"
3 #include "xi-Type.h"
4 #include "xi-Value.h"
6 namespace xi {
8 /******************* C/C++ Parameter Marshalling ******************
9 For entry methods like:
10         entry void foo(int nx,double xarr[nx],complex<float> yarr[ny],long ny);
12 We generate code on the call-side (in the proxy entry method) to
13 create a message and copy the user's parameters into it.  Scalar
14 fields are PUP'd, arrays are just memcpy'd.
16 The message looks like this:
18 messagestart>--------- PUP'd data ----------------
19         |  PUP'd nx
20         |  PUP'd offset-to-xarr (from array start, int byte count)
21         |  PUP'd length-of-xarr (in elements)
22         |  PUP'd offset-to-yarr
23         |  PUP'd length-of-yarr (in elements)
24         |  PUP'd ny
25         +-------------------------------------------
26         |  alignment gap (to multiple of 16 bytes)
27 arraystart>------- xarr data ----------
28         | xarr[0]
29         | xarr[1]
30         | ...
31         | xarr[nx-1]
32         +------------------------------
33         |  alignment gap (for yarr-elements)
34         +--------- yarr data ----------
35         | yarr[0]
36         | yarr[1]
37         | ...
38         | yarr[ny-1]
39         +------------------------------
41 On the recieve side, all the scalar fields are PUP'd to fresh
42 stack copies, and the arrays are passed to the user as pointers
43 into the message data-- so there's no copy on the receive side.
45 The message is freed after the user entry returns.
47 Parameter::Parameter(int Nline, Type* Ntype, const char* Nname, const char* NarrLen,
48                      Value* Nvalue)
49     : type(Ntype),
50       name(Nname),
51       arrLen(NarrLen),
52       val(Nvalue),
53       line(Nline),
54       byConst(false),
55       conditional(0),
56       given_name(Nname),
57       podType(false),
58       rdma(false) {
59   if (isMessage()) {
60     name = "impl_msg";
61   }
62   if (name == NULL && !isVoid()) { /*Fabricate a unique name for this marshalled param.*/
63     static int unnamedCount = 0;
64     name = new char[50];
65     sprintf((char*)name, "impl_noname_%x", unnamedCount++);
66   }
67   byReference = false;
68   declaredReference = false;
69   if ((arrLen == NULL) && (val == NULL)) { /* Consider passing type by reference: */
70     if (type->isNamed()) {                 /* Some user-defined type: pass by reference */
71       byReference = true;
72     }
73     if (type->isReference()) {
74       byReference = true;
75       declaredReference = true;
76       /* Clip off the ampersand--we'll add
77          it back ourselves in Parameter::print. */
78       type = type->deref();
79     }
80     if (type->isConst()) {
81       byConst = true;
82       type = type->deref();
83     }
84   }
87 ParamList::ParamList(ParamList* pl)
88     : manyPointers(false), param(pl->param), next(pl->next) {}
90 int ParamList::print(XStr& str, int withDefaultValues, int useConst, int fwdNum) {
91   fwdNum = param->print(str, withDefaultValues, useConst, fwdNum);
92   if (next) {
93     str << ", ";
94     fwdNum = next->print(str, withDefaultValues, useConst, fwdNum);
95   }
96   return fwdNum;
99 void ParamList::printTypes(XStr& str, int withDefaultValues, int useConst) {
100   XStr typeStr;
101   param->getType()->print(typeStr);
102   str << typeStr;
103   if (next) {
104     str << ", ";
105     next->printTypes(str, withDefaultValues, useConst);
106   }
109 int Parameter::print(XStr& str, int withDefaultValues, int useConst, int fwdNum) {
110   if (isRdma()) {
111     str << "CkRdmaWrapper rdmawrapper_" << name;
112   } else if (arrLen != NULL) {  // Passing arrays by const pointer-reference
113     if (useConst) str << "const ";
114     str << type << " *";
115     if (name != NULL) str << name;
116   } else {
117     if (conditional) {
118       str << type << " *" << name;
119     } else if (byReference) {  // Pass named types by const C++ reference
120       if (fwdNum) {
121         str << "Fwd" << fwdNum++ << " &&";
122       } else {
123         if (useConst || byConst) str << "const ";
124         str << type << " &";
125       }
126       if (name != NULL) str << name;
127     } else {  // Pass everything else by value
128               // @TODO uncommenting this requires that PUP work on const types
129               // if (byConst) str << "const ";
130       //"void" shouldn't be typed in the param list
131       // to have CkEntryOptions as the last argument
132       if (!type->isVoid()) str << type;
133       if (name != NULL) str << " " << name;
134       if (withDefaultValues && val != NULL) {
135         str << " = ";
136         val->print(str);
137       }
138     }
139   }
140   return fwdNum;
143 void ParamList::printAddress(XStr& str) {
144   param->printAddress(str);
145   if (next) {
146     str << ", ";
147     next->printAddress(str);
148   }
151 void Parameter::printAddress(XStr& str) {
152   type->print(str);
153   str << "*";
154   if (name != NULL) str << " " << name;
157 void ParamList::printValue(XStr& str) {
158   param->printValue(str);
159   if (next) {
160     str << ", ";
161     next->printValue(str);
162   }
165 void Parameter::printValue(XStr& str) {
166   if (arrLen == NULL) str << "*";
167   if (name != NULL) str << name;
170 int ParamList::orEach(pred_t f) {
171   ParamList* cur = this;
172   int ret = 0;
173   do {
174     ret |= ((cur->param)->*f)();
175   } while (NULL != (cur = cur->next));
176   return ret;
179 void ParamList::callEach(fn_t f, XStr& str) {
180   ParamList* cur = this;
181   do {
182     ((cur->param)->*f)(str);
183   } while (NULL != (cur = cur->next));
186 void ParamList::callEach(rdmafn_t f, XStr& str, bool isArray) {
187   ParamList* cur = this;
188   do {
189     ((cur->param)->*f)(str, isArray);
190   } while (NULL != (cur = cur->next));
193 int ParamList::hasConditional() { return orEach(&Parameter::isConditional); }
195 /** marshalling: pack fields into flat byte buffer **/
196 void ParamList::marshall(XStr& str, XStr& entry) {
197   if (isVoid())
198     str << "  void *impl_msg = CkAllocSysMsg(impl_e_opts);\n";
199   else if (isMarshalled()) {
200     str << "  //Marshall: ";
201     print(str, 0);
202     str << "\n";
203     // First pass: find sizes
204     str << "  int impl_off=0;\n";
205     int hasArrays = orEach(&Parameter::isArray);
206     if (hasArrays) {
207       str << "  int impl_arrstart=0;\n";
208       callEach(&Parameter::marshallRegArraySizes, str);
209     }
210     bool hasrdma = hasRdma();
211     if (hasrdma) {
212       str << "#if CMK_ONESIDED_IMPL\n";
213       str << "  int impl_num_rdma_fields = 0; \n";
214       callEach(&Parameter::marshallRdmaParameters, str, true);
215       str << "#else\n";
216       if (!hasArrays) str << "  int impl_arrstart=0;\n";
217       callEach(&Parameter::marshallRdmaParameters, str, false);
218       str << "#endif\n";
219     }
220     str << "  { //Find the size of the PUP'd data\n";
221     str << "    PUP::sizer implP;\n";
222     callEach(&Parameter::pup, str);
223     if (hasrdma) {
224       str << "#if CMK_ONESIDED_IMPL\n";
225       str << "    implP|impl_num_rdma_fields;\n";
226       // All rdma parameters have to be pupped at the start
227       callEach(&Parameter::pupRdma, str, true);
228       str << "#else\n";
229       callEach(&Parameter::pupRdma, str, false);
230       if (!hasArrays) {
231         str << "    impl_arrstart=CK_ALIGN(implP.size(),16);\n";
232         str << "    impl_off+=impl_arrstart;\n";
233       }
234       str << "#endif\n";
235     }
236     if (hasArrays) { /*round up pup'd data length--that's the first array*/
237       str << "    impl_arrstart=CK_ALIGN(implP.size(),16);\n";
238       str << "    impl_off+=impl_arrstart;\n";
239     } else /*No arrays--no padding*/
240       str << "    impl_off+=implP.size();\n";
241     str << "  }\n";
242     // Now that we know the size, allocate the packing buffer
243     if (hasConditional())
244       str << "  MarshallMsg_" << entry << " *impl_msg=CkAllocateMarshallMsgT<MarshallMsg_"
245           << entry << ">(impl_off,impl_e_opts);\n";
246     else
247       str << "  CkMarshallMsg *impl_msg=CkAllocateMarshallMsg(impl_off,impl_e_opts);\n";
248     // Second pass: write the data
249     str << "  { //Copy over the PUP'd data\n";
250     str << "    PUP::toMem implP((void *)impl_msg->msgBuf);\n";
251     if (hasRdma()) {
252       str << "#if CMK_ONESIDED_IMPL\n";
253       str << "    implP|impl_num_rdma_fields;\n";
254       callEach(&Parameter::pupRdma, str, true);
255       str << "#else\n";
256       callEach(&Parameter::pupRdma, str, false);
257       str << "#endif\n";
258     }
259     callEach(&Parameter::pup, str);
260     callEach(&Parameter::copyPtr, str);
261     str << "  }\n";
262     if (hasArrays) {  // Marshall each array
263       str << "  char *impl_buf=impl_msg->msgBuf+impl_arrstart;\n";
264       callEach(&Parameter::marshallArrayData, str);
265     }
266     if (hasrdma) {
267       str << "#if CMK_ONESIDED_IMPL\n";
268       str << "  UsrToEnv(impl_msg)->setRdma(true);\n";
269       str << "#else\n";
270       if (!hasArrays) str << "  char *impl_buf=impl_msg->msgBuf+impl_arrstart;\n";
271       callEach(&Parameter::marshallRdmaArrayData, str);
272       str << "#endif\n";
273     }
274   }
277 void Parameter::check() {
278   Type* dt = type->deref();
279   checkPointer(dt);
282 void Parameter::checkPointer(Type* dt) {
283   if (dt->isPointer())
284     XLAT_ERROR_NOCOL(
285         "can't pass pointers across processors--\n"
286         "Indicate the array length with []'s, or pass a reference",
287         line);
290 void Parameter::marshallArraySizes(XStr& str, Type* dt) {
291   str << "  int impl_off_" << name << ", impl_cnt_" << name << ";\n";
292   str << "  impl_off_" << name << "=impl_off=CK_ALIGN(impl_off,sizeof(" << dt << "));\n";
293   str << "  impl_off+=(impl_cnt_" << name << "=sizeof(" << dt << ")*(" << arrLen
294       << "));\n";
297 void Parameter::marshallRegArraySizes(XStr& str) {
298   Type* dt = type->deref();
299   if (isArray()) marshallArraySizes(str, dt);
302 void Parameter::marshallRdmaParameters(XStr& str, bool genRdma) {
303   if (isRdma()) {
304     Type* dt = type->deref();  // Type, without &
305     if (genRdma) {
306       str << "  impl_num_rdma_fields++;\n";
307       str << "  rdmawrapper_" << name << ".cnt=sizeof(" << dt << ")*(" << arrLen
308           << ");\n";
309     } else {
310       marshallArraySizes(str, dt);
311     }
312   }
315 void Parameter::pupRdma(XStr& str, bool genRdma) {
316   if (isRdma()) {
317     if (genRdma)
318       str << "    implP|rdmawrapper_" << name << ";\n";
319     else
320       pupArray(str);
321   }
324 void Parameter::pupArray(XStr& str) {
325   str << "    implP|impl_off_" << name << ";\n";
326   str << "    implP|impl_cnt_" << name << ";\n";
329 void Parameter::pup(XStr& str) {
330   if (isArray()) {
331     pupArray(str);
332   } else if (!conditional) {
333     if (byReference) {
334       str << "    //Have to cast away const-ness to get pup routine\n";
335       str << "    implP|(typename std::remove_cv<typename std::remove_reference<" << type << ">::type>::type &)" << name << ";\n";
336     } else if (!isRdma())
337       str << "    implP|" << name << ";\n";
338   }
341 void Parameter::marshallRdmaArrayData(XStr& str) {
342   if (isRdma()) {
343     str << "  memcpy(impl_buf+impl_off_" << name << ","
344         << "rdmawrapper_" << name << ".ptr"
345         << ",impl_cnt_" << name << ");\n";
346     str << "  rdmawrapper_" << name << ".callback->send("
347         << "sizeof(void *)"
348         << ","
349         << "&rdmawrapper_" << name << ".ptr"
350         << ");\n";
351     str << "  free(rdmawrapper_" << name << ".callback);\n";
352   }
355 void Parameter::marshallArrayData(XStr& str) {
356   if (isArray())
357     str << "  memcpy(impl_buf+impl_off_" << name << "," << name << ",impl_cnt_" << name
358         << ");\n";
361 void Parameter::copyPtr(XStr& str) {
362   if (isConditional()) {
363     str << "    impl_msg->" << name << "=" << name << ";\n";
364   }
367 void ParamList::beginRednWrapperUnmarshall(XStr& str, bool needsClosure) {
368   if (needsClosure) {
369     str << *entry->genClosureTypeNameProxyTemp << "*"
370         << " genClosure = new " << *entry->genClosureTypeNameProxyTemp << "()"
371         << ";\n";
372   }
374   if (isMarshalled()) {
375     str << "  /*Unmarshall pup'd fields: ";
376     print(str, 0);
377     str << "*/\n";
378     str << "  PUP::fromMem implP(impl_buf);\n";
379     if (next != NULL && next->next == NULL) {
380       // 2 argument case - special cases for an array and its length, in either order
381       if (isArray() && !next->isArray()) {
382         if (!needsClosure) {
383           Type* dtLen = next->param->type->deref();
384           str << "  PUP::detail::TemporaryObjectHolder<" << dtLen << "> "
385               << next->param->name << "; " << next->param->name << ".t = "
386               << "((CkReductionMsg*)impl_msg)->getLength() / sizeof("
387               << param->type->deref() << ");\n";
388           Type* dt = param->type->deref();
389           str << "  " << dt << "* " << param->name << "; " << param->name << " = (" << dt
390               << "*)impl_buf;\n";
391         } else {
392           str << "  genClosure->" << next->param->name << " = "
393               << "((CkReductionMsg*)impl_msg)->getLength() / sizeof("
394               << param->type->deref() << ");\n";
395           Type* dt = param->type->deref();
396           str << "  genClosure->" << param->name << " = (" << dt << "*)impl_buf;\n";
397         }
398       } else if (!isArray() && next->isArray()) {
399         if (!needsClosure) {
400           Type* dt = param->type->deref();
401           str << "  PUP::detail::TemporaryObjectHolder<" << dt << "> " << param->name
402               << "; " << param->name << ".t = "
403               << "((CkReductionMsg*)impl_msg)->getLength() / sizeof("
404               << next->param->type->deref() << ");\n";
405           dt = next->param->type->deref();
406           str << "  " << dt << "* " << next->param->name << "; " << next->param->name
407               << " = (" << dt << "*)impl_buf;\n";
408         } else {
409           str << "  genClosure->" << param->name << " = "
410               << "((CkReductionMsg*)impl_msg)->getLength() / sizeof("
411               << next->param->type->deref() << ");\n";
412           Type* dt = next->param->type->deref();
413           str << "  genClosure->" << next->param->name << " = (" << dt << "*)impl_buf;\n";
414         }
415       } else {
416         if (!needsClosure) {
417           if (hasRdma()) {
418             str << "#if CMK_ONESIDED_IMPL\n";
419             str << "  CkUnpackRdmaPtrs(impl_buf);\n";
420             str << "  int impl_num_rdma_fields; implP|impl_num_rdma_fields;\n";
421             callEach(&Parameter::beginUnmarshallRdma, str, true);
422             str << "#else\n";
423             callEach(&Parameter::beginUnmarshallRdma, str, false);
424             str << "#endif\n";
425           }
426           callEach(&Parameter::beginUnmarshall, str);
427         } else {
428           if (hasRdma()) {
429             str << "#if CMK_ONESIDED_IMPL\n";
430             str << "  CkUnpackRdmaPtrs(impl_buf);\n";
431             callEach(&Parameter::beginUnmarshallSDAGCallRdma, str, true);
432             str << "#else\n";
433             callEach(&Parameter::beginUnmarshallSDAGCallRdma, str, false);
434             str << "#endif\n";
435           }
436           callEach(&Parameter::beginUnmarshallSDAGCall, str);
437         }
438       }
439     } else if (next == NULL && isArray()) {
440       // 1 argument case - special case for a standalone array
441       Type* dt = param->type->deref();
442       if (!needsClosure) {
443         str << "  " << dt << "* " << param->name << "; " << param->name << " = (" << dt
444             << "*)impl_buf;\n";
445       } else {
446         str << "  genClosure->" << param->name << " = (" << dt << "*)impl_buf;\n";
447       }
448     } else {
449       str << "  /* non two-param case */\n";
450       if (!needsClosure) {
451         if (hasRdma()) {
452           str << "#if CMK_ONESIDED_IMPL\n";
453           str << "  CkUnpackRdmaPtrs(impl_buf);\n";
454           str << "  int impl_num_rdma_fields; implP|impl_num_rdma_fields;\n";
455           callEach(&Parameter::beginUnmarshallRdma, str, true);
456           str << "#else\n";
457           callEach(&Parameter::beginUnmarshallRdma, str, false);
458           str << "#endif\n";
459         }
460         callEach(&Parameter::beginUnmarshall, str);
461       } else
462         callEach(&Parameter::beginUnmarshallSDAGCall, str);
463       str << "  impl_buf+=CK_ALIGN(implP.size(),16);\n";
464       str << "  /*Unmarshall arrays:*/\n";
465       if (!needsClosure)
466         callEach(&Parameter::unmarshallRegArrayData, str);
467       else
468         callEach(&Parameter::unmarshallRegArrayDataSDAGCall, str);
469     }
470   }
471   if (needsClosure) {
472     str << "  genClosure->setRefnum(CkGetRefNum((CkReductionMsg*)impl_msg));\n";
473   }
476 /** unmarshalling: unpack fields from flat buffer **/
477 void ParamList::beginUnmarshall(XStr& str) {
478   if (isMarshalled()) {
479     str << "  /*Unmarshall pup'd fields: ";
480     print(str, 0);
481     str << "*/\n";
482     str << "  PUP::fromMem implP(impl_buf);\n";
483     if (hasRdma()) {
484       str << "#if CMK_ONESIDED_IMPL\n";
485       str << "  CkUnpackRdmaPtrs(impl_buf);\n";
486       str << "  int impl_num_rdma_fields; implP|impl_num_rdma_fields; \n";
487       callEach(&Parameter::beginUnmarshallRdma, str, true);
488       str << "#else\n";
489       callEach(&Parameter::beginUnmarshallRdma, str, false);
490       str << "#endif\n";
491     }
492     callEach(&Parameter::beginUnmarshall, str);
493     str << "  impl_buf+=CK_ALIGN(implP.size(),16);\n";
494     str << "  /*Unmarshall arrays:*/\n";
495     callEach(&Parameter::unmarshallRegArrayData, str);
496     if (hasRdma()) {
497       str << "#if !CMK_ONESIDED_IMPL\n";
498       callEach(&Parameter::unmarshallRdmaArrayData, str, true);
499       str << "#endif\n";
500     }
501   }
504 void Parameter::beginUnmarshallArray(XStr& str) {
505   str << "  int impl_off_" << name << ", impl_cnt_" << name << ";\n";
506   str << "  implP|impl_off_" << name << ";\n";
507   str << "  implP|impl_cnt_" << name << ";\n";
510 void Parameter::beginUnmarshallRdma(XStr& str,
511                                     bool genRdma) {  // First pass: unpack pup'd entries
512   Type* dt = type->deref();                          // Type, without &
513   if (isRdma()) {
514     if (genRdma) {
515       str << "  CkRdmaWrapper rdmawrapper_" << name << ";\n";
516       str << "  implP|rdmawrapper_" << name << ";\n";
517     } else
518       beginUnmarshallArray(str);
519   }
522 void Parameter::beginUnmarshall(XStr& str) {  // First pass: unpack pup'd entries
523   Type* dt = type->deref();                   // Type, without &
524   if (isArray())
525     beginUnmarshallArray(str);
526   else if (isConditional())
527     str << "  " << dt << " *" << name << "=impl_msg_typed->" << name << ";\n";
528   else if (!isRdma())
529     str << "  PUP::detail::TemporaryObjectHolder<" << dt << "> " << name << ";\n"
530         << "  "
531         << "implP|" << name << ";\n";
534 void Parameter::beginUnmarshallSDAGCallRdma(XStr& str, bool genRdma) {
535   if (isRdma()) {
536     if (genRdma) {
537       if (isFirstRdma()) {
538         str << "  implP|genClosure->num_rdma_fields;\n";
539       }
540       str << "  implP|genClosure->rdmawrapper_" << name << ";\n";
541     } else {
542       beginUnmarshallArray(str);
543     }
544   }
547 void Parameter::beginUnmarshallSDAGCall(XStr& str) {
548   Type* dt = type->deref();
549   if (isArray()) {
550     beginUnmarshallArray(str);
551   } else if (isRdma()) {
552     // unmarshalled before regular parameters
553   } else {
554     str << "  implP|" << (podType ? "" : "*") << "genClosure->" << name << ";\n";
555   }
558 /** unmarshalling: unpack fields from flat buffer **/
559 void ParamList::beginUnmarshallSDAGCall(XStr& str, bool usesImplBuf) {
560   bool hasArray = false;
561   for (ParamList* pl = this; pl != NULL; pl = pl->next) {
562     hasArray = hasArray || pl->param->isArray();
563   }
565   if (isMarshalled()) {
566     str << "  PUP::fromMem implP(impl_buf);\n";
567     str << "  " << *entry->genClosureTypeNameProxyTemp << "*"
568         << " genClosure = new " << *entry->genClosureTypeNameProxyTemp << "()"
569         << ";\n";
570     if (hasRdma()) {
571       str << "#if CMK_ONESIDED_IMPL\n";
572       str << "  CkUnpackRdmaPtrs(impl_buf);\n";
573       callEach(&Parameter::beginUnmarshallSDAGCallRdma, str, true);
574       str << "#else\n";
575       callEach(&Parameter::beginUnmarshallSDAGCallRdma, str, false);
576       str << "#endif\n";
577     }
578     callEach(&Parameter::beginUnmarshallSDAGCall, str);
579     str << "  impl_buf+=CK_ALIGN(implP.size(),16);\n";
580     if (hasRdma()) str << "#if !CMK_ONESIDED_IMPL\n";
581     callEach(&Parameter::unmarshallRdmaArrayDataSDAGCall, str);
582     if (hasRdma()) str << "#endif\n";
583     callEach(&Parameter::unmarshallRegArrayDataSDAGCall, str);
584     if (hasArray || hasRdma()) {
585       if (!usesImplBuf) {
586         str << "  genClosure->_impl_marshall = impl_msg_typed;\n";
587         str << "  CmiReference(UsrToEnv(genClosure->_impl_marshall));\n";
588       } else {
589         if (hasRdma() && !hasArray) str << "#if !CMK_ONESIDED_IMPL\n";
590         str << "  genClosure->_impl_buf_in = impl_buf;\n";
591         str << "  genClosure->_impl_buf_size = implP.size();\n";
592         if (hasRdma() && !hasArray) str << "#endif\n";
593       }
594     }
595   }
597 void ParamList::beginUnmarshallSDAG(XStr& str) {
598   if (isMarshalled()) {
599     str << "          PUP::fromMem implP(impl_buf);\n";
600     if (hasRdma()) {
601       str << "#if CMK_ONESIDED_IMPL\n";
602       /* Before migration of the closure structure, Rdmawrapper pointers
603        * store the offset to the actual buffer from the msgBuf
604        * After migration, the Rdmawrapper pointer needs to be adjusted
605        * to point to the msgBuf + offset. As the actual buffer is within
606        * the message, the adjusting should happen after the message is
607        * unpacked. (see code in Entry::genClosure)
608        */
609       callEach(&Parameter::adjustUnmarshalledRdmaPtrsSDAG, str);
610       str << "  implP|num_rdma_fields;\n";
611       callEach(&Parameter::beginUnmarshallRdma, str, true);
612       str << "#else\n";
613       callEach(&Parameter::beginUnmarshallRdma, str, false);
614       str << "#endif\n";
615     }
616     callEach(&Parameter::beginUnmarshall, str);
617     str << "          impl_buf+=CK_ALIGN(implP.size(),16);\n";
618     // If there's no rdma support, unmarshall as a regular array
619     str << "#if !CMK_ONESIDED_IMPL\n";
620     callEach(&Parameter::unmarshallRdmaArrayDataSDAG, str);
621     str << "#endif\n";
622     callEach(&Parameter::unmarshallRegArrayDataSDAG, str);
623   }
626 void Parameter::unmarshallRegArrayDataSDAG(XStr& str) {
627   if (isArray()) {
628     Type* dt = type->deref();  // Type, without &
629     str << "          " << name << " = (" << dt << " *)(impl_buf+impl_off_" << name
630         << ");\n";
631   }
634 void Parameter::adjustUnmarshalledRdmaPtrsSDAG(XStr& str) {
635   if (isRdma()) {
636     str << "  rdmawrapper_" << name << ".ptr = ";
637     str << "(void *)(impl_buf + (size_t)(rdmawrapper_" << name << ".ptr));\n";
638   }
641 void Parameter::unmarshallRdmaArrayDataSDAG(XStr& str) {
642   if (isRdma()) {
643     Type* dt = type->deref();  // Type, without &
644     str << "          " << name << " = (" << dt << " *)(impl_buf+impl_off_" << name
645         << ");\n";
646   }
649 void Parameter::unmarshallRegArrayDataSDAGCall(XStr& str) {
650   if (isArray()) {
651     Type* dt = type->deref();  // Type, without &
652     str << "  genClosure->" << name << " = (" << dt << " *)(impl_buf+impl_off_" << name
653         << ");\n";
654   }
657 void Parameter::unmarshallRdmaArrayDataSDAGCall(XStr& str) {
658   if (isRdma()) {
659     Type* dt = type->deref();  // Type, without &
660     str << "  genClosure->" << name << " = (" << dt << " *)(impl_buf+impl_off_" << name
661         << ");\n";
662   }
665 void ParamList::unmarshallSDAGCall(XStr& str, int isFirst) {
666   if (isFirst && isMessage())
667     str << "(" << param->type << ")impl_msg";
668   else if (!isVoid()) {
669     str << "genClosure->";
670     str << param->getName();
671     if (next) {
672       str << ", ";
673       next->unmarshallSDAGCall(str, 0);
674     }
675   }
678 void Parameter::unmarshallArrayData(XStr& str) {
679   Type* dt = type->deref();  // Type, without &
680   str << "  " << dt << " *" << name << "=(" << dt << " *)(impl_buf+impl_off_" << name
681       << ");\n";
684 void Parameter::unmarshallRdmaArrayData(XStr& str, bool genRegArray) {
685   if (isRdma() && genRegArray) unmarshallArrayData(str);
688 void Parameter::unmarshallRegArrayData(
689     XStr& str) {  // Second pass: unpack pointed-to arrays
690   if (isArray()) unmarshallArrayData(str);
693 void ParamList::unmarshall(XStr& str, bool isInline, bool isFirst)  // Pass-by-value
695   if (isFirst && isMessage())
696     str << "(" << param->type << ")impl_msg";
697   else if (!isVoid()) {
698     if (param->isRdma()) {
699       str << "\n#if CMK_ONESIDED_IMPL\n";
700       str << "(" << (param->getType())->deref() << " *)";
701       str << "rdmawrapper_" << param->getName() << ".ptr";
702       str << "\n#else\n";
703       str << param->getName();
704       str << "\n#endif\n";
705     } else if (param->isArray() || isInline) {
706       str << param->getName();
707     } else {
708       str << "std::move(" << param->getName() << ".t)";
709     }
711     if (next) {
712       str << ", ";
713       next->unmarshall(str, isInline, false);
714     }
715   }
718 // Do forwarding for rvalue references, used for inline and local entry methods
719 void ParamList::unmarshallForward(XStr& str,
720                                   bool isInline,
721                                   bool isFirst,
722                                   int fwdNum)
724   if (!isInline)
725     unmarshall(str, isInline, isFirst);
726   if (isReference()) {
727     str << "std::forward<Fwd" << fwdNum++ << ">(" << param->getName() << ")";
728     if (next) {
729       str << ", ";
730       next->unmarshallForward(str, isInline, false, fwdNum);
731     }
732   } else {
733     unmarshall(str, isInline, isFirst);
734   }
737 void ParamList::unmarshallAddress(XStr& str,
738                                   int isFirst)  // Pass-by-reference, for Fortran
740   if (isFirst && isMessage())
741     str << "(" << param->type << ")impl_msg";
742   else if (!isVoid()) {
743     //@TODO : Case for RDMA
744     if (param->isArray())
745       str << param->getName();  // Arrays are already pointers
746     else
747       str << "& " << param->getName() << ".t";  // Take address of simple types and structs
748     if (next) {
749       str << ", ";
750       next->unmarshallAddress(str, 0);
751     }
752   }
755 void ParamList::pupAllValues(XStr& str) {
756   if (isMarshalled()) callEach(&Parameter::pupAllValues, str);
759 void Parameter::pupAllValues(XStr& str) {
760   str << "  if (implDestP.hasComments()) implDestP.comment(\"" << name << "\");\n";
761   if (isArray()) {
762     str << "  implDestP.synchronize(PUP::sync_begin_array);\n"
763            "  for (int impl_i=0;impl_i*(sizeof(*"
764         << name << "))<impl_cnt_" << name
765         << ";impl_i++) {\n"
766            "    implDestP.synchronize(PUP::sync_item);\n"
767            "    implDestP|"
768         << name
769         << "[impl_i];\n"
770            "  }\n"
771            "  implDestP.synchronize(PUP::sync_end_array);\n";
772   } else if (isRdma()) {
773     str << "#if CMK_ONESIDED_IMPL\n";
774     str << "  implDestP|rdmawrapper_" << name << ";\n";
775     str << "#else\n";
776     str << "  implDestP.synchronize(PUP::sync_begin_array);\n"
777            "  { for (int impl_i=0;impl_i*(sizeof(*"
778         << name << "))<impl_cnt_" << name
779         << ";impl_i++) { \n"
780            "      implDestP.synchronize(PUP::sync_item);\n"
781            "      implDestP|"
782         << name
783         << "[impl_i];\n"
784            "  } } \n"
785            "  implDestP.synchronize(PUP::sync_end_array);\n";
786     str << "#endif\n";
787   } else /* not an array */ {
788     if (isConditional())
789       str << "  pup_pointer(&implDestP, (void**)&" << name << ");\n";
790     else
791       str << "  implDestP|" << name << ";\n";
792   }
795 void ParamList::endUnmarshall(XStr&) {
796   /* Marshalled entry points now have the "SNOKEEP" attribute...
797   if (isMarshalled()) {
798           str<<"  delete (CkMarshallMsg *)impl_msg;\n";
799   }
800   */
803 void ParamList::printMsg(XStr& str) {
804   ParamList* pl;
805   param->printMsg(str);
806   pl = next;
807   while (pl != NULL) {
808     str << ", ";
809     pl->param->printMsg(str);
810     pl = pl->next;
811   }
814 void Parameter::printMsg(XStr& str) {
815   type->print(str);
816   if (given_name != 0) str << given_name;
819 int Parameter::isMessage(void) const { return type->isMessage(); }
820 int Parameter::isVoid(void) const { return type->isVoid(); }
821 int Parameter::isCkArgMsgPtr(void) const { return type->isCkArgMsgPtr(); }
822 int Parameter::isCkMigMsgPtr(void) const { return type->isCkMigMsgPtr(); }
823 int Parameter::isArray(void) const { return (arrLen != NULL && !isRdma()); }
824 int Parameter::isConditional(void) const { return conditional; }
825 int Parameter::isRdma(void) const { return rdma; }
826 int Parameter::isFirstRdma(void) const { return firstRdma; }
828 int Parameter::operator==(const Parameter& parm) const { return *type == *parm.type; }
830 void Parameter::setConditional(int c) {
831   conditional = c;
832   if (c) byReference = false;
835 void Parameter::setRdma(bool r) { rdma = r; }
837 void Parameter::setFirstRdma(bool fr) { firstRdma = fr; }
839 void Parameter::setAccelBufferType(int abt) {
840   accelBufferType = ((abt < ACCEL_BUFFER_TYPE_MIN || abt > ACCEL_BUFFER_TYPE_MAX)
841                          ? (ACCEL_BUFFER_TYPE_UNKNOWN)
842                          : (abt));
845 int Parameter::getAccelBufferType() { return accelBufferType; }
846 void Parameter::setAccelInstName(XStr* ain) { accelInstName = ain; }
847 XStr* Parameter::getAccelInstName(void) { return accelInstName; }
849 ParamList::ParamList(Parameter* Nparam, ParamList* Nnext) : param(Nparam), next(Nnext) {
850   manyPointers = false;
851   if (next != NULL && (param->isMessage() || next->isMessage())) {
852     manyPointers = true;
853   }
856 int ParamList::isNamed(void) const { return param->type->isNamed(); }
857 int ParamList::isBuiltin(void) const { return param->type->isBuiltin(); }
858 int ParamList::isMessage(void) const { return (next == NULL) && param->isMessage(); }
859 int ParamList::hasRdma(void) { return orEach(&Parameter::isRdma); }
860 int ParamList::isRdma(void) { return param->isRdma(); }
861 int ParamList::isFirstRdma(void) { return param->isFirstRdma(); }
862 const char* ParamList::getArrayLen(void) const { return param->getArrayLen(); }
863 int ParamList::isArray(void) const { return param->isArray(); }
864 int ParamList::isReference(void) const {
865   return param->type->isReference() || param->byReference;
867 int ParamList::declaredReference(void) const {
868   return param->type->isReference() || param->declaredReference;
870 bool ParamList::isConst(void) const { return param->type->isConst() || param->byConst; }
871 int ParamList::isVoid(void) const { return (next == NULL) && param->isVoid(); }
872 int ParamList::isPointer(void) const { return param->type->isPointer(); }
873 const char* ParamList::getGivenName(void) const { return param->getGivenName(); }
874 void ParamList::setGivenName(const char* s) { param->setGivenName(s); }
875 const char* ParamList::getName(void) const { return param->getName(); }
876 int ParamList::isMarshalled(void) const { return !isVoid() && !isMessage(); }
877 int ParamList::isCkArgMsgPtr(void) const {
878   return (next == NULL) && param->isCkArgMsgPtr();
880 int ParamList::isCkMigMsgPtr(void) const {
881   return (next == NULL) && param->isCkMigMsgPtr();
883 int ParamList::getNumStars(void) const { return param->type->getNumStars(); }
884 const char* ParamList::getBaseName(void) { return param->type->getBaseName(); }
885 void ParamList::genMsgProxyName(XStr& str) { param->type->genMsgProxyName(str); }
887 void ParamList::checkParamList() {
888   if (manyPointers) {
889     XLAT_ERROR_NOCOL(
890         "multiple pointers passed to a non-local entry method\n"
891         "You may pass only a single pointer to it, which should point to a message.",
892         param->line);
893   }
896 int ParamList::operator==(ParamList& plist) {
897   if (!(*param == *(plist.param))) return 0;
898   if (!next && !plist.next) return 1;
899   if (!next || !plist.next) return 0;
900   return *next == *plist.next;
903 }  // namespace xi