Merge nodehelper lib and example codes into charm
[charm.git] / src / xlat-i / xi-symbol.C
1 #include <list>
2 using std::list;
3 #include <algorithm>
4 using std::for_each;
5 #include <stdlib.h>
6 #include "xi-symbol.h"
7 #include <ctype.h> // for tolower()
8 #include <iostream>
9 using std::cerr;
10 using std::cout;
11 using std::endl;
12
13 #if ! CMK_BOOL_DEFINED
14 typedef enum {false = 0, true = 1} bool;
15 #endif
16
17 #include <fstream>
18
19 namespace xi {
20    
21 int fortranMode;
22 int internalMode;
23 const char *cur_file;
24 const char *python_doc;
25
26 const char *Prefix::Proxy="CProxy_";
27 const char *Prefix::ProxyElement="CProxyElement_";
28 const char *Prefix::ProxySection="CProxySection_";
29 const char *Prefix::Message="CMessage_";
30 const char *Prefix::Index="CkIndex_";
31 const char *Prefix::Python="CkPython_";
32
33
34 //Fatal error function
35 void die(const char *why,int line)
36 {
37         if (line==-1)
38                 fprintf(stderr,"%s: Charmxi fatal error> %s\n",cur_file,why);
39         else
40                 fprintf(stderr,"%s:%d: Charmxi fatal error> %s\n",cur_file,line,why);
41         exit(1);
42 }
43
44 // Make the name lower case
45 char* fortranify(const char *s, const char *suff1="", const char *suff2="", const char *suff3="")
46 {
47   int i, len1 = strlen(s), len2 = strlen(suff1),
48          len3 = strlen(suff2), len4 = strlen(suff3);
49   int c = len1+len2+len3+len4;
50   char str[1024], strUpper[1024];
51   strcpy(str, s);
52   strcat(str, suff1);
53   strcat(str, suff2);
54   strcat(str, suff3);
55   for(i = 0; i < c+1; i++)
56     str[i] = tolower(str[i]);
57   for(i = 0; i < c+1; i++)
58     strUpper[i] = toupper(str[i]);
59   char *retVal;
60   retVal = new char[2*c+20];
61   strcpy(retVal, "FTN_NAME(");
62   strcat(retVal, strUpper);
63   strcat(retVal, ",");
64   strcat(retVal, str);
65   strcat(retVal, ")");
66
67   return retVal;
68 }
69
70 void templateGuardBegin(bool templateOnly, XStr &str) {
71   if (templateOnly)
72     str << "#ifdef " << "CK_TEMPLATES_ONLY\n";
73   else
74     str << "#ifndef " << "CK_TEMPLATES_ONLY\n";
75 }
76 void templateGuardEnd(XStr &str) {
77   str << "#endif /* CK_TEMPLATES_ONLY */\n";
78 }
79
80 Value::Value(const char *s)
81 {
82   factor = 1;
83   val=s;
84   if(val == 0 || strlen(val)==0 ) return;
85   char *v = (char *)malloc(strlen(val)+5);
86   strcpy(v,val);
87   int pos = strlen(v)-1;
88   if(v[pos]=='K' || v[pos]=='k') {
89     v[pos] = '\0';
90     factor = 1024;
91   }
92   if(v[pos]=='M' || v[pos]=='m') {
93     v[pos] = '\0';
94     factor = 1024*1024;
95   }
96   val=v;
97 }
98
99
100 int
101 Value::getIntVal(void)
102 {
103   if(val==0 || strlen(val)==0) return 0;
104   return (atoi((const char *)val)*factor);
105 }
106
107
108 /**
109    Apply fn_ on each Construct in the list l, passing it arg as
110    the target. If between_ is passed, do that to arg between each
111    element.
112  */
113 template<typename T, typename U, typename A>
114 class perElemGenC
115 {
116     void (U::*fn)(A);
117     void (*between)(A);
118     A arg;
119 public:
120     perElemGenC(list<T*> &l,
121                A arg_,
122                void (U::*fn_)(A),
123                void (*between_)(A) = NULL)
124         : fn(fn_), between(between_), arg(arg_)
125         {
126             for_each(l.begin(), l.end(), *this);
127         }
128     void operator()(T* m)
129         {
130             if (m)
131             {
132                 (m->*fn)(arg);
133                 if (between)
134                     between(arg);
135             }
136         }
137 };
138
139 template<typename T, typename U, typename A>
140 void perElemGen(list<T*> &l, A& arg_, void (U::*fn_)(A&),
141 // Sun Studio 7 (C++ compiler version 5.4) can't handle this
142 //              void (*between_)(A&) = NULL)
143                 void (*between_)(A&))
144 {
145     perElemGenC<T, U, A&>(l, arg_, fn_, between_);
146 }
147
148 template<typename T, typename U, typename A>
149 void perElemGen(list<T*> &l, A& arg_, void (U::*fn_)(A&))
150 {
151     perElemGenC<T, U, A&>(l, arg_, fn_, NULL);
152 }
153
154 template<typename T, typename U, typename A>
155 void perElemGen(list<T*> &l, A* arg_, void (U::*fn_)(A*),
156 // See above
157 //              void (*between_)(A*) = NULL)
158                 void (*between_)(A*))
159 {
160     perElemGenC<T, U, A*>(l, arg_, fn_, between_);
161 }
162
163 template<typename T, typename U, typename A>
164 void perElemGen(list<T*> &l, A* arg_, void (U::*fn_)(A*))
165 {
166     perElemGenC<T, U, A*>(l, arg_, fn_, NULL);
167 }
168
169 void newLine(XStr &str)
170 {
171     str << endx;
172 }
173
174 ConstructList::ConstructList(int l, Construct *c, ConstructList *n)
175 {
176     constructs.push_back(c);
177     if (n)
178         constructs.insert(constructs.end(),
179                           n->constructs.begin(), n->constructs.end());
180     line = l;
181 }
182
183 void
184 ConstructList::setExtern(int e)
185 {
186   Construct::setExtern(e);
187   perElemGen(constructs, e, &Construct::setExtern);
188 }
189
190 void
191 ConstructList::setModule(Module *m)
192 {
193   Construct::setModule(m);
194   perElemGen(constructs, m, &Construct::setModule);
195 }
196
197 void
198 ConstructList::print(XStr& str)
199 {
200     perElemGen(constructs, str, &Construct::print);
201 }
202
203 int ConstructList::genAccels_spe_c_funcBodies(XStr& str) {
204     int rtn = 0;
205     for (list<Construct *>::iterator i = constructs.begin();
206          i != constructs.end(); ++i)
207         if (*i) rtn += (*i)->genAccels_spe_c_funcBodies(str);
208     return rtn;
209 }
210 void ConstructList::genAccels_spe_c_regFuncs(XStr& str) {
211     perElemGen(constructs, str, &Construct::genAccels_spe_c_regFuncs);
212 }
213 void ConstructList::genAccels_spe_c_callInits(XStr& str) {
214     perElemGen(constructs, str, &Construct::genAccels_spe_c_callInits);
215 }
216 void ConstructList::genAccels_spe_h_includes(XStr& str) {
217     perElemGen(constructs, str, &Construct::genAccels_spe_h_includes);
218 }
219 void ConstructList::genAccels_spe_h_fiCountDefs(XStr& str) {
220     perElemGen(constructs, str, &Construct::genAccels_spe_h_fiCountDefs);
221 }
222 void ConstructList::genAccels_ppe_c_regFuncs(XStr& str) {
223     perElemGen(constructs, str, &Construct::genAccels_ppe_c_regFuncs);
224 }
225
226
227 void
228 TParamList::print(XStr& str)
229 {
230   tparam->print(str);
231   if(next) {
232     str << ",";
233     next->print(str);
234   }
235 }
236
237 std::string TParamList::to_string()
238 {
239     XStr s;
240     print(s);
241     return s.get_string();
242 }
243
244
245 void
246 Type::genProxyName(XStr &str,forWhom forElement)
247 {
248   (void)str; (void)forElement;
249   die("type::genProxyName called (INTERNAL ERROR)");
250 }
251 void
252 Type::genIndexName(XStr &str)
253 {
254   (void)str;
255   die("type::genIndexName called (INTERNAL ERROR)");
256 }
257 void
258 Type::genMsgProxyName(XStr &str)
259 {
260   (void)str;
261   die("type::genMsgProxyName called (INTERNAL ERROR)");
262 }
263
264 void
265 NamedType::print(XStr& str)
266 {
267   if (scope) str << scope;
268   str << name;
269   if (tparams) str << "<"<<tparams<<" >";
270 }
271
272 void NamedType::genIndexName(XStr& str) { 
273     if (scope) str << scope;
274     str << Prefix::Index; 
275     str << name;
276     if (tparams) str << "<"<<tparams<<" >";
277 }
278
279 void NamedType::genMsgProxyName(XStr& str) { 
280     if (scope) str << scope;
281     str << Prefix::Message;
282     str << name;
283     if (tparams) str << "<"<<tparams<<" >";
284 }
285
286 void
287 PtrType::print(XStr& str)
288 {
289   type->print(str);
290   for(int i=0;i<numstars;i++)
291     str << "*";
292 }
293
294 void
295 TypeList::print(XStr& str)
296 {
297   type->print(str);
298   if(next) {
299     str << ", ";
300     next->print(str);
301   }
302 }
303
304 int TypeList::length(void) const
305 {
306   if (next) return next->length()+1;
307   else return 1;
308 }
309
310 MemberList::MemberList(Member *m, MemberList *n)
311 {
312     members.push_back(m);
313     if (n)
314         members.insert(members.end(), n->members.begin(), n->members.end());
315 }
316
317
318 void
319 MemberList::print(XStr& str)
320 {
321     perElemGen(members, str, &Member::print);
322 }
323
324 void
325 MemberList::appendMember(Member *m)
326 {
327     members.push_back(m);
328 }
329
330 int MemberList::genAccels_spe_c_funcBodies(XStr& str) {
331     int rtn = 0;
332     for (list<Member*>::iterator i = members.begin(); i != members.end(); ++i)
333         if (*i)
334             rtn += (*i)->genAccels_spe_c_funcBodies(str);
335     return rtn;
336 }
337 void MemberList::genAccels_spe_c_regFuncs(XStr& str) {
338     perElemGen(members, str, &Member::genAccels_spe_c_regFuncs);
339 }
340 void MemberList::genAccels_spe_c_callInits(XStr& str) {
341     perElemGen(members, str, &Member::genAccels_spe_c_callInits);
342 }
343 void MemberList::genAccels_spe_h_includes(XStr& str) {
344     perElemGen(members, str, &Member::genAccels_spe_h_includes);
345 }
346 void MemberList::genAccels_spe_h_fiCountDefs(XStr& str) {
347     perElemGen(members, str, &Member::genAccels_spe_h_fiCountDefs);
348 }
349 void MemberList::genAccels_ppe_c_regFuncs(XStr& str) {
350     perElemGen(members, str, &Member::genAccels_ppe_c_regFuncs);
351 }
352
353
354 void
355 Chare::print(XStr& str)
356 {
357   if(external)
358     str << "extern ";
359   if(templat)
360     templat->genSpec(str);
361
362   str << chareTypeName()<<" "<<type;
363   if(bases) { str << ": "; bases->print(str); }
364   if(list) {
365     str << "{\n"; list->print(str); str << "};\n";
366   } else {
367     str << ";\n";
368   }
369 }
370
371 void
372 Message::print(XStr& str)
373 {
374   if(external)
375     str << "extern ";
376   if(templat)
377     templat->genSpec(str);
378   str << "message ";
379   type->print(str);
380   printVars(str);
381   str << ";\n";
382 }
383
384 void
385 TType::print(XStr& str)
386 {
387   str << "class ";
388   type->print(str);
389   if(init) {
390     str << "=";
391     init->print(str);
392   }
393 }
394
395 void
396 TName::print(XStr& str)
397 {
398   type->print(str);
399   str << " "<<name;
400   if(val) {
401     str << "=";
402     str << val;
403   }
404 }
405
406
407 void
408 TVarList::print(XStr& str)
409 {
410   tvar->print(str);
411   if(next) {
412     str << ", ";
413     next->print(str);
414   }
415 }
416
417 void
418 Template::print(XStr& str)
419 {
420   if(entity)
421     entity->print(str);
422 }
423
424 void
425 Entry::print(XStr& str)
426 {
427   if(isThreaded())
428     str << "threaded ";
429   if(isSync())
430     str << "sync ";
431   if(retType) {
432     retType->print(str);
433     str << " ";
434   }
435   str << name<<"(";
436   if(param)
437     param->print(str);
438   str << ")";
439   if(stacksize) {
440     str << " stacksize = ";
441     stacksize->print(str);
442   }
443   str << ";\n";
444 }
445
446 void
447 Module::print(XStr& str)
448 {
449   if(external)
450     str << "extern ";
451   str << "module "<<name;
452   if(clist) {
453     str << " {\n";
454     clist->print(str);
455     str << "}\n";
456   } else {
457     str << ";\n";
458   }
459 }
460
461 void
462 Module::generate()
463 {
464   using std::ofstream;
465   XStr declstr, defstr;
466   XStr pubDeclStr, pubDefStr, pubDefConstr;
467
468   // DMK - Accel Support
469   #if CMK_CELL != 0
470   XStr accelstr_spe_c, accelstr_spe_h;
471   #endif
472
473   declstr <<
474   "#ifndef _DECL_"<<name<<"_H_\n"
475   "#define _DECL_"<<name<<"_H_\n"
476   "#include \"charm++.h\"\n";
477   if (fortranMode) declstr << "#include \"charm-api.h\"\n";
478   if (clist) clist->genDecls(declstr);
479   declstr << "extern void _register"<<name<<"(void);\n";
480   if(isMain()) {
481     declstr << "extern \"C\" void CkRegisterMainModule(void);\n";
482   }
483   declstr << "#endif"<<endx;
484   // Generate the publish class if there are structured dagger connect entries
485   int connectPresent = 0;
486   if (clist) clist->genPub(pubDeclStr, pubDefStr, pubDefConstr, connectPresent);
487   if (connectPresent == 1) {
488      pubDeclStr << "};\n\n";
489      pubDefConstr <<"}\n\n";
490   }
491
492   // defstr << "#ifndef _DEFS_"<<name<<"_H_"<<endx;
493   // defstr << "#define _DEFS_"<<name<<"_H_"<<endx;
494   genDefs(defstr);
495   templateGuardBegin(false, defstr);
496   defstr <<
497   "void _register"<<name<<"(void)\n"
498   "{\n"
499   "  static int _done = 0; if(_done) return; _done = 1;\n";
500   if (clist) clist->genReg(defstr);
501   defstr << "}\n";
502   if(isMain()) {
503     if (fortranMode) defstr << "extern void _registerf90main(void);\n";
504     defstr << "extern \"C\" void CkRegisterMainModule(void) {\n";
505     if (fortranMode) { // For Fortran90
506       defstr << "  // FORTRAN\n";
507       defstr << "  _registerf90main();\n";
508     }
509     defstr <<
510     "  _register"<<name<<"();\n"
511     "}\n";
512   }
513   templateGuardEnd(defstr);
514   // defstr << "#endif"<<endx;
515
516
517   // DMK - Accel Support
518   #if CMK_CELL != 0
519
520   /// Generate the SPE code file contents ///
521   accelstr_spe_c << "#ifndef __ACCEL_" << name << "_C__\n"
522                  << "#define __ACCEL_" << name << "_C__\n\n\n";
523   int numAccelEntries = genAccels_spe_c_funcBodies(accelstr_spe_c);
524   accelstr_spe_c << "\n\n#endif //__ACCEL_" << name << "_C__\n";
525
526   /// Generate the SPE header file contents ///
527   accelstr_spe_h << "#ifndef __ACCEL_" << name << "_H__\n"
528                  << "#define __ACCEL_" << name << "_H__\n\n\n";
529   genAccels_spe_h_includes(accelstr_spe_h);
530   accelstr_spe_h << "\n\n";
531   accelstr_spe_h << "#define MODULE_" << name << "_FUNC_INDEX_COUNT (" << numAccelEntries;
532   genAccels_spe_h_fiCountDefs(accelstr_spe_h);
533   accelstr_spe_h << ")\n\n\n";
534   accelstr_spe_h << "#endif //__ACCEL_" << name << "_H__\n";
535
536   #endif
537
538
539   XStr topname, botname;
540   topname<<name<<".decl.h";
541   botname<<name<<".def.h";
542   ofstream decl(topname.get_string()), def(botname.get_string());
543   if(!decl || !def) {
544     cerr<<"Cannot open "<<topname.get_string()<<"or "
545         <<botname.get_string()<<" for writing!!\n";
546     die("cannot create output files (check directory permissions)\n");
547   }
548   decl<<declstr.get_string();
549   def<<defstr.get_string();
550   if (connectPresent == 1) {
551     decl << pubDeclStr.charstar();
552     def << pubDefConstr.charstar();
553     def << pubDefStr.charstar();
554   }
555
556   // DMK - Accel Support
557   #if CMK_CELL != 0
558
559   /// Generate this module's code (actually create the files) ///
560   XStr accelname_c, accelname_h;
561   accelname_c << name << ".genSPECode.c";
562   accelname_h << name << ".genSPECode.h";
563   ofstream accel_c(accelname_c.get_string()), accel_h(accelname_h.get_string());
564   if (!accel_c) {
565     cerr << "Cannot open " << accelname_c.get_string() << " for writing!!\n";
566     die("Cannot create output files (check directory permissions)\n");
567   }
568   if (!accel_h) {
569     cerr << "Cannot open " << accelname_h.get_string() << " for writing!!\n";
570     die("Cannot create output files (check directory permissions)\n");
571   }
572   accel_c << accelstr_spe_c.get_string();
573   accel_h << accelstr_spe_h.get_string();
574   
575   // If this is the main module, generate the general C file and include this modules accel.h file
576   if (isMain()) {
577
578     XStr mainAccelStr_c;
579     mainAccelStr_c << "#include \"main__funcLookup__.genSPECode.h" << "\"\n"
580                    << "#include \"" << name << ".genSPECode.c" << "\"\n";
581     ofstream mainAccel_c("main__funcLookup__.genSPECode.c");
582     if (!mainAccel_c) {
583       cerr << "Cannot open main__funcLookup__.genSPECode.c for writing!!\n";
584       die("Cannot create output files (check directory permissions)");
585     }
586     mainAccel_c << mainAccelStr_c.get_string();
587
588     XStr mainAccelStr_h;
589     mainAccelStr_h << "#ifndef __MAIN_FUNCLOOKUP_H__\n"
590                    << "#define __MAIN_FUNCLOOKUP_H__\n\n"
591                    << "#include <spu_intrinsics.h>\n"
592                    << "#include <stdlib.h>\n"
593                    << "#include <stdio.h>\n"
594                    << "#include \"spert.h\"\n\n"
595                    << "#include \"simd.h\"\n"
596                    << "#include \"" << name << ".genSPECode.h" << "\"\n\n"
597                    << "#endif //__MAIN_FUNCLOOKUP_H__\n";
598     ofstream mainAccel_h("main__funcLookup__.genSPECode.h");
599     if (!mainAccel_h) {
600       cerr << "Cannot open main__funcLookup__.genSPECode.h for writing!!\n";
601       die("Cannot create output files (check directory permissions)");
602     }
603     mainAccel_h << mainAccelStr_h.get_string();
604
605   }
606
607   #endif
608 }
609
610 void
611 Module::preprocess()
612 {
613   if (clist!=NULL) clist->preprocess();
614 }
615
616 void
617 Module::genDepend(const char *cifile)
618 {
619   cout << name << ".decl.h " << name << ".def.h: "
620        << cifile << ".stamp" << endl;
621 }
622
623 void
624 ModuleList::print(XStr& str)
625 {
626     perElemGen(modules, str, &Module::print);
627 }
628
629 void
630 ModuleList::generate()
631 {
632     for (list<Module*>::iterator i = modules.begin(); i != modules.end(); ++i)
633         (*i)->generate();
634 }
635
636 void
637 ModuleList::preprocess()
638 {
639     for (list<Module*>::iterator i = modules.begin(); i != modules.end(); ++i)
640         (*i)->preprocess();
641 }
642
643 void
644 ModuleList::genDepends(std::string ciFileBaseName)
645 {
646     perElemGen(modules, ciFileBaseName.c_str(), &Module::genDepend);
647 }
648
649 void
650 Readonly::print(XStr& str)
651 {
652   if(external)
653     str << "extern ";
654   str << "readonly ";
655   if(msg)
656     str << "message ";
657   type->print(str);
658   if(msg)
659     str << " *";
660   else
661     str << " ";
662   str << name;
663   if(dims)
664     dims->print(str);
665   str << ";\n";
666 }
667
668 void
669 MemberList::setChare(Chare *c)
670 {
671     perElemGen(members, c, &Member::setChare);
672 }
673
674 void
675 ConstructList::genPub(XStr& declstr, XStr& defstr, XStr& defconstr, int& connectPresent)
676 {
677     for (list<Construct*>::iterator i = constructs.begin(); 
678          i != constructs.end(); ++i)
679         if (*i) {
680             (*i)->genPub(declstr, defstr, defconstr, connectPresent);
681             declstr << endx;
682         }
683 }
684
685 void
686 ConstructList::genDecls(XStr& str)
687 {
688     perElemGen(constructs, str, &Construct::genDecls, newLine);
689 }
690
691 void
692 ConstructList::genDefs(XStr& str)
693 {
694     perElemGen(constructs, str, &Construct::genDefs, newLine);
695 }
696
697 void
698 ConstructList::genReg(XStr& str)
699 {
700     perElemGen(constructs, str, &Construct::genReg, newLine);
701 }
702
703 void
704 ConstructList::preprocess()
705 {
706     for (list<Construct*>::iterator i = constructs.begin(); 
707          i != constructs.end(); ++i)
708         if (*i)
709             (*i)->preprocess();
710 }
711
712 XStr Chare::proxyName(int withTemplates)
713 {
714   XStr str;
715   str<<proxyPrefix()<<type;
716   if (withTemplates) str<<tvars();
717   return str;
718 }
719
720 XStr Chare::indexName(int withTemplates)
721 {
722   XStr str;
723   str<<Prefix::Index<<type;
724   if (withTemplates) str<<tvars();
725   return str;
726 }
727
728 XStr Chare::indexList()
729 {
730   // generating "int *index1, int *index2, int *index3"
731   XStr str;
732   if (!isArray()) { // Currently, only arrays are supported
733       cerr << (char *)baseName() << ": only chare arrays are currently supported\n";
734       exit(1);
735   }
736   XStr dim = ((Array*)this)->dim();
737   if (dim==(const char*)"1D")
738     str << "const int *index1";
739   else if (dim==(const char*)"2D")
740     str << "const int *index1, const int *index2";
741   else if (dim==(const char*)"3D")
742     str << "const int *index1, const int *index2, const int *index3";
743   else {
744       cerr << (char *)baseName() << ": only up to 3 dimension chare arrays are currently supported\n";
745       exit(1);
746   }
747   return str;
748 }
749
750 static const char *forWhomStr(forWhom w)
751 {
752   switch(w) {
753   case forAll: return Prefix::Proxy;
754   case forIndividual: return Prefix::ProxyElement;
755   case forSection: return Prefix::ProxySection;
756   case forIndex: return Prefix::Index;
757   case forPython: return "";
758   default: return NULL;
759   };
760 }
761
762 void NamedType::genProxyName(XStr& str,forWhom forElement)
763 {
764     const char *prefix=forWhomStr(forElement);
765     if (prefix==NULL)
766         die("Unrecognized forElement type passed to NamedType::genProxyName");
767     if (scope) str << scope;
768     str << prefix;
769     str << name;
770     if (tparams) str << "<"<<tparams<<" >";
771 }
772
773 void TypeList::genProxyNames(XStr& str, const char *prefix, const char *middle,
774                              const char *suffix, const char *sep,forWhom forElement)
775 {
776   if(type) {
777     str << prefix;
778     type->genProxyName(str,forElement);
779     if (middle!=NULL) {
780       str << middle;
781       type->genProxyName(str,forElement);
782     }
783     str << suffix;
784   }
785   if(next) {
786     str << sep;
787     next->genProxyNames(str, prefix, middle, suffix, sep,forElement);
788   }
789 }
790 void Chare::genProxyNames(XStr& str, const char *prefix,const char *middle,
791         const char *suffix, const char *sep)
792 {
793         bases->genProxyNames(str,prefix,middle,suffix,sep,forElement);
794 }
795 void Chare::genIndexNames(XStr& str, const char *prefix,const char *middle,
796         const char *suffix, const char *sep)
797 {
798         bases->genProxyNames(str,prefix,middle,suffix,sep,forIndex);
799 }
800 char *Chare::proxyPrefix(void)
801 {
802   return (char *)forWhomStr(forElement);
803 }
804
805 //Common multiple inheritance disambiguation code
806 void Chare::sharedDisambiguation(XStr &str,const XStr &super)
807 {
808     (void)super;
809     str << "\n    void ckDelegate(CkDelegateMgr *dTo,CkDelegateData *dPtr=NULL)"
810         << "\n    { ";
811     genProxyNames(str,"      ",NULL,"::ckDelegate(dTo,dPtr); ","");
812     str << "}"
813         << "\n    void ckUndelegate(void)"
814         << "\n    { ";
815     genProxyNames(str,"      ",NULL,"::ckUndelegate(); ","");
816     str << "}"
817         << "\n    void pup(PUP::er &p)"
818         << "\n    { ";
819     genProxyNames(str,"      ",NULL,"::pup(p); ","");
820     str << "}";
821     if (isPython()) {
822       str << "\n    void registerPython(const char *str)"
823           << "\n    { CcsRegisterHandler(str, CkCallback("<<Prefix::Index<<type<<"::pyRequest(0), *this)); }";
824     }
825     str << "\n";
826 }
827
828
829 static const char *CIClassStart = // prefix, name
830 "{\n"
831 "  public:\n"
832 ;
833
834 static const char *CIClassEnd =
835 "};\n"
836 ;
837
838 Chare::Chare(int ln, attrib_t Nattr, NamedType *t, TypeList *b, MemberList *l)
839          : attrib(Nattr), type(t), list(l), bases(b)
840 {
841         line = ln;
842         entryCount=1;
843         hasElement=0;
844         forElement=forAll;
845         hasSection=0;
846         bases_CBase=NULL;
847         setTemplate(0);
848         hasSdagEntry=0;
849         if (list)
850         {
851                 list->setChare(this);
852                 //Add migration constructor to MemberList
853                 if(isMigratable()) {
854                         Entry *e=new Entry(ln,SMIGRATE,NULL,
855                           (char *)type->getBaseName(),
856                           new ParamList(new Parameter(line,
857                                 new PtrType(new NamedType("CkMigrateMessage")))),0,0,0);
858                         e->setChare(this);
859                         list=new MemberList(e,list);
860                 }
861         }
862         if (bases==NULL) //Always add Chare as a base class
863                 bases = new TypeList(new NamedType("Chare"), NULL);
864 }
865
866 void
867 Chare::genRegisterMethodDef(XStr& str)
868 {
869   if(external || type->isTemplated())
870     return;
871   templateGuardBegin(isTemplated(), str);
872   str <<  tspec() <<
873   "void "<<indexName()<<"::__register(const char *s, size_t size) {\n"
874   "  __idx = CkRegisterChare(s, size,";
875   if (isMainChare()) str << " TypeMainChare";
876   else if (isGroup()) str << " TypeGroup";
877   else if (isNodeGroup()) str << " TypeNodeGroup";
878   else if (isArray()) str << " TypeArray";
879   else if (isChare()) str << " TypeChare";
880   else str << " TypeInvalid";
881   str << ");\n";
882   if (internalMode) str << "  CkRegisterChareInCharm(__idx);\n";
883   // register all bases
884   genIndexNames(str, "  CkRegisterBase(__idx, ",NULL, "::__idx);\n", "");
885   genSubRegisterMethodDef(str);
886   if(list)
887     list->genReg(str);
888   if (hasSdagEntry) {
889       str << "  " << baseName() << "::__sdag_register(); \n";
890   }
891   str << "}\n";
892   templateGuardEnd(str);
893 }
894
895 void
896 Chare::genPub(XStr& declstr, XStr& defstr, XStr& defconstr, int& connectPresent)
897 {
898   if(type->isTemplated())
899     return;
900   else
901   {
902     if(list)
903       list->genPub(declstr, defstr, defconstr, connectPresent);
904   }
905 }
906
907 void
908 Chare::genDecls(XStr& str)
909 {
910   if(type->isTemplated())
911     return;
912   str << "/* DECLS: "; print(str); str << " */\n";
913
914   // include python header and add two methods called execute and iterate.
915   // these cannot be added to the .ci file of the PythonCCS interface since
916   // different charm object require different definitions...
917   if (isPython()) {
918     str << "#include \"PythonCCS.h\"\n";
919     if (list) {
920       Entry *etemp = new Entry(0,0,new BuiltinType("void"),"pyRequest",new ParamList(new Parameter(0,new PtrType(new NamedType("CkCcsRequestMsg",0)),"msg")),0,0,0,0);
921       list->appendMember(etemp);
922       etemp->setChare(this);
923       //etemp = new Entry(0,0,new BuiltinType("void"),"getPrint",new ParamList(new Parameter(0,new PtrType(new NamedType("CkCcsRequestMsg",0)),"msg")),0,0,0,0);
924       //list->appendMember(etemp);
925       //etemp->setChare(this);
926     }
927   }
928
929   //Forward declaration of the user-defined implementation class*/
930   str << tspec()<<" class "<<type<<";\n";
931   str << tspec()<<" class "<<Prefix::Index<<type<<";\n";
932   str << tspec()<<" class "<<Prefix::Proxy<<type<<";\n";
933   if (hasElement)
934     str << tspec()<<" class "<<Prefix::ProxyElement<<type<<";\n";
935   if (hasSection)
936     str << tspec()<<" class "<<Prefix::ProxySection<<type<<";\n";
937   if (isPython())
938     str << tspec()<<" class "<<Prefix::Python<<type<<";\n";
939
940  //Generate index class
941   str << "/* --------------- index object ------------------ */\n";
942   str << tspec()<< "class "<<Prefix::Index<<type;
943   str << ":";
944   genProxyNames(str, "public ",NULL, "", ", ");
945   if(external || type->isTemplated())
946   { //Just a template instantiation/forward declaration
947     str << ";";
948   }
949   else
950   { //Actual implementation
951     str << CIClassStart;
952     genTypedefs(str);
953     str << "    static int __idx;\n";
954     str << "    static void __register(const char *s, size_t size);\n";
955     if(list)
956       list->genIndexDecls(str);
957     str << CIClassEnd;
958   }
959   str << "/* --------------- element proxy ------------------ */\n";
960   genSubDecls(str);
961   if (hasElement) {
962     str << "/* ---------------- collective proxy -------------- */\n";
963     forElement=forAll; genSubDecls(str); forElement=forIndividual;
964   }
965   if (hasSection) {
966     str << "/* ---------------- section proxy -------------- */\n";
967     forElement=forSection; genSubDecls(str); forElement=forIndividual;
968   }
969   if (isPython()) {
970     str << "/* ---------------- python wrapper -------------- */\n";
971     genPythonDecls(str);
972   }
973
974   if(list) {
975     //handle the case that some of the entries may be sdag Entries
976     int sdagPresent = 0;
977     XStr sdagStr;
978     CParsedFile myParsedFile(this);
979     list->collectSdagCode(&myParsedFile, sdagPresent);
980     if(sdagPresent) {
981       XStr classname;
982       XStr sdagDecls;
983       classname << baseName(0);
984       resetNumbers();
985       myParsedFile.doProcess(classname, sdagDecls, sdagDefs);
986       str << sdagDecls;
987     }
988   }
989
990   // Create CBase_Whatever convenience type so that chare implementations can
991   // avoid inheriting from a complex CBaseT templated type.
992   TypeList *b=bases_CBase;
993   if (b==NULL) b=bases; //Fall back to normal bases list if no CBase available
994   if (templat) {
995     templat->genSpec(str);
996     str << "\nclass CBase_" << type << " : public ";
997   } else {
998     str << "typedef ";
999   }
1000   str << "CBaseT" << b->length() << "<";
1001   if (isPython()) {
1002     str << Prefix::Python << type;
1003   } else {
1004     str << b;
1005   }
1006   str << ", CProxy_" << type;
1007   if (templat) {
1008     templat->genVars(str);
1009     str << " > { };\n";
1010   } else {
1011     str << "> CBase_" << type << ";\n";
1012   }
1013 }
1014
1015 void
1016 Chare::preprocess()
1017 {
1018   if(list) list->preprocess();
1019 }
1020
1021 /*This disambiguation code is needed to support
1022   multiple inheritance in Chares (Groups, Arrays).
1023   They resolve ambiguous accessor calls to the parent "super".
1024   Because mutator routines need to change *all* the base
1025   classes, mutators are generated in xi-symbol.C.
1026 */
1027 static void
1028 disambig_proxy(XStr &str, const XStr &super)
1029 {
1030   str << "\n    int ckIsDelegated(void) const"
1031       << "\n    { return " << super << "::ckIsDelegated(); }"
1032       << "\n    inline CkDelegateMgr *ckDelegatedTo(void) const"
1033       << "\n    { return " << super << "::ckDelegatedTo(); }"
1034       << "\n    inline CkDelegateData *ckDelegatedPtr(void) const"
1035       << "\n    { return " << super << "::ckDelegatedPtr(); }"
1036       << "\n    CkGroupID ckDelegatedIdx(void) const"
1037       << "\n    { return " << super << "::ckDelegatedIdx(); }"
1038       << "\n";
1039 }
1040
1041 void
1042 Chare::genSubDecls(XStr& str)
1043 {
1044   XStr ptype;
1045   ptype<<proxyPrefix()<<type;
1046
1047   // Class declaration
1048   str << tspec()<< "class "<<ptype;
1049   if(external || type->isTemplated()) {
1050     str << ";";
1051     return;
1052   }
1053   str << ":";
1054   genProxyNames(str, "public ",NULL, "", ", ");
1055   str << CIClassStart;
1056
1057   genTypedefs(str);
1058
1059   // Various constructors:
1060   str << "    "<<ptype<<"(void) {};\n";
1061
1062   str << "    "<<ptype<<"(CkChareID __cid) : ";
1063   genProxyNames(str, "",NULL, "(__cid)", ", ");
1064   str << "{  }\n";
1065
1066   str << "    "<<ptype<<"(const Chare *c) : ";
1067   genProxyNames(str, "",NULL, "(c)", ", ");
1068   str << "{  }\n";
1069
1070   //Multiple inheritance-- resolve inheritance ambiguity
1071     XStr super;
1072     bases->getFirst()->genProxyName(super,forElement);
1073     disambig_proxy(str, super);
1074     str << "\n    inline void ckCheck(void) const"
1075         << "\n    { "<< super << "::ckCheck(); }"
1076         << "\n    const CkChareID &ckGetChareID(void) const"
1077         << "\n    { return " << super << "::ckGetChareID(); }"
1078         << "\n    operator const CkChareID &(void) const"
1079         << "\n    { return ckGetChareID(); }"
1080         << "\n";
1081
1082     sharedDisambiguation(str,super);
1083     str << "\n    void ckSetChareID(const CkChareID &c)"
1084         << "\n    {";
1085     genProxyNames(str,"      ",NULL,"::ckSetChareID(c); ","");
1086     str << "}"
1087         << "\n    "<<type<<tvars()<<" *ckLocal(void) const"
1088         << "\n    { return ("<<type<<tvars()<<" *)CkLocalChare(&ckGetChareID()); }"
1089         << "\n";
1090
1091   if(list)
1092     list->genDecls(str);
1093   str << CIClassEnd;
1094   if (!isTemplated()) str << "PUPmarshall("<<ptype<<")\n";
1095 }
1096
1097 void Chare::genPythonDecls(XStr& str) {
1098
1099   XStr ptype;
1100   ptype<<Prefix::Python<<type;
1101
1102   // Class declaration
1103   str << tspec()<< "class "<<ptype;
1104   if(external || type->isTemplated()) {
1105     str << ";";
1106     return;
1107   }
1108   str << ":";
1109   TypeList *b=bases_CBase;
1110   if (b==NULL) b=bases; //Fall back to normal bases list if no CBase available
1111   b->genProxyNames(str,"public ",NULL,"",", ",forPython);
1112   str << ", public PythonObject ";
1113   str << CIClassStart;
1114
1115   // default constructor methods
1116   str << "    "<<ptype<<"(void) {}\n";
1117   str << "    "<<ptype<<"(CkMigrateMessage *msg): ";
1118   b->genProxyNames(str,"",NULL,"(msg)",", ",forPython);
1119   str << " {}\n";
1120
1121   // define pupper
1122   str << "    void pup(PUP::er &p) {\n";
1123   b->genProxyNames(str,"      ",NULL,"::pup(p);","\n",forPython);
1124   str << "\n    }\n";
1125
1126   // define the python custom methods and their documentation
1127   str << "    static PyMethodDef CkPy_MethodsCustom[];\n";
1128   str << "    PyMethodDef *getMethods(void) {return CkPy_MethodsCustom;}\n";
1129   str << "    static const char *CkPy_MethodsCustomDoc;\n";
1130   str << "    const char *getMethodsDoc(void) {return CkPy_MethodsCustomDoc;}\n";
1131
1132   str << CIClassEnd;
1133
1134   // declare all static python methods and CkPy_MethodsCustom
1135   if (list)
1136     list->genPythonDecls(str);
1137   str << "\n";
1138
1139   if (!isTemplated()) str << "PUPmarshall("<<ptype<<")\n";
1140 }
1141
1142 void Chare::genPythonDefs(XStr& str) {
1143
1144   XStr ptype;
1145   ptype<<Prefix::Python<<type;
1146
1147   // generate the python methods array
1148   str << "PyMethodDef "<<ptype<<"::CkPy_MethodsCustom[] = {\n";
1149   if (list)
1150     list->genPythonStaticDefs(str);
1151   str << "  {NULL, NULL}\n};\n\n";
1152   // generate documentaion for the methods
1153   str << "const char * "<<ptype<<"::CkPy_MethodsCustomDoc = \"charm.__doc__ = \\\"Available methods for object "<<type<<":\\\\n\"";
1154   if (list)
1155     list->genPythonStaticDocs(str);
1156   str << "\n  \"\\\"\";\n\n";
1157
1158   if (list)
1159     list->genPythonDefs(str);
1160
1161 }
1162
1163 Group::Group(int ln, attrib_t Nattr,
1164         NamedType *t, TypeList *b, MemberList *l)
1165         :Chare(ln,Nattr|CGROUP,t,b,l)
1166 {
1167         hasElement=1;
1168         forElement=forIndividual;
1169         hasSection=1;
1170         bases_CBase=NULL;
1171         if (b==NULL) {//Add Group as a base class
1172                 delete bases;
1173                 if (isNodeGroup())
1174                         bases = new TypeList(new NamedType("NodeGroup"), NULL);
1175                 else {
1176                         bases = new TypeList(new NamedType("IrrGroup"), NULL);
1177                         bases_CBase = new TypeList(new NamedType("Group"), NULL);
1178                 }
1179         }
1180 }
1181
1182 void Group::genSubRegisterMethodDef(XStr& str) {
1183         if(!isTemplated()){
1184                 str << "   CkRegisterGroupIrr(__idx,"<<type<<"::isIrreducible());\n";
1185         }else{
1186                 str << "   CkRegisterGroupIrr(__idx," <<type<<tvars() <<"::isIrreducible());\n";
1187         }
1188 }
1189
1190 static void
1191 disambig_reduction_client(XStr &str, const XStr &super)
1192 {
1193   str << "\n    inline void setReductionClient(CkReductionClientFn fn,void *param=NULL) const"
1194       << "\n    { " << super << "::setReductionClient(fn,param); }"
1195       << "\n    inline void ckSetReductionClient(CkReductionClientFn fn,void *param=NULL) const"
1196       << "\n    { " << super << "::ckSetReductionClient(fn,param); }"
1197       << "\n    inline void ckSetReductionClient(CkCallback *cb) const"
1198       << "\n    { " << super << "::ckSetReductionClient(cb); }"
1199       << "\n";
1200 }
1201
1202 static void
1203 disambig_group(XStr &str, const XStr &super)
1204 {
1205   disambig_proxy(str, super);
1206   str << "inline void ckCheck(void) const {" << super << "::ckCheck();}\n"
1207       << "CkChareID ckGetChareID(void) const\n"
1208       << "   {return " << super << "::ckGetChareID();}\n"
1209       << "CkGroupID ckGetGroupID(void) const\n"
1210       << "   {return " << super << "::ckGetGroupID();}\n"
1211       << "operator CkGroupID () const { return ckGetGroupID(); }\n";
1212   disambig_reduction_client(str, super);
1213 }
1214
1215 void
1216 Group::genSubDecls(XStr& str)
1217 {
1218   XStr ptype; ptype<<proxyPrefix()<<type;
1219   XStr ttype; ttype<<type<<tvars();
1220   XStr super;
1221   bases->getFirst()->genProxyName(super,forElement);
1222
1223   // Class declaration:
1224   str << tspec()<< "class "<<ptype;
1225   if(external || type->isTemplated()) {
1226     str << ";";
1227     return;
1228   }
1229   str << ": ";
1230   genProxyNames(str, "public ",NULL, "", ", ");
1231   str << CIClassStart;
1232
1233   genTypedefs(str);
1234
1235   // Basic constructors:
1236   str << "    "<<ptype<<"(void) {}\n";
1237   str << "    "<<ptype<<"(const IrrGroup *g) : ";
1238   genProxyNames(str, "", NULL,"(g)", ", ");
1239   str << "{  }\n";
1240
1241   if (forElement==forIndividual)
1242   {//For a single element
1243     str << "    "<<ptype<<"(CkGroupID _gid,int _onPE,CK_DELCTOR_PARAM) : ";
1244     genProxyNames(str, "", NULL,"(_gid,_onPE,CK_DELCTOR_ARGS)", ", ");
1245     str << "{  }\n";
1246     str << "    "<<ptype<<"(CkGroupID _gid,int _onPE) : ";
1247     genProxyNames(str, "", NULL,"(_gid,_onPE)", ", ");
1248     str << "{  }\n";
1249
1250     disambig_group(str, super);
1251     str << "int ckGetGroupPe(void) const\n"
1252         << "{return " << super << "::ckGetGroupPe();}\n";
1253
1254   }
1255   else if (forElement==forSection)
1256   {//For a section of the group
1257     str << "    "<<ptype<<"(const CkGroupID &_gid,const int *_pelist,int _npes,CK_DELCTOR_PARAM) : ";
1258     genProxyNames(str, "", NULL,"(_gid,_pelist,_npes,CK_DELCTOR_ARGS)", ", ");
1259     str << "{  }\n";
1260     str << "    "<<ptype<<"(const CkGroupID &_gid,const int *_pelist,int _npes) : ";
1261     genProxyNames(str, "", NULL,"(_gid,_pelist,_npes)", ", ");
1262     str << "{  }\n";
1263     str << "    "<<ptype<<"(int n,const CkGroupID *_gid, int const * const *_pelist,const int *_npes) : ";
1264     genProxyNames(str, "", NULL,"(n,_gid,_pelist,_npes)", ", ");
1265     str << "{  }\n";
1266     str << "    "<<ptype<<"(int n,const CkGroupID *_gid, int const * const *_pelist,const int *_npes,CK_DELCTOR_PARAM) : ";
1267     genProxyNames(str, "", NULL,"(n,_gid,_pelist,_npes,CK_DELCTOR_ARGS)", ", ");
1268     str << "{  }\n";
1269     
1270     disambig_group(str, super);
1271     str << "inline int ckGetNumSections() const\n" <<
1272       "{ return " << super << "::ckGetNumSections(); }\n" <<
1273       "inline CkSectionInfo &ckGetSectionInfo()\n" <<
1274       "{ return " << super << "::ckGetSectionInfo(); }\n" <<
1275       "inline CkSectionID *ckGetSectionIDs()\n" <<
1276       "{ return " << super << "::ckGetSectionIDs(); }\n" <<
1277       "inline CkSectionID &ckGetSectionID()\n" <<
1278       "{ return " << super << "::ckGetSectionID(); }\n" <<
1279       "inline CkSectionID &ckGetSectionID(int i)\n" <<
1280       "{ return " << super << "::ckGetSectionID(i); }\n" <<
1281       "inline CkGroupID ckGetGroupIDn(int i) const\n" <<
1282       "{ return " << super << "::ckGetGroupIDn(i); }\n" <<
1283       "inline int *ckGetElements() const\n" <<
1284       "{ return " << super << "::ckGetElements(); }\n" <<
1285       "inline int *ckGetElements(int i) const\n" <<
1286       "{ return " << super << "::ckGetElements(i); }\n" <<
1287       "inline int ckGetNumElements() const\n" <<
1288       "{ return " << super << "::ckGetNumElements(); } \n" <<
1289       "inline int ckGetNumElements(int i) const\n" <<
1290       "{ return " << super << "::ckGetNumElements(i); }\n";
1291   }
1292   else if (forElement==forAll)
1293   {//For whole group
1294     str << "    "<<ptype<<"(CkGroupID _gid,CK_DELCTOR_PARAM) : ";
1295     genProxyNames(str, "", NULL,"(_gid,CK_DELCTOR_ARGS)", ", ");
1296     str << "{  }\n";
1297     str << "    "<<ptype<<"(CkGroupID _gid) : ";
1298     genProxyNames(str, "", NULL,"(_gid)", ", ");
1299     str << "{  }\n";
1300
1301     //Group proxy can be indexed into an element proxy:
1302     forElement=forIndividual;//<- for the proxyName below
1303     str << "    "<<proxyName(1)<<" operator[](int onPE) const\n";
1304     str << "      {return "<<proxyName(1)<<"(ckGetGroupID(),onPE,CK_DELCTOR_CALL);}\n";
1305     forElement=forAll;
1306
1307     disambig_group(str, super);
1308   }
1309
1310   //Multiple inheritance-- resolve inheritance ambiguity
1311   sharedDisambiguation(str,super);
1312   str<<"    void ckSetGroupID(CkGroupID g) {\n";
1313   genProxyNames(str,"      ",NULL,"::ckSetGroupID(g);\n","");
1314   str<<"    }\n";
1315
1316   str << "    "<<ttype<<"* ckLocalBranch(void) const {\n";
1317   str << "      return ckLocalBranch(ckGetGroupID());\n";
1318   str << "    }\n";
1319   str << "    static "<<ttype<< "* ckLocalBranch(CkGroupID gID) {\n";
1320   str << "      return ("<<ttype<<"*)";
1321   if(isNodeGroup())
1322     str << "CkLocalNodeBranch(gID);\n";
1323   else
1324     str << "CkLocalBranch(gID);\n";
1325   str << "    }\n";
1326   if(list)
1327     list->genDecls(str);
1328   str << CIClassEnd;
1329   if (!isTemplated()) str << "PUPmarshall("<<ptype<<")\n";
1330
1331 }
1332
1333 XStr indexSuffix2object(const XStr &indexSuffix) {
1334         if (indexSuffix==(const char*)"1D") return "CkIndex1D";
1335         if (indexSuffix==(const char*)"2D") return "CkIndex2D";
1336         if (indexSuffix==(const char*)"3D") return "CkIndex3D";
1337         if (indexSuffix==(const char*)"4D") return "CkIndex4D";
1338         if (indexSuffix==(const char*)"5D") return "CkIndex5D";
1339         if (indexSuffix==(const char*)"6D") return "CkIndex6D";
1340         if (indexSuffix==(const char*)"Max") return "CkIndexMax";
1341         else return indexSuffix;
1342 }
1343
1344 //Array Constructor
1345 Array::Array(int ln, attrib_t Nattr, NamedType *index,
1346         NamedType *t, TypeList *b, MemberList *l)
1347     : Chare(ln,Nattr|CARRAY|CMIGRATABLE,t,b,l)
1348 {
1349         hasElement=1;
1350         forElement=forIndividual;
1351         hasSection=1;
1352         index->print(indexSuffix);
1353       //printf("indexSuffix = %s\n", indexSuffix.charstar());
1354         if (indexSuffix!=(const char*)"none")
1355                 indexType<<"CkArrayIndex"<<indexSuffix;
1356         else indexType<<"CkArrayIndex";
1357
1358         if(b==0) { //No other base class:
1359                 delete bases;
1360                 if (0==strcmp(type->getBaseName(),"ArrayElement"))
1361                         //ArrayElement has special "ArrayBase" superclass
1362                         bases = new TypeList(new NamedType("ArrayBase"), NULL);
1363                 else {//Everybody else inherits from ArrayElementT<indexType>
1364                         bases=new TypeList(new NamedType("ArrayElement"),NULL);
1365                         XStr indexObject(indexSuffix2object(indexSuffix));
1366                         XStr parentClass;
1367                         parentClass<<"ArrayElementT<"<<indexObject<<">";
1368                         char *parentClassName=strdup(parentClass);
1369                         bases_CBase = new TypeList(new NamedType(parentClassName), NULL);
1370                 }
1371         }
1372 }
1373
1374 static void
1375 disambig_array(XStr &str, const XStr &super)
1376 {
1377   disambig_proxy(str, super);
1378   str << "\n    inline void ckCheck(void) const"
1379       << "\n    { " << super << "::ckCheck(); }"
1380       << "\n    inline operator CkArrayID () const"
1381       << "\n    { return ckGetArrayID(); }"
1382       << "\n    inline CkArrayID ckGetArrayID(void) const"
1383       << "\n    { return " << super << "::ckGetArrayID(); }"
1384       << "\n    inline CkArray *ckLocalBranch(void) const"
1385       << "\n    { return " << super << "::ckLocalBranch(); }"
1386       << "\n    inline CkLocMgr *ckLocMgr(void) const"
1387       << "\n    { return " << super << "::ckLocMgr(); }"
1388       << "\n"
1389       << "\n    inline static CkArrayID ckCreateEmptyArray(void)"
1390       << "\n    { return " << super << "::ckCreateEmptyArray(); }"
1391       << "\n    inline static CkArrayID ckCreateArray(CkArrayMessage *m,int ctor,const CkArrayOptions &opts)"
1392       << "\n    { return " << super << "::ckCreateArray(m,ctor,opts); }"
1393       << "\n    inline void ckInsertIdx(CkArrayMessage *m,int ctor,int onPe,const CkArrayIndex &idx)"
1394       << "\n    { " << super << "::ckInsertIdx(m,ctor,onPe,idx); }"
1395       << "\n    inline void doneInserting(void)"
1396       << "\n    { " << super << "::doneInserting(); }"
1397       << "\n"
1398       << "\n    inline void ckBroadcast(CkArrayMessage *m, int ep, int opts=0) const"
1399       << "\n    { " << super << "::ckBroadcast(m,ep,opts); }";
1400   disambig_reduction_client(str, super);
1401 }
1402
1403 void
1404 Array::genSubDecls(XStr& str)
1405 {
1406   XStr ptype; ptype<<proxyPrefix()<<type;
1407
1408   // Class declaration:
1409   str << tspec()<< " class "<<ptype;
1410   if(external || type->isTemplated()) {
1411     str << ";";
1412     return;
1413   }
1414   str << " : ";
1415   genProxyNames(str, "public ",NULL, "", ", ");
1416   str << CIClassStart;
1417
1418   genTypedefs(str);
1419
1420   str << "    "<<ptype<<"(void) {}\n";//An empty constructor
1421   if (forElement!=forSection)
1422   { //Generate constructor based on array element
1423           str << "    "<<ptype<<"(const ArrayElement *e) : ";
1424     genProxyNames(str, "", NULL,"(e)", ", ");
1425     str << "{  }\n";
1426   }
1427
1428   //Resolve multiple inheritance ambiguity
1429   XStr super;
1430   bases->getFirst()->genProxyName(super,forElement);
1431   sharedDisambiguation(str,super);
1432
1433   if (forElement==forIndividual)
1434   {/*For an individual element (no indexing)*/
1435     disambig_array(str, super);
1436     str << "\n    inline void ckInsert(CkArrayMessage *m,int ctor,int onPe)"
1437         << "\n    { " << super << "::ckInsert(m,ctor,onPe); }"
1438         << "\n    inline void ckSend(CkArrayMessage *m, int ep, int opts = 0) const"
1439         << "\n    { " << super << "::ckSend(m,ep,opts); }"
1440         << "\n    inline void *ckSendSync(CkArrayMessage *m, int ep) const"
1441         << "\n    { return " << super << "::ckSendSync(m,ep); }"
1442         << "\n    inline const CkArrayIndex &ckGetIndex() const"
1443         << "\n    { return " << super << "::ckGetIndex(); }"
1444         << "\n"
1445         << "\n    " << type << tvars() << " *ckLocal(void) const"
1446         << "\n    { return ("<<type<<tvars()<<" *)"<<super<<"::ckLocal(); }"
1447         << "\n";
1448
1449     //This constructor is used for array indexing
1450     str << "\n    " <<ptype<<"(const CkArrayID &aid,const "<<indexType<<" &idx,CK_DELCTOR_PARAM)"
1451         << "\n        :";
1452     genProxyNames(str, "",NULL, "(aid,idx,CK_DELCTOR_ARGS)", ", ");
1453     str << "\n    {}"
1454         << "\n    " <<ptype<<"(const CkArrayID &aid,const "<<indexType<<" &idx)"
1455         << "\n        :";
1456     genProxyNames(str, "",NULL, "(aid,idx)", ", ");
1457     str << "\n    {}"
1458         << "\n";
1459
1460     if ((indexType != (const char*)"CkArrayIndex") && (indexType != (const char*)"CkArrayIndexMax"))
1461     {
1462       // Emit constructors that take the base class array index too.  This proves
1463       // useful for runtime code that needs to access an element via a CkArrayIndex and
1464       // an array proxy. This might compromise type safety a wee bit and is hence not
1465       // propagated throughout.  For eg, CProxy_Foo::operator[] still accepts only the
1466       // appropriate CkArrayIndexND.
1467       str << "\n    " <<ptype<<"(const CkArrayID &aid,const CkArrayIndex &idx,CK_DELCTOR_PARAM)"
1468           << "\n        :";
1469       genProxyNames(str, "",NULL, "(aid,idx,CK_DELCTOR_ARGS)", ", ");
1470       str << "\n    {}"
1471           << "\n    " << ptype<<"(const CkArrayID &aid,const CkArrayIndex &idx)"
1472           << "\n        :";
1473       genProxyNames(str, "",NULL, "(aid,idx)", ", ");
1474       str << "\n    {}"
1475           << "\n";
1476     }
1477   }
1478   else if (forElement==forAll)
1479   {/*Collective, indexible version*/
1480     disambig_array(str, super);
1481
1482     //Build a simple, empty array
1483     str << "\n    static CkArrayID ckNew(void) { return ckCreateEmptyArray(); }";
1484
1485     XStr etype; etype<<Prefix::ProxyElement<<type<<tvars();
1486     if (indexSuffix!=(const char*)"none")
1487     {
1488       str << "\n    // Generalized array indexing:"
1489           << "\n    "<<etype<<" operator [] (const "<<indexType<<" &idx) const"
1490           << "\n    { return "<<etype<<"(ckGetArrayID(), idx, CK_DELCTOR_CALL); }"
1491           << "\n    "<<etype<<" operator() (const "<<indexType<<" &idx) const"
1492           << "\n    { return "<<etype<<"(ckGetArrayID(), idx, CK_DELCTOR_CALL); }"
1493           << "\n";
1494     }
1495
1496   //Add specialized indexing for these common types
1497     if (indexSuffix==(const char*)"1D")
1498     {
1499     str << "    " << etype << " operator [] (int idx) const \n"
1500         << "        {return "<< etype <<"(ckGetArrayID(), CkArrayIndex1D(idx), CK_DELCTOR_CALL);}\n"
1501         << "    " << etype <<" operator () (int idx) const \n"
1502         << "        {return "<< etype <<"(ckGetArrayID(), CkArrayIndex1D(idx), CK_DELCTOR_CALL);}\n";
1503     } else if (indexSuffix==(const char*)"2D") {
1504     str <<
1505     "    "<<etype<<" operator () (int i0,int i1) const \n"
1506     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex2D(i0,i1), CK_DELCTOR_CALL);}\n"
1507     "    "<<etype<<" operator () (CkIndex2D idx) const \n"
1508     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex2D(idx), CK_DELCTOR_CALL);}\n";
1509     } else if (indexSuffix==(const char*)"3D") {
1510     str <<
1511     "    "<<etype<<" operator () (int i0,int i1,int i2) const \n"
1512     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex3D(i0,i1,i2), CK_DELCTOR_CALL);}\n"
1513     "    "<<etype<<" operator () (CkIndex3D idx) const \n"
1514     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex3D(idx), CK_DELCTOR_CALL);}\n";
1515     } else if (indexSuffix==(const char*)"4D") {
1516     str <<
1517     "    "<<etype<<" operator () (short int i0,short int i1,short int i2,short int i3) const \n"
1518     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex4D(i0,i1,i2,i3), CK_DELCTOR_CALL);}\n"
1519     "    "<<etype<<" operator () (CkIndex4D idx) const \n"
1520     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex4D(idx), CK_DELCTOR_CALL);}\n";
1521     } else if (indexSuffix==(const char*)"5D") {
1522     str <<
1523     "    "<<etype<<" operator () (short int i0,short int i1,short int i2,short int i3,short int i4) const \n"
1524     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex5D(i0,i1,i2,i3,i4), CK_DELCTOR_CALL);}\n"
1525     "    "<<etype<<" operator () (CkIndex5D idx) const \n"
1526     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex5D(idx), CK_DELCTOR_CALL);}\n";
1527     } else if (indexSuffix==(const char*)"6D") {
1528     str <<
1529     "    "<<etype<<" operator () (short int i0,short int i1,short int i2,short int i3,short int i4,short int i5) const \n"
1530     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex6D(i0,i1,i2,i3,i4,i5), CK_DELCTOR_CALL);}\n"
1531     "    "<<etype<<" operator () (CkIndex6D idx) const \n"
1532     "        {return "<<etype<<"(ckGetArrayID(), CkArrayIndex6D(idx), CK_DELCTOR_CALL);}\n";
1533     }
1534     str <<"    "<<ptype<<"(const CkArrayID &aid,CK_DELCTOR_PARAM) \n"
1535          "        :";genProxyNames(str, "",NULL, "(aid,CK_DELCTOR_ARGS)", ", ");str<<" {}\n";
1536     str <<"    "<<ptype<<"(const CkArrayID &aid) \n"
1537          "        :";genProxyNames(str, "",NULL, "(aid)", ", ");str<<" {}\n";
1538   }
1539   else if (forElement==forSection)
1540   { /* for Section, indexible version*/
1541     disambig_array(str, super);
1542     str << "\n    inline void ckSend(CkArrayMessage *m, int ep, int opts = 0)"
1543         << "\n    { " << super << "::ckSend(m,ep,opts); }"
1544         << "\n    inline CkSectionInfo &ckGetSectionInfo()"
1545         << "\n    { return " << super << "::ckGetSectionInfo(); }"
1546         << "\n    inline CkSectionID *ckGetSectionIDs()"
1547         << "\n    { return " << super << "::ckGetSectionIDs(); }"
1548         << "\n    inline CkSectionID &ckGetSectionID()"
1549         << "\n    { return " << super << "::ckGetSectionID(); }"
1550         << "\n    inline CkSectionID &ckGetSectionID(int i)"
1551         << "\n    { return " << super << "::ckGetSectionID(i); }"
1552         << "\n    inline CkArrayID ckGetArrayIDn(int i) const"
1553         << "\n    { return " << super << "::ckGetArrayIDn(i); } "
1554         << "\n    inline CkArrayIndex *ckGetArrayElements() const"
1555         << "\n    { return " << super << "::ckGetArrayElements(); }"
1556         << "\n    inline CkArrayIndex *ckGetArrayElements(int i) const"
1557         << "\n    { return " << super << "::ckGetArrayElements(i); }"
1558         << "\n    inline int ckGetNumElements() const"
1559         << "\n    { return " << super << "::ckGetNumElements(); } "
1560         << "\n    inline int ckGetNumElements(int i) const"
1561         << "\n    { return " << super << "::ckGetNumElements(i); }";
1562
1563     XStr etype; etype<<Prefix::ProxyElement<<type<<tvars();
1564     if (indexSuffix!=(const char*)"none")
1565     {
1566       str <<
1567     "    // Generalized array indexing:\n"
1568     "    "<<etype<<" operator [] (const "<<indexType<<" &idx) const\n"
1569     "        {return "<<etype<<"(ckGetArrayID(), idx, CK_DELCTOR_CALL);}\n"
1570     "    "<<etype<<" operator() (const "<<indexType<<" &idx) const\n"
1571     "        {return "<<etype<<"(ckGetArrayID(), idx, CK_DELCTOR_CALL);}\n";
1572     }
1573
1574   //Add specialized indexing for these common types
1575     if (indexSuffix==(const char*)"1D")
1576     {
1577     str <<
1578     "    "<<etype<<" operator [] (int idx) const \n"
1579     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex1D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1580     "    "<<etype<<" operator () (int idx) const \n"
1581     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex1D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1582     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex1D *elems, int nElems) {\n"
1583     "      return CkSectionID(aid, elems, nElems);\n"
1584     "    } \n"
1585     "    static CkSectionID ckNew(const CkArrayID &aid, int l, int u, int s) {\n"
1586     "      CkVec<CkArrayIndex1D> al;\n"
1587     "      for (int i=l; i<=u; i+=s) al.push_back(CkArrayIndex1D(i));\n"
1588     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1589     "    } \n";
1590     } else if (indexSuffix==(const char*)"2D") {
1591     str <<
1592     "    "<<etype<<" operator () (int idx) const \n"
1593     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex2D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1594     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex2D *elems, int nElems) {\n"
1595     "      return CkSectionID(aid, elems, nElems);\n"
1596     "    } \n"
1597     "    static CkSectionID ckNew(const CkArrayID &aid, int l1, int u1, int s1, int l2, int u2, int s2) {\n"
1598     "      CkVec<CkArrayIndex2D> al;\n"
1599     "      for (int i=l1; i<=u1; i+=s1) \n"
1600     "        for (int j=l2; j<=u2; j+=s2) \n"
1601     "          al.push_back(CkArrayIndex2D(i, j));\n"
1602     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1603     "    } \n";
1604     } else if (indexSuffix==(const char*)"3D") {
1605     str <<
1606     "    "<<etype<<" operator () (int idx) const \n"
1607     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex3D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1608     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex3D *elems, int nElems) {\n"
1609     "      return CkSectionID(aid, elems, nElems);\n"
1610     "    } \n"
1611     "    static CkSectionID ckNew(const CkArrayID &aid, int l1, int u1, int s1, int l2, int u2, int s2, int l3, int u3, int s3) {\n"
1612     "      CkVec<CkArrayIndex3D> al;\n"
1613     "      for (int i=l1; i<=u1; i+=s1) \n"
1614     "        for (int j=l2; j<=u2; j+=s2) \n"
1615     "          for (int k=l3; k<=u3; k+=s3) \n"
1616     "          al.push_back(CkArrayIndex3D(i, j, k));\n"
1617     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1618     "    } \n";
1619     } else if (indexSuffix==(const char*)"4D") {
1620     str <<
1621     "    "<<etype<<" operator () (int idx) const \n"
1622     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex4D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1623     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex4D *elems, int nElems) {\n"
1624     "      return CkSectionID(aid, elems, nElems);\n"
1625     "    } \n"
1626     "    static CkSectionID ckNew(const CkArrayID &aid, int l1, int u1, int s1, int l2, int u2, int s2, int l3, int u3, int s3, int l4, int u4, int s4) {\n"
1627     "      CkVec<CkArrayIndex4D> al;\n"
1628     "      for (int i=l1; i<=u1; i+=s1) \n"
1629     "        for (int j=l2; j<=u2; j+=s2) \n"
1630     "          for (int k=l3; k<=u3; k+=s3) \n"
1631     "            for (int l=l4; l<=u4; l+=s4) \n"
1632     "              al.push_back(CkArrayIndex4D(i, j, k, l));\n"
1633     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1634     "    } \n";
1635     } else if (indexSuffix==(const char*)"5D") {
1636     str <<
1637     "    "<<etype<<" operator () (int idx) const \n"
1638     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex5D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1639     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex5D *elems, int nElems) {\n"
1640     "      return CkSectionID(aid, elems, nElems);\n"
1641     "    } \n"
1642     "    static CkSectionID ckNew(const CkArrayID &aid, int l1, int u1, int s1, int l2, int u2, int s2, int l3, int u3, int s3, int l4, int u4, int s4, int l5, int u5, int s5) {\n"
1643     "      CkVec<CkArrayIndex5D> al;\n"
1644     "      for (int i=l1; i<=u1; i+=s1) \n"
1645     "        for (int j=l2; j<=u2; j+=s2) \n"
1646     "          for (int k=l3; k<=u3; k+=s3) \n"
1647     "            for (int l=l4; l<=u4; l+=s4) \n"
1648     "              for (int m=l5; m<=u5; m+=s5) \n"
1649     "                al.push_back(CkArrayIndex5D(i, j, k, l, m));\n"
1650     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1651     "    } \n";
1652     } else if (indexSuffix==(const char*)"6D") {
1653     str <<
1654     "    "<<etype<<" operator () (int idx) const \n"
1655     "        {return "<<etype<<"(ckGetArrayID(), *(CkArrayIndex6D*)&ckGetArrayElements()[idx], CK_DELCTOR_CALL);}\n"
1656     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex6D *elems, int nElems) {\n"
1657     "      return CkSectionID(aid, elems, nElems);\n"
1658     "    } \n"
1659     "    static CkSectionID ckNew(const CkArrayID &aid, int l1, int u1, int s1, int l2, int u2, int s2, int l3, int u3, int s3, int l4, int u4, int s4, int l5, int u5, int s5, int l6, int u6, int s6) {\n"
1660     "      CkVec<CkArrayIndex6D> al;\n"
1661     "      for (int i=l1; i<=u1; i+=s1) \n"
1662     "        for (int j=l2; j<=u2; j+=s2) \n"
1663     "          for (int k=l3; k<=u3; k+=s3) \n"
1664     "            for (int l=l4; l<=u4; l+=s4) \n"
1665     "              for (int m=l5; m<=u5; m+=s5) \n"
1666     "                for (int n=l6; n<=u6; n+=s6) \n"
1667     "                  al.push_back(CkArrayIndex6D(i, j, k, l, m, n));\n"
1668     "      return CkSectionID(aid, al.getVec(), al.size());\n"
1669     "    } \n";
1670     }
1671
1672     str <<"    "<<ptype<<"(const CkArrayID &aid, CkArrayIndex *elems, int nElems, CK_DELCTOR_PARAM) \n"
1673          "        :";genProxyNames(str, "",NULL, "(aid,elems,nElems,CK_DELCTOR_ARGS)", ", ");str << " {}\n";
1674     str <<"    "<<ptype<<"(const CkArrayID &aid, CkArrayIndex *elems, int nElems) \n"
1675          "        :";genProxyNames(str, "",NULL, "(aid,elems,nElems)", ", ");str<<" {}\n";
1676     str <<"    "<<ptype<<"(const CkSectionID &sid)"
1677           "       :";genProxyNames(str, "",NULL, "(sid)", ", ");str<< " {}\n";
1678         str <<"    "<<ptype<<"(int n, const CkArrayID *aid, CkArrayIndex const * const *elems, const int *nElems, CK_DELCTOR_PARAM) \n"
1679           "        :";genProxyNames(str, "",NULL, "(n,aid,elems,nElems,CK_DELCTOR_ARGS)", ", ");str << " {}\n";
1680         str <<"    "<<ptype<<"(int n, const CkArrayID *aid, CkArrayIndex const * const *elems, const int *nElems) \n"
1681           "        :";genProxyNames(str, "",NULL, "(n,aid,elems,nElems)", ", ");str<<" {}\n";
1682     str <<
1683     "    static CkSectionID ckNew(const CkArrayID &aid, CkArrayIndex *elems, int nElems) {\n"
1684     "      return CkSectionID(aid, elems, nElems);\n"
1685     "    } \n";
1686   }
1687
1688   if(list){
1689     list->genDecls(str);
1690   }
1691   str << CIClassEnd;
1692   if (!isTemplated()) str << "PUPmarshall("<<ptype<<")\n";
1693 }
1694
1695 void
1696 Chare::genTypedefs(XStr &str) {
1697    str << "    typedef "<<baseName(1)<<" local_t;\n";
1698    str << "    typedef "<<Prefix::Index<<baseName(1)<<" index_t;\n";
1699    str << "    typedef "<<Prefix::Proxy<<baseName(1)<<" proxy_t;\n";
1700
1701    if (hasElement)
1702      str << "    typedef "<<Prefix::ProxyElement<<baseName(1)<<" element_t;\n";
1703    else /* !hasElement, so generic proxy is element type */
1704      str << "    typedef "<<Prefix::Proxy<<baseName(1)<<" element_t;\n";
1705
1706    if (hasSection)
1707      str << "    typedef "<<Prefix::ProxySection<<baseName(1)<<" section_t;\n";
1708    str << "\n";
1709 }
1710
1711
1712
1713 void
1714 Chare::genDefs(XStr& str)
1715 {
1716   str << "/* DEFS: "; print(str); str << " */\n";
1717   if (fortranMode) { // For Fortran90
1718     if (!isArray()) { // Currently, only arrays are supported
1719       cerr << (char *)baseName() << ": only chare arrays are currently supported\n";
1720       exit(1);
1721     }
1722     // We have to generate the chare array itself
1723     str << "/* FORTRAN */\n";
1724     str << "extern \"C\" void " << fortranify(baseName(), "_allocate") << "(char **, void *, " << indexList() << ");\n";
1725     str << "extern \"C\" void " << fortranify(baseName(), "_pup") << "(pup_er p, char **, void *);\n";
1726     str << "extern \"C\" void " << fortranify(baseName(), "_resumefromsync") << "(char **, void *, " << indexList() << ");\n";
1727     str << "\n";
1728     XStr dim = ((Array*)this)->dim();
1729     str << "class " << baseName() << " : public ArrayElement" << dim << "\n";
1730     str << "{\n";
1731     str << "public:\n";
1732     str << "  char user_data[64];\n";
1733     str << "public:\n";
1734     str << "  " << baseName() << "()\n";
1735     str << "  {\n";
1736 //    str << "    CkPrintf(\"" << baseName() << " %d created\\n\",thisIndex);\n";
1737     str << "    CkArrayID *aid = &thisArrayID;\n";
1738     if (dim==(const char*)"1D")
1739       str << "    " << fortranify(baseName(), "_allocate") << "((char **)&user_data, &aid, &thisIndex);\n";
1740     else if (dim==(const char*)"2D")
1741       str << "    " << fortranify(baseName(), "_allocate") << "((char **)&user_data, &aid, &thisIndex.x, &thisIndex.y);\n";
1742     else if (dim==(const char*)"3D")
1743       str << "    " << fortranify(baseName(), "_allocate") << "((char **)&user_data, &aid, &thisIndex.x, &thisIndex.y, &thisIndex.z);\n";
1744     str << "      usesAtSync = CmiTrue;\n";
1745     str << "  }\n";
1746     str << "\n";
1747     str << "  " << baseName() << "(CkMigrateMessage *m)\n";
1748     str << "  {\n";
1749     str << "    /* CkPrintf(\"" << baseName() << " %d migrating\\n\",thisIndex);*/ \n";
1750     str << "  }\n";
1751     str << "\n";
1752
1753     str << "  virtual void pup(PUP::er &p)\n";
1754     str << "  {\n";
1755     str << "    ArrayElement" << dim << "::pup(p);\n";
1756     str << "    p(user_data, 64);\n";
1757     str << "    CkArrayID *aid = &thisArrayID;\n";
1758     str << "    ::" << fortranify(baseName(), "_pup") << "(&p, (char **)&user_data, &aid); \n";
1759     str << "  }\n";
1760     str << "\n";
1761
1762       // Define the Fortran interface function for ResumeFromSync
1763     str << "  void ResumeFromSync()\n";
1764     str << "  {\n";
1765     str << "    CkArrayID *aid = &thisArrayID;\n";
1766     str << "    ::" << fortranify(baseName(), "_resumefromSync");
1767     if (dim == (const char*)"1D") {
1768       str << "((char **)&user_data, &aid, &thisIndex);\n";
1769     }
1770     else if (dim == (const char*)"2D") {
1771       str << "((char **)&user_data, &aid, &thisIndex.x, &thisIndex.y);\n";
1772     }
1773     else if (dim == (const char*)"3D") {
1774       str << "((char **)&user_data, &aid, &thisIndex.x, &thisIndex.y, &thisIndex.z);\n";
1775     }
1776     str << "  }\n";
1777
1778     str << "};\n";
1779     str << "\n";
1780     if (dim==(const char*)"1D") {
1781       str << "extern \"C\" void " << fortranify(baseName(), "_cknew") << "(int *numElem, long *aindex)\n";
1782       str << "{\n";
1783       str << "    CkArrayID *aid = new CkArrayID;\n";
1784       str << "    *aid = CProxy_" << baseName() << "::ckNew(*numElem); \n";
1785     }
1786     else if (dim==(const char*)"2D") {
1787       str << "extern \"C\" void " << fortranify(baseName(), "_cknew") << "(int *numx, int *numy, long *aindex)\n";
1788       str << "{\n";
1789       str << "    CkArrayID *aid = new CkArrayID;\n";
1790       str << "    *aid = CProxy_" << baseName() << "::ckNew(); \n";
1791       str << "    CProxy_" << baseName() << " p(*aid);\n";
1792       str << "    for (int i=0; i<*numx; i++) \n";
1793       str << "      for (int j=0; j<*numy; j++) \n";
1794       str << "        p[CkArrayIndex2D(i, j)].insert(); \n";
1795       str << "    p.doneInserting(); \n";
1796     }
1797     else if (dim==(const char*)"3D") {
1798       str << "extern \"C\" void " << fortranify(baseName(), "_cknew") << "(int *numx, int *numy, int *numz, long *aindex)\n";
1799       str << "{\n";
1800       str << "    CkArrayID *aid = new CkArrayID;\n";
1801       str << "    *aid = CProxy_" << baseName() << "::ckNew(); \n";
1802       str << "    CProxy_" << baseName() << " p(*aid);\n";
1803       str << "    for (int i=0; i<*numx; i++) \n";
1804       str << "      for (int j=0; j<*numy; j++) \n";
1805       str << "        for (int k=0; k<*numz; k++) \n";
1806       str << "          p[CkArrayIndex3D(i, j, k)].insert(); \n";
1807       str << "    p.doneInserting(); \n";
1808     }
1809     str << "    *aindex = (long)aid;\n";
1810     str << "}\n";
1811
1812       // Define the Fortran interface function for AtSync
1813     if (dim == (const char*)"1D") {
1814       str << "extern \"C\" void "
1815           << fortranify(baseName(), "_atsync")
1816           << "(long* aindex, int *index1)\n";
1817       str << "{\n";
1818       str << "  CkArrayID *aid = (CkArrayID *)*aindex;\n";
1819       str << "\n";
1820       str << "  CProxy_" << baseName() << " h(*aid);\n";
1821       str << "  h[*index1].ckLocal()->AtSync();\n";
1822     }
1823     else if (dim == (const char*)"2D") {
1824       str << "extern \"C\" void "
1825           << fortranify(baseName(), "_atsync")
1826           << "(long* aindex, int *index1, int *index2)\n";
1827       str << "{\n";
1828       str << "  CkArrayID *aid = (CkArrayID *)*aindex;\n";
1829       str << "\n";
1830       str << "  CProxy_" << baseName() << " h(*aid);\n";
1831       str << "  h[CkArrayIndex2D(*index1, *index2)].ckLocal()->AtSync();\n";
1832     }
1833     else if (dim == (const char*)"3D") {
1834       str << "extern \"C\" void "
1835           << fortranify(baseName(), "_atsync")
1836           << "(long* aindex, int *index1, int *index2, int *index3)\n";
1837       str << "{\n";
1838       str << "  CkArrayID *aid = (CkArrayID *)*aindex;\n";
1839       str << "\n";
1840       str << "  CProxy_" << baseName() << " h(*aid);\n";
1841       str << "  h[CkArrayIndex3D(*index1, *index2, *index3)].ckLocal()->AtSync();\n";
1842     }
1843     str << "}\n";
1844
1845   }
1846
1847   templateGuardBegin(isTemplated(), str);
1848   if(!type->isTemplated()) {
1849     if(external) str << "extern ";
1850     str << tspec()<<" int "<<indexName()<<"::__idx";
1851     if(!external) str << "=0";
1852     str << ";\n";
1853   }
1854   templateGuardEnd(str);
1855
1856   if(list)
1857   {//Add definitions for all entry points
1858     list->genDefs(str);
1859     if (hasElement)
1860     { //Define the entry points for the element
1861       forElement=forAll;
1862       list->genDefs(str);
1863       if (hasSection) {  // for Section
1864         forElement=forSection;
1865         list->genDefs(str);
1866       }
1867       forElement=forIndividual;
1868     }
1869   }
1870
1871   templateGuardBegin(isTemplated(), str);
1872   // define the python routines
1873   if (isPython()) {
1874     str << "/* ---------------- python wrapper -------------- */\n";
1875
1876     // write CkPy_MethodsCustom
1877     genPythonDefs(str);
1878   }
1879   templateGuardEnd(str);
1880
1881   if(!external && !type->isTemplated())
1882     genRegisterMethodDef(str);
1883   if (hasSdagEntry) {
1884     str << "\n";
1885     str << sdagDefs;
1886   }
1887 }
1888
1889 void
1890 Chare::genReg(XStr& str)
1891 {
1892   str << "/* REG: "; print(str); str << "*/\n";
1893   if(external || templat)
1894     return;
1895   str << "  "<<indexName()<<"::__register(\""<<type<<"\", sizeof("<<type<<"));\n";
1896 }
1897
1898 static const char *CIMsgClassAnsi =
1899 "{\n"
1900 "  public:\n"
1901 "    static int __idx;\n"
1902 "    void* operator new(size_t, void*p) { return p; }\n"
1903 "    void* operator new(size_t);\n"
1904 "    void* operator new(size_t, int*, const int);\n"
1905 "    void* operator new(size_t, int*);\n"
1906 "#if CMK_MULTIPLE_DELETE\n"
1907 "    void operator delete(void*p, void*){dealloc(p);}\n"
1908 "    void operator delete(void*p){dealloc(p);}\n"
1909 "    void operator delete(void*p, int*, const int){dealloc(p);}\n"
1910 "    void operator delete(void*p, int*){dealloc(p);}\n"
1911 "#endif\n"
1912 "    void operator delete(void*p, size_t){dealloc(p);}\n"
1913 "    static void* alloc(int,size_t, int*, int);\n"
1914 "    static void dealloc(void *p);\n"
1915 ;
1916
1917 void
1918 Message::genAllocDecl(XStr &str)
1919 {
1920   int i, num;
1921   XStr mtype;
1922   mtype << type;
1923   if(templat) templat->genVars(mtype);
1924   str << CIMsgClassAnsi;
1925   str << "    CMessage_" << mtype << "();\n";
1926   str << "    static void *pack(" << mtype << " *p);\n";
1927   str << "    static " << mtype << "* unpack(void* p);\n";
1928   num = numArrays();
1929   if(num>0) {
1930     str << "    void *operator new(size_t";
1931     for(i=0;i<num;i++)
1932       str << ", int";
1933     str << ");\n";
1934   }
1935   str << "    void *operator new(size_t, ";
1936   for(i=0;i<num;i++)
1937     str << "int, ";
1938   str << "const int);\n";
1939   str << "#if CMK_MULTIPLE_DELETE\n";
1940   if(num>0) {
1941     str << "    void operator delete(void *p";
1942     for(i=0;i<num;i++)
1943         str << ", int";
1944     str << "){dealloc(p);}\n";
1945   }
1946   str << "    void operator delete(void *p, ";
1947   for(i=0;i<num;i++)
1948     str << "int, ";
1949   str << "const int){dealloc(p);}\n";
1950   str << "#endif\n";
1951 }
1952
1953 void
1954 Message::genDecls(XStr& str)
1955 {
1956   XStr ptype;
1957   ptype<<proxyPrefix()<<type;
1958   if(type->isTemplated())
1959     return;
1960   str << "/* DECLS: "; print(str); str << " */\n";
1961   if(templat)
1962     templat->genSpec(str);
1963   str << "class ";
1964   type->print(str);
1965   str << ";\n";
1966   if(templat)
1967     templat->genSpec(str);
1968   str << "class "<<ptype;
1969   if(external || type->isTemplated()) {
1970     str << ";\n";
1971     return;
1972   }
1973   str << ":public CkMessage";
1974
1975   genAllocDecl(str);
1976
1977   if(!(external||type->isTemplated())) {
1978    // generate register function
1979     str << "    static void __register(const char *s, size_t size, CkPackFnPtr pack, CkUnpackFnPtr unpack) {\n";
1980     str << "      __idx = CkRegisterMsg(s, pack, unpack, dealloc, size);\n";
1981     str << "    }\n";
1982   }
1983   str << "};\n";
1984   
1985   if (strncmp(type->getBaseName(), "MarshallMsg_", 12) == 0) {
1986     MsgVarList *ml;
1987     MsgVar *mv;
1988     int i;
1989     str << "class " << type << " : public " << ptype << " {\n";
1990     str << "  public:\n";
1991     int num = numVars();
1992     for(i=0, ml=mvlist; i<num; i++, ml=ml->next) {
1993       mv = ml->msg_var;
1994       if (mv->isConditional() || mv->isArray()) {
1995         str << "    /* "; mv->print(str); str << " */\n";
1996         str << "    " << mv->type << " *" << mv->name << ";\n";
1997       }
1998     }
1999     str <<"};\n";
2000   }
2001 }
2002
2003 void
2004 Message::genDefs(XStr& str)
2005 {
2006   int i, count, num = numVars();
2007   int numArray = numArrays();
2008   MsgVarList *ml;
2009   MsgVar *mv;
2010   XStr ptype, mtype, tspec;
2011   ptype<<proxyPrefix()<<type;
2012   if(templat) templat->genVars(ptype);
2013   mtype << type;
2014   if(templat) templat->genVars(mtype);
2015   if(templat) { templat->genSpec(tspec); tspec << " "; }
2016
2017   str << "/* DEFS: "; print(str); str << " */\n";
2018
2019   templateGuardBegin(templat, str);
2020   if(!(external||type->isTemplated())) {
2021
2022     // new (size_t)
2023     str << tspec << "void *" << ptype << "::operator new(size_t s){\n";
2024     str << "  return " << mtype << "::alloc(__idx, s, 0, 0);\n}\n";
2025     // new (size_t, int*)
2026     str << tspec << "void *" << ptype << "::operator new(size_t s, int* sz){\n";
2027     str << "  return " << mtype << "::alloc(__idx, s, sz, 0);\n}\n";
2028     // new (size_t, int*, priobits)
2029     str << tspec << "void *" << ptype << "::operator new(size_t s, int* sz,";
2030     str << "const int pb){\n";
2031     str << "  return " << mtype << "::alloc(__idx, s, sz, pb);\n}\n";
2032     // new (size_t, int, int, ..., int)
2033     if(numArray>0) {
2034       str << tspec << "void *" << ptype << "::operator new(size_t s";
2035       for(i=0;i<numArray;i++)
2036         str << ", int sz" << i;
2037       str << ") {\n";
2038       str << "  int sizes[" << numArray << "];\n";
2039       for(i=0;i<numArray;i++)
2040         str << "  sizes[" << i << "] = sz" << i << ";\n";
2041       str << "  return " << mtype << "::alloc(__idx, s, sizes, 0);\n";
2042       str << "}\n";
2043     }
2044     // new (size_t, int, int, ..., int, priobits)
2045     // degenerates to  new(size_t, priobits)  if no varsize
2046     str << tspec << "void *"<< ptype << "::operator new(size_t s, ";
2047     for(i=0;i<numArray;i++)
2048       str << "int sz" << i << ", ";
2049     str << "const int p) {\n";
2050     if (numArray>0) str << "  int sizes[" << numArray << "];\n";
2051     for(i=0, count=0, ml=mvlist ;i<num; i++, ml=ml->next)
2052       if (ml->msg_var->isArray()) {
2053         str << "  sizes[" << count << "] = sz" << count << ";\n";
2054         count ++;
2055       }
2056     str << "  return " << mtype << "::alloc(__idx, s, " << (numArray>0?"sizes":"0") << ", p);\n";
2057     str << "}\n";
2058     // alloc(int, size_t, int*, priobits)
2059     str << tspec << "void* " << ptype;
2060     str << "::alloc(int msgnum, size_t sz, int *sizes, int pb) {\n";
2061     str << "  CkpvAccess(_offsets)[0] = ALIGN8(sz);\n";
2062     for(i=0, count=0, ml=mvlist; i<num; i++, ml=ml->next) {
2063       mv = ml->msg_var;
2064       if (mv->isArray()) {
2065         str << "  if(sizes==0)\n";
2066         str << "    CkpvAccess(_offsets)[" << count+1 << "] = CkpvAccess(_offsets)[0];\n";
2067         str << "  else\n";
2068         str << "    CkpvAccess(_offsets)[" << count+1 << "] = CkpvAccess(_offsets)[" << count << "] + ";
2069         str << "ALIGN8(sizeof(" << mv->type << ")*sizes[" << count << "]);\n";
2070         count ++;
2071       }
2072     }
2073     str << "  return CkAllocMsg(msgnum, CkpvAccess(_offsets)[" << numArray << "], pb);\n";
2074     str << "}\n";
2075
2076     str << tspec << ptype << "::" << proxyPrefix() << type << "() {\n";
2077     str << mtype << " *newmsg = (" << mtype << " *)this;\n";
2078     for(i=0, count=0, ml=mvlist; i<num; i++,ml=ml->next) {
2079       mv = ml->msg_var;
2080       if (mv->isArray()) {
2081         str << "  newmsg->" << mv->name << " = (" << mv->type << " *) ";
2082         str << "((char *)newmsg + CkpvAccess(_offsets)[" << count << "]);\n";
2083         count ++;
2084       }
2085     }
2086     str << "}\n";
2087
2088     int numCond = numConditional();
2089     str << tspec << "void " << ptype << "::dealloc(void *p) {\n";
2090     if (numCond > 0) {
2091       str << "  " << mtype << " *msg = (" << mtype << "*) p;\n";
2092       for(i=0, count=0, ml=mvlist; i<num; i++, ml=ml->next) {
2093         mv = ml->msg_var;
2094         if (mv->isConditional()) {
2095           if (mv->type->isPointer()) die("conditional variable cannot be a pointer", line);
2096           str << "  CkConditional *cond_" << mv->name << " = static_cast<CkConditional*>(msg->" << mv->name << ");\n";
2097           str << "  if (cond_" << mv->name << "!=NULL) cond_" << mv->name << "->deallocate();\n";
2098         }
2099       }
2100     }
2101     str << "  CkFreeMsg(p);\n";
2102     str << "}\n";
2103     // pack
2104     str << tspec << "void* " << ptype << "::pack(" << mtype << " *msg) {\n";
2105     for(i=0, ml=mvlist; i<num; i++, ml=ml->next) {
2106       mv = ml->msg_var;
2107       if (mv->isArray()) {
2108         str << "  msg->" << mv->name << " = (" <<mv->type << " *) ";
2109         str << "((char *)msg->" << mv->name << " - (char *)msg);\n";
2110       }
2111     }
2112     if (numCond > 0) {
2113       str << "  int impl_off[" <<  numCond+1 << "];\n";
2114       str << "  impl_off[0] = UsrToEnv(msg)->getUsersize();\n";
2115       for(i=0, count=0, ml=mvlist; i<num; i++, ml=ml->next) {
2116         mv = ml->msg_var;
2117         if (mv->isConditional()) {
2118           str << "  if (msg->" << mv->name << "!=NULL) { /* conditional packing of ";
2119           mv->type->print(str); str << " " << mv->name << " */\n";
2120           str << "    PUP::sizer implP;\n";
2121           str << "    implP|*msg->" << mv->name << ";\n";
2122           str << "    impl_off[" << count+1 << "] = impl_off[" << count << "] + implP.size();\n";
2123           str << "  } else {\n";
2124           str << "    impl_off[" << count+1 << "] = impl_off[" << count << "];\n";
2125           str << "  }\n";
2126           count ++;
2127         }
2128       }
2129       str << "  " << mtype << " *newmsg = (" << mtype << "*) CkAllocMsg(__idx, impl_off["
2130           << numCond << "], UsrToEnv(msg)->getPriobits());\n";
2131       str << "  envelope *newenv = UsrToEnv(newmsg);\n";
2132       str << "  UInt newSize = newenv->getTotalsize();\n";
2133       str << "  CmiMemcpy(newenv, UsrToEnv(msg), impl_off[0]+sizeof(envelope));\n";
2134       str << "  newenv->setTotalsize(newSize);\n";
2135       str << "  if (UsrToEnv(msg)->getPriobits() > 0) CmiMemcpy(newenv->getPrioPtr(), UsrToEnv(msg)->getPrioPtr(), newenv->getPrioBytes());\n";
2136       for(i=0, count=0, ml=mvlist; i<num; i++, ml=ml->next) {
2137         mv = ml->msg_var;
2138         if (mv->isConditional()) {
2139           str << "  if (msg->" << mv->name << "!=NULL) { /* conditional packing of ";
2140           mv->type->print(str); str << " " << mv->name << " */\n";
2141           str << "    newmsg->" << mv->name << " = ("; mv->type->print(str);
2142           str << "*)(((char*)newmsg)+impl_off[" << count << "]);\n";
2143           str << "    PUP::toMem implP((void *)newmsg->" << mv->name << ");\n";
2144           str << "    implP|*msg->" << mv->name << ";\n";
2145           str << "    newmsg->" << mv->name << " = (" << mv->type << "*) ((char *)newmsg->" << mv->name << " - (char *)newmsg);\n";
2146           str << "  }\n";
2147           count++;
2148         }
2149       }
2150       str << "  CkFreeMsg(msg);\n";
2151       str << "  msg = newmsg;\n";
2152     }
2153     str << "  return (void *) msg;\n}\n";
2154     // unpack
2155     str << tspec << mtype << "* " << ptype << "::unpack(void* buf) {\n";
2156     str << "  " << mtype << " *msg = (" << mtype << " *) buf;\n";
2157     for(i=0, ml=mvlist; i<num; i++, ml=ml->next) {
2158       mv = ml->msg_var;
2159       if (mv->isArray()) {
2160         str << "  msg->" << mv->name << " = (" <<mv->type << " *) ";
2161         str << "((size_t)msg->" << mv->name << " + (char *)msg);\n";
2162       }
2163     }
2164     if (numCond > 0) {
2165       for(i=0, count=0, ml=mvlist; i<num; i++, ml=ml->next) {
2166         mv = ml->msg_var;
2167         if (mv->isConditional()) {
2168           str << "  if (msg->" << mv->name << "!=NULL) { /* conditional packing of ";
2169           mv->type->print(str); str << " " << mv->name << " */\n";
2170           str << "    PUP::fromMem implP((char*)msg + (size_t)msg->" << mv->name << ");\n";
2171           str << "    msg->" << mv->name << " = new " << mv->type << ";\n";
2172           str << "    implP|*msg->" << mv->name << ";\n";
2173           str << "  }\n";
2174           count ++;
2175         }
2176       }
2177     }
2178     str << "  return msg;\n}\n";
2179   }
2180   if(!templat) {
2181     if(!external && !type->isTemplated()) {
2182       str << "int "<< ptype <<"::__idx=0;\n";
2183     }
2184   } else {
2185     str << tspec << "int "<< ptype <<"::__idx=0;\n";
2186   }
2187   templateGuardEnd(str);
2188 }
2189
2190 void
2191 Message::genReg(XStr& str)
2192 {
2193   str << "/* REG: "; print(str); str << "*/\n";
2194   if(!templat && !external) {
2195     XStr ptype, mtype, tspec;
2196     ptype<<proxyPrefix()<<type;
2197     str << ptype << "::__register(\"" << type << "\", sizeof(" << type <<"),";
2198     str << "(CkPackFnPtr) " << type << "::pack,";
2199     str << "(CkUnpackFnPtr) " << type << "::unpack);\n";
2200   }
2201 }
2202
2203 void
2204 Template::setExtern(int e)
2205 {
2206   Construct::setExtern(e);
2207   entity->setExtern(e);
2208 }
2209
2210 void
2211 Template::genVars(XStr& str)
2212 {
2213   str << " < ";
2214   if(tspec)
2215     tspec->genShort(str);
2216   str << " > ";
2217 }
2218
2219 XStr generateTemplateSpec(TVarList* tspec)
2220 {
2221   XStr str;
2222
2223   if(tspec) {
2224     str << "template < ";
2225     tspec->genLong(str);
2226     str << " > ";
2227   }
2228
2229   return str;
2230 }
2231
2232 void
2233 Template::genSpec(XStr& str)
2234 {
2235   str << generateTemplateSpec(tspec);
2236 }
2237
2238 void
2239 Template::genPub(XStr& declstr, XStr& defstr, XStr& defconstr, int& connectPresent)
2240 {
2241   if(!external && entity) {
2242     entity->genPub(declstr, defstr, defconstr, connectPresent);
2243   }
2244 }
2245
2246 void
2247 Template::genDecls(XStr& str)
2248 {
2249   if(!external && entity) {
2250     entity->genDecls(str);
2251   }
2252 }
2253
2254 void
2255 Template::genDefs(XStr& str)
2256 {
2257   if(!external && entity)
2258     entity->genDefs(str);
2259 }
2260
2261 int Template::genAccels_spe_c_funcBodies(XStr& str) {
2262   int rtn = 0;
2263   if (!external && entity) { rtn += entity->genAccels_spe_c_funcBodies(str); }
2264   return rtn;
2265 }
2266
2267 void Template::genAccels_spe_c_regFuncs(XStr& str) {
2268   if (!external && entity) { entity->genAccels_spe_c_regFuncs(str); }
2269 }
2270
2271 void Template::genAccels_spe_c_callInits(XStr& str) {
2272   if (!external && entity) { entity->genAccels_spe_c_callInits(str); }
2273 }
2274
2275 void Template::genAccels_spe_h_includes(XStr& str) {
2276   if (!external && entity) { entity->genAccels_spe_h_includes(str); }
2277 }
2278
2279 void Template::genAccels_spe_h_fiCountDefs(XStr& str) {
2280   if (!external && entity) { entity->genAccels_spe_h_fiCountDefs(str); }
2281 }
2282
2283 void Template::genAccels_ppe_c_regFuncs(XStr& str) {
2284   if (!external && entity) { entity->genAccels_ppe_c_regFuncs(str); }
2285 }
2286
2287 void
2288 TVarList::genLong(XStr& str)
2289 {
2290   if(tvar)
2291     tvar->genLong(str);
2292   if(next) {
2293     str << ", ";
2294     next->genLong(str);
2295   }
2296 }
2297
2298 void
2299 TVarList::genShort(XStr& str)
2300 {
2301   if(tvar)
2302     tvar->genShort(str);
2303   if(next) {
2304     str << ", ";
2305     next->genShort(str);
2306   }
2307 }
2308
2309 void TType::genLong(XStr& str)
2310 {
2311   str << "class ";
2312   if(type)
2313     type->print(str);
2314   if(init) {
2315     str << "=";
2316     init->print(str);
2317   }
2318 }
2319
2320 void TType::genShort(XStr& str)
2321 {
2322   if(type)
2323     type->print(str);
2324 }
2325
2326 void TName::genLong(XStr& str)
2327 {
2328   if(type)
2329     type->print(str);
2330   str << " "<<name;
2331   if(val) {
2332     str << "="<<val;
2333   }
2334 }
2335
2336 void TName::genShort(XStr& str)
2337 {
2338   str << name;
2339 }
2340
2341 void
2342 Module::genPub(XStr& declstr, XStr& defstr, XStr& defconstr, int& connectPresent)
2343 {
2344   if(!external) {
2345     if (clist) clist->genPub(declstr, defstr, defconstr, connectPresent);
2346   }
2347 }
2348
2349
2350 void
2351 Module::genDecls(XStr& str)
2352 {
2353   if(external) {
2354     str << "#include \""<<name<<".decl.h\"\n";
2355   } else {
2356     if (clist) clist->genDecls(str);
2357   }
2358
2359   #if CMK_CELL != 0
2360     str << "extern int register_accel_spe_funcs__module_" << name << "(int curIndex);\n";
2361     if (isMain()) {
2362       str << "extern \"C\" void register_accel_spe_funcs(void);\n";
2363     }
2364   #endif
2365 }
2366
2367 void
2368 Module::genDefs(XStr& str)
2369 {
2370   if(!external)
2371     if (clist)
2372       clist->genDefs(str);
2373
2374   // DMK - Accel Support
2375   #if CMK_CELL != 0
2376
2377     if (!external) {
2378       templateGuardBegin(false, str);
2379
2380       // Create the registration function
2381       // NOTE: Add a check so modules won't register more than once.  It is possible that to modules
2382       //   could have 'extern' references to each other, creating infinite loops in the registration
2383       //   process.  Avoid this problem.
2384       str << "int register_accel_spe_funcs__module_" << name << "(int curIndex) {\n"
2385           << "  static int hasAlreadyRegisteredFlag = 0;\n"
2386           << "  if (hasAlreadyRegisteredFlag) { return curIndex; };\n"
2387           << "  hasAlreadyRegisteredFlag = 1;\n";
2388       genAccels_ppe_c_regFuncs(str);
2389       str << "  return curIndex;\n"
2390           << "}\n";
2391
2392       // Check to see if this is the main module (create top register function if so)
2393       if (isMain()) {
2394         str << "#include\"spert.h\"\n"  // NOTE: Make sure SPE_FUNC_INDEX_USER is defined
2395             << "extern \"C\" void register_accel_spe_funcs(void) {\n"
2396             << "  register_accel_spe_funcs__module_" << name << "(SPE_FUNC_INDEX_USER);\n"
2397             << "}\n";
2398       }
2399
2400       templateGuardEnd(str);
2401     }
2402
2403   #endif
2404 }
2405
2406 void
2407 Module::genReg(XStr& str)
2408 {
2409   if(external) {
2410     str << "  _register"<<name<<"();"<<endx;
2411   } else {
2412     if (clist) clist->genDefs(str);
2413   }
2414 }
2415
2416
2417 int Module::genAccels_spe_c_funcBodies(XStr& str) {
2418
2419   // If this is an external module decloration, just place an include
2420   if (external) {
2421     str << "#include \"" << name << ".genSPECode.c\"\n";
2422     return 0;
2423   }
2424
2425   // If this is the main module, generate the function lookup table
2426   if (isMain()) {
2427     str << "typedef void(*AccelFuncPtr)(DMAListEntry*);\n\n"
2428         << "typedef struct __func_lookup_table_entry {\n"
2429         << "  int funcIndex;\n"
2430         << "  AccelFuncPtr funcPtr;\n"
2431         << "} FuncLookupTableEntry;\n\n"
2432         << "FuncLookupTableEntry funcLookupTable[MODULE_" << name << "_FUNC_INDEX_COUNT];\n\n\n";
2433   }
2434
2435   // Process each of the sub-constructs
2436   int rtn = 0;
2437   if (clist) { rtn += clist->genAccels_spe_c_funcBodies(str); }
2438
2439   // Create the accelerated function registration function for accelerated entries local to this module
2440   // NOTE: Add a check so modules won't register more than once.  It is possible that to modules
2441   //   could have 'extern' references to each other, creating infinite loops in the registration
2442   //   process.  Avoid this problem.
2443   str << "int register_accel_funcs_" << name << "(int curIndex) {\n"
2444       << "  static int hasAlreadyRegisteredFlag = 0;\n"
2445       << "  if (hasAlreadyRegisteredFlag) { return curIndex; };\n"
2446       << "  hasAlreadyRegisteredFlag = 1;\n";
2447   genAccels_spe_c_regFuncs(str);
2448   str << "  return curIndex;\n"
2449       << "}\n\n\n";
2450
2451   // If this is the main module, generate the funcLookup function
2452   if (isMain()) {
2453
2454     str << "\n\n";
2455     str << "#ifdef __cplusplus\n"
2456         << "extern \"C\"\n"
2457         << "#endif\n"
2458         << "void funcLookup(int funcIndex,\n"
2459         << "                void* readWritePtr, int readWriteLen,\n"
2460         << "                void* readOnlyPtr, int readOnlyLen,\n"
2461         << "                void* writeOnlyPtr, int writeOnlyLen,\n"
2462         << "                DMAListEntry* dmaList\n"
2463         << "               ) {\n\n";
2464
2465     str << "  if ((funcIndex >= SPE_FUNC_INDEX_USER) && (funcIndex < (SPE_FUNC_INDEX_USER + MODULE_" << name << "_FUNC_INDEX_COUNT))) {\n"
2466
2467         //<< "    // DMK - DEBUG\n"
2468         //<< "    printf(\"[DEBUG-ACCEL] :: [SPE_%d] - Calling funcIndex %d...\\n\", (int)getSPEID(), funcIndex);\n"
2469
2470         << "    (funcLookupTable[funcIndex - SPE_FUNC_INDEX_USER].funcPtr)(dmaList);\n"
2471         << "  } else if (funcIndex == SPE_FUNC_INDEX_INIT) {\n"
2472         << "    if (register_accel_funcs_" << name << "(0) != MODULE_" << name << "_FUNC_INDEX_COUNT) {\n"
2473         << "      printf(\"ERROR : register_accel_funcs_" << name << "() returned an invalid value.\\n\");\n"
2474         << "    };\n";
2475     genAccels_spe_c_callInits(str);
2476     str << "  } else if (funcIndex == SPE_FUNC_INDEX_CLOSE) {\n"
2477         << "    // NOTE : Do nothing on close, but handle case...\n"
2478         << "  } else {\n"
2479         << "    printf(\"ERROR : Unknown funcIndex (%d) passed to funcLookup()... ignoring.\\n\", funcIndex);\n"
2480         << "  }\n";
2481
2482     str << "}\n";
2483   }
2484
2485   return rtn;
2486 }
2487
2488 void Module::genAccels_spe_c_regFuncs(XStr& str) {
2489   if (external) {
2490     str << "  curIndex = register_accel_funcs_" << name << "(curIndex);\n";
2491   } else {
2492     if (clist) { clist->genAccels_spe_c_regFuncs(str); }
2493   }
2494 }
2495
2496 void Module::genAccels_spe_c_callInits(XStr& str) {
2497   if (clist) { clist->genAccels_spe_c_callInits(str); }
2498 }
2499
2500 void Module::genAccels_spe_h_includes(XStr& str) {
2501   if (external) {
2502     str << "#include \"" << name << ".genSPECode.h\"\n";
2503   }
2504   if (clist) { clist->genAccels_spe_h_includes(str); }
2505 }
2506
2507 void Module::genAccels_spe_h_fiCountDefs(XStr& str) {
2508   if (external) {
2509     str << " + MODULE_" << name << "_FUNC_INDEX_COUNT";
2510   }
2511   if (clist) { clist->genAccels_spe_h_fiCountDefs(str); }
2512 }
2513
2514 void Module::genAccels_ppe_c_regFuncs(XStr& str) {
2515   if (external) {
2516     str << "  curIndex = register_accel_spe_funcs__module_" << name << "(curIndex);\n";
2517   } else {
2518     if (clist) { clist->genAccels_ppe_c_regFuncs(str); }
2519   }
2520 }
2521
2522 void
2523 Readonly::genDecls(XStr& str)
2524 {
2525   str << "/* DECLS: "; print(str); str << " */\n";
2526 }
2527
2528 void
2529 Readonly::genIndexDecls(XStr& str)
2530 {
2531   str << "/* DECLS: "; print(str); str << " */\n";
2532 }
2533
2534 //Turn this string into a valid identifier
2535 XStr makeIdent(const XStr &in)
2536 {
2537   XStr ret;
2538   const char *i=in.get_string_const();
2539   while (*i!=0) {
2540     //Quote all "special" characters
2541     if (*i==':') ret<<"_QColon_";
2542     else if (*i==' ') ret<<"_QSpace_";
2543     else if (*i=='+') ret<<"_QPlus_";
2544     else if (*i=='-') ret<<"_QMinus_";
2545     else if (*i=='*') ret<<"_QTimes_";
2546     else if (*i=='/') ret<<"_QSlash_";
2547     else if (*i=='%') ret<<"_QPercent_";
2548     else if (*i=='&') ret<<"_QAmpersand_";
2549     else if (*i=='.') ret<<"_QDot_";
2550     else if (*i==',') ret<<"_QComma_";
2551     else if (*i=='\'') ret<<"_QSQuote_";
2552     else if (*i=='\"') ret<<"_QQuote_";
2553     else if (*i=='(') ret<<"_QLparen_";
2554     else if (*i==')') ret<<"_QRparen_";
2555     else if (*i=='<') ret<<"_QLess_";
2556     else if (*i=='>') ret<<"_QGreater_";
2557     else if (*i=='{') ret<<"_QLbrace_";
2558     else if (*i=='}') ret<<"_QRbrace_";
2559     else ret << *i; //Copy character unmodified
2560     i++; //Advance to next
2561   }
2562   return ret;
2563 }
2564
2565 void
2566 Readonly::genDefs(XStr& str)
2567 {
2568   str << "/* DEFS: "; print(str); str << " */\n";
2569   if(!container && !strchr(name, ':')) {
2570     str << "extern ";
2571     type->print(str);
2572     if(msg)
2573       str << "*";
2574     str << " "<<name;
2575     if(dims)
2576       dims->print(str);
2577     str << ";\n";
2578   }
2579
2580   if (!msg) { //Generate a pup for this readonly
2581     templateGuardBegin(false, str);
2582     str << "extern \"C\" void __xlater_roPup_"<<makeIdent(qName());
2583     str <<    "(void *_impl_pup_er) {\n";
2584     str << "  PUP::er &_impl_p=*(PUP::er *)_impl_pup_er;\n";
2585     if(dims){
2586             str << "  _impl_p("<<qName()<<","; dims->printValue(str); str<<");\n";
2587     }else{
2588             str << "  _impl_p|"<<qName()<<";\n";
2589     }
2590     str << "}\n";
2591     templateGuardEnd(str);
2592   }
2593
2594   if (fortranMode) {
2595       str << "extern \"C\" void "
2596           << fortranify("set_", name)
2597           << "(int *n) { " << name << " = *n; }\n";
2598       str << "extern \"C\" void "
2599           << fortranify("get_", name)
2600           << "(int *n) { *n = " << name << "; }\n";
2601   }
2602 }
2603
2604 void
2605 Readonly::genReg(XStr& str)
2606 {
2607   if(external)
2608     return;
2609   if(msg) {
2610     if(dims) die("readonly Message cannot be an array",line);
2611     str << "  CkRegisterReadonlyMsg(\""<<qName()<<"\",\""<<type<<"\",";
2612     str << "(void **)&"<<qName()<<");\n";
2613   } else {
2614     str << "  CkRegisterReadonly(\""<<qName()<<"\",\""<<type<<"\",";
2615     str << "sizeof("<<qName()<<"),(void *) &"<<qName()<<",";
2616     str << "__xlater_roPup_"<<makeIdent(qName())<<");\n";
2617   }
2618 }
2619
2620 void TParamList::genSpec(XStr& str)
2621 {
2622   if(tparam)
2623     tparam->genSpec(str);
2624   if(next) {
2625     str << ", ";
2626     next->genSpec(str);
2627   }
2628 }
2629
2630 void MemberList::genIndexDecls(XStr& str)
2631 {
2632     perElemGen(members, str, &Member::genIndexDecls, newLine);
2633 }
2634
2635 void MemberList::genPub(XStr& declstr, XStr& defstr, XStr& defconstr, int& connectPresent)
2636 {
2637     for (list<Member*>::iterator i = members.begin(); i != members.end(); ++i)
2638         if (*i) {
2639             (*i)->genPub(declstr, defstr, defconstr, connectPresent);
2640             declstr << endx;
2641         }
2642 }
2643
2644 void MemberList::genDecls(XStr& str)
2645 {
2646     perElemGen(members, str, &Member::genDecls, newLine);
2647 }
2648
2649 void MemberList::collectSdagCode(CParsedFile *pf, int& sdagPresent)
2650 {
2651     for (list<Member*>::iterator i = members.begin(); i != members.end(); ++i)
2652         if (*i)
2653             (*i)->collectSdagCode(pf, sdagPresent);
2654 }
2655
2656 void MemberList::genDefs(XStr& str)
2657 {
2658     perElemGen(members, str, &Member::genDefs, newLine);
2659 }
2660
2661 void MemberList::genReg(XStr& str)
2662 {
2663     perElemGen(members, str, &Member::genReg, newLine);
2664 }
2665
2666 void MemberList::preprocess()
2667 {
2668     for (list<Member*>::iterator i = members.begin(); i != members.end(); ++i)
2669         if (*i)
2670             (*i)->preprocess();
2671 }
2672
2673 void MemberList::lookforCEntry(CEntry *centry)
2674 {
2675     perElemGen(members, centry, &Member::lookforCEntry);
2676 }
2677
2678 void MemberList::genPythonDecls(XStr& str) {
2679     perElemGen(members, str, &Member::genPythonDecls, newLine);
2680 }
2681
2682 void MemberList::genPythonDefs(XStr& str) {
2683     perElemGen(members, str, &Member::genPythonDefs, newLine);
2684 }
2685
2686 void MemberList::genPythonStaticDefs(XStr& str) {
2687     perElemGen(members, str, &Member::genPythonStaticDefs);
2688 }
2689
2690 void MemberList::genPythonStaticDocs(XStr& str) {
2691     perElemGen(members, str, &Member::genPythonStaticDocs);
2692 }
2693
2694 void Entry::lookforCEntry(CEntry *centry)
2695 {
2696    // compare name
2697    if (strcmp(name, *centry->entry) != 0) return;
2698    // compare param
2699    if (param && !centry->paramlist) return;
2700    if (!param && centry->paramlist) return;
2701    if (param && !(*param == *centry->paramlist)) return;
2702
2703    isWhenEntry = 1;
2704    centry->decl_entry = this;
2705 }
2706
2707 void Chare::lookforCEntry(CEntry *centry)
2708 {
2709   if(list)
2710     list->lookforCEntry(centry);
2711   if (centry->decl_entry == NULL)  {
2712     cerr<<"Function \""<<centry->entry->get_string_const()
2713         <<"\" appears in Sdag When construct, but not defined as an entry function. "
2714         << endl;
2715     die("(FATAL ERROR)");
2716   }
2717 }
2718
2719 ///////////////////////////// CPARSEDFILE //////////////////////
2720 /*void CParsedFile::print(int indent)
2721 {
2722   for(CEntry *ce=entryList.begin(); !entryList.end(); ce=entryList.next())
2723   {
2724     ce->print(indent);
2725     printf("\n");
2726   }
2727   for(SdagConstruct *cn=nodeList.begin(); !nodeList.end(); cn=nodeList.next())
2728   {
2729     cn->print(indent);
2730     printf("\n");
2731   }
2732 }
2733 */
2734 XStr *CParsedFile::className = NULL;
2735
2736 void CParsedFile::numberNodes(void)
2737 {
2738   for(Entry *cn=nodeList.begin(); !nodeList.end(); cn=nodeList.next()) {
2739     if (cn->sdagCon != 0) {
2740       cn->sdagCon->numberNodes();
2741     }
2742   }
2743 }
2744
2745 void CParsedFile::labelNodes(void)
2746 {
2747   for(Entry *cn=nodeList.begin(); !nodeList.end(); cn=nodeList.next()) {
2748     if (cn->sdagCon != 0) {
2749       cn->sdagCon->labelNodes();
2750     }
2751   }
2752 }
2753
2754 void CParsedFile::propagateState(void)
2755 {
2756   for(Entry *cn=nodeList.begin(); !nodeList.end(); cn=nodeList.next()) {
2757     cn->sdagCon->propagateState(0);
2758   }
2759 }
2760
2761 void CParsedFile::mapCEntry(void)
2762 {
2763   CEntry *en;
2764   for(en=entryList.begin(); !entryList.end(); en=entryList.next()) {
2765     container->lookforCEntry(en);
2766   }
2767 }
2768
2769 void CParsedFile::generateEntryList(void)
2770 {
2771   for(Entry *cn=nodeList.begin(); !nodeList.end(); cn=nodeList.next()) {
2772     cn->sdagCon->generateEntryList(entryList, 0);
2773   }
2774 }
2775
2776 void CParsedFile::generateConnectEntryList(void)
2777 {
2778   for(Entry *cn=nodeList.begin(); !nodeList.end(); cn=nodeList.next()) {
2779     cn->sdagCon->generateConnectEntryList(connectEntryList);
2780   }
2781 }
2782
2783 void CParsedFile::generateCode(XStr& decls, XStr& defs)
2784 {
2785   for(Entry *cn=nodeList.begin(); !nodeList.end(); cn=nodeList.next()) {
2786     cn->sdagCon->setNext(0,0);
2787     cn->sdagCon->generateCode(decls, defs, cn);
2788   }
2789 }
2790
2791 void CParsedFile::generateEntries(XStr& decls, XStr& defs)
2792 {
2793   CEntry *en;
2794   SdagConstruct *sc;
2795   decls << "public:\n";
2796   for(sc=connectEntryList.begin(); !connectEntryList.end(); sc=connectEntryList.next())
2797      sc->generateConnectEntries(decls);
2798   for(en=entryList.begin(); !entryList.end(); en=entryList.next()) {
2799     en->generateCode(decls, defs);
2800   }
2801 }
2802
2803 void CParsedFile::generateInitFunction(XStr& decls, XStr& defs)
2804 {
2805   decls << "private:\n";
2806   decls << "  CDep *__cDep;\n";
2807
2808   XStr name = "__sdag_init";
2809   generateSignature(decls, defs, container, false, "void", &name, false, NULL);
2810   defs << "    __cDep = new CDep(" << numEntries << "," << numWhens << ");\n";
2811   CEntry *en;
2812   for(en=entryList.begin(); !entryList.end(); en=entryList.next()) {
2813     en->generateDeps(defs);
2814   }
2815   endMethod(defs);
2816 }
2817
2818
2819 /**
2820     Create a merging point for each of the places where multiple
2821     dependencies lead into some future task.
2822
2823     Used by Isaac's critical path detection
2824 */
2825 void CParsedFile::generateDependencyMergePoints(XStr& decls) 
2826 {
2827   decls << " \n";
2828
2829   // Each when statement will have a set of message dependencies, and
2830   // also the dependencies from completion of previous task
2831   for(int i=0;i<numWhens;i++){
2832     decls << "  MergeablePathHistory _when_" << i << "_PathMergePoint; /* For Critical Path Detection */ \n";
2833   }
2834   
2835   // The end of each overlap block will have multiple paths that merge
2836   // before the subsequent task is executed
2837   for(int i=0;i<numOlists;i++){
2838     decls << "  MergeablePathHistory olist__co" << i << "_PathMergePoint; /* For Critical Path Detection */ \n";
2839   }
2840 }
2841
2842 void CParsedFile::generatePupFunction(XStr& decls)
2843 {
2844   decls << "public:\n";
2845   decls << "  void __sdag_pup(PUP::er& p) {\n";
2846   decls << "    if (__cDep) { __cDep->pup(p); }\n";
2847   decls << "  }\n";
2848 }
2849
2850 void CParsedFile::generateTrace()
2851 {
2852   for(Entry *cn=nodeList.begin(); !nodeList.end(); cn=nodeList.next()) {
2853     if (cn->sdagCon != 0) {
2854       cn->sdagCon->generateTrace();
2855     }
2856   }
2857 }
2858
2859 void CParsedFile::generateRegisterEp(XStr& decls, XStr& defs)
2860 {
2861   XStr name = "__sdag_register";
2862   generateSignature(decls, defs, container, true, "void", &name, false, NULL);
2863
2864   for(Entry *cn=nodeList.begin(); !nodeList.end(); cn=nodeList.next()) {
2865     if (cn->sdagCon != 0) {
2866       cn->sdagCon->generateRegisterEp(defs);
2867     }
2868   }
2869   endMethod(defs);
2870 }
2871
2872 void CParsedFile::generateTraceEp(XStr& decls, XStr& defs)
2873 {
2874   for(Entry *cn=nodeList.begin(); !nodeList.end(); cn=nodeList.next()) {
2875     if (cn->sdagCon != 0) {
2876       cn->sdagCon->generateTraceEp(decls, defs, container);
2877     }
2878   }
2879 }
2880
2881 ////////////////////////// SDAGCONSTRUCT ///////////////////////
2882 SdagConstruct::SdagConstruct(EToken t, SdagConstruct *construct1)
2883 {
2884   con1 = 0;  con2 = 0; con3 = 0; con4 = 0;
2885   type = t;
2886   traceName=NULL;
2887   publishesList = new TList<SdagConstruct*>();
2888   constructs = new TList<SdagConstruct*>();
2889   constructs->append(construct1);
2890 }
2891
2892 SdagConstruct::SdagConstruct(EToken t, SdagConstruct *construct1, SdagConstruct *aList)
2893 {
2894   con1=0; con2=0; con3=0; con4=0;
2895   type = t;
2896   traceName=NULL;
2897   publishesList = new TList<SdagConstruct*>();
2898   constructs = new TList<SdagConstruct*>();
2899   constructs->append(construct1);
2900   SdagConstruct *sc;
2901   for(sc = aList->constructs->begin(); !aList->constructs->end(); sc=aList->constructs->next())
2902     constructs->append(sc);
2903 }
2904
2905 SdagConstruct::SdagConstruct(EToken t, XStr *txt, SdagConstruct *c1, SdagConstruct *c2, SdagConstruct *c3,
2906                              SdagConstruct *c4, SdagConstruct *constructAppend, EntryList *el)
2907 {
2908   text = txt;
2909   type = t;
2910   traceName=NULL;
2911   con1 = c1; con2 = c2; con3 = c3; con4 = c4;
2912   publishesList = new TList<SdagConstruct*>();
2913   constructs = new TList<SdagConstruct*>();
2914   if (constructAppend != 0) {
2915     constructs->append(constructAppend);
2916   }
2917   elist = el;
2918 }
2919
2920 SdagConstruct::SdagConstruct(EToken t, const char *entryStr, const char *codeStr, ParamList *pl)
2921 {
2922   type = t;
2923   traceName=NULL;
2924   text = new XStr(codeStr);
2925   connectEntry = new XStr(entryStr);
2926   con1 = 0; con2 = 0; con3 = 0; con4 =0;
2927   publishesList = new TList<SdagConstruct*>();
2928   constructs = new TList<SdagConstruct*>();
2929   param = pl;
2930
2931 }
2932
2933 ///////////////////////////// ENTRY ////////////////////////////
2934
2935 void ParamList::checkParamList(){
2936   if(manyPointers){ 
2937     die("You may pass only a single pointer to a non-local entry method. It should point to a message.", param->line);
2938     abort();
2939   }
2940 }
2941
2942 Entry::Entry(int l, int a, Type *r, const char *n, ParamList *p, Value *sz, SdagConstruct *sc, const char *e, int connect, ParamList *connectPList) :
2943       attribs(a), retType(r), stacksize(sz), sdagCon(sc), name((char *)n), targs(0), intExpr(e), param(p), connectParam(connectPList), isConnect(connect)
2944 {
2945   line=l; container=NULL;
2946   entryCount=-1;
2947   isWhenEntry=0;
2948   if (param && param->isMarshalled() && !isThreaded()) attribs|=SNOKEEP;
2949
2950   if(!isThreaded() && stacksize) die("Non-Threaded methods cannot have stacksize",line);
2951   if(retType && !isSync() && !isIget() && !isLocal() && !retType->isVoid())
2952     die("A remote method normally returns void.  To return non-void, you need to declare the method as [sync], which means it has blocking semantics.",line);
2953   if (isPython()) pythonDoc = python_doc;
2954   if(!isLocal() && p){
2955     p->checkParamList();
2956   }
2957
2958 }
2959 void Entry::setChare(Chare *c) {
2960         Member::setChare(c);
2961         // mainchare constructor parameter is not allowed
2962         /* ****************** REMOVED 10/8/2002 ************************
2963         if (isConstructor()&&container->isMainChare() && param != NULL)
2964           if (!param->isCkArgMsgPtr())
2965            die("MainChare Constructor doesn't allow parameter!", line);
2966         Removed old treatment for CkArgMsg to allow argc, argv or void
2967         constructors for mainchares.
2968         * **************************************************************/
2969         if (isConstructor() && container->isMainChare() && param->isVoid()) {
2970           //Main chare always magically takes CkArgMsg
2971           Type *t = new PtrType(new NamedType("CkArgMsg"));
2972           param=new ParamList(new Parameter(line,t));
2973           std::cerr << "Charmxi> " << line << ": Deprecation warning: mainchare constructors should explicitly take CkArgMsg* if that's how they're implemented.\n";
2974         }
2975
2976         entryCount=c->nextEntry();
2977
2978         //Make a special "callmarshall" method, for communication optimizations to use:
2979         hasCallMarshall=param->isMarshalled() && !isThreaded() && !isSync() && !isExclusive() && !fortranMode;
2980         if (isSdag()) container->setSdag(1);
2981 }
2982
2983 // "parameterType *msg" or "void".
2984 // Suitable for use as the only parameter
2985 XStr Entry::paramType(int withDefaultVals,int withEO,int useConst)
2986 {
2987   XStr str;
2988   param->print(str,withDefaultVals,useConst);
2989   if (withEO) str<<eo(withDefaultVals,!param->isVoid());
2990   return str;
2991 }
2992
2993 // "parameterType *msg," if there is a non-void parameter,
2994 // else empty.  Suitable for use with another parameter following.
2995 XStr Entry::paramComma(int withDefaultVals,int withEO)
2996 {
2997   XStr str;
2998   if (!param->isVoid()) {
2999     str << paramType(withDefaultVals,withEO);
3000     str << ", ";
3001   }
3002   return str;
3003 }
3004 XStr Entry::eo(int withDefaultVals,int priorComma) {
3005   XStr str;
3006   if (param->isMarshalled()) {//FIXME: add options for void methods, too...
3007     if (priorComma) str<<", ";
3008     str<<"const CkEntryOptions *impl_e_opts";
3009     if (withDefaultVals) str<<"=NULL";
3010   }
3011   return str;
3012 }
3013
3014 void Entry::collectSdagCode(CParsedFile *pf, int& sdagPresent)
3015 {
3016   if (isSdag()) {
3017     sdagPresent = 1;
3018     pf->nodeList.append(this);
3019   }
3020 }
3021
3022 XStr Entry::marshallMsg(void)
3023 {
3024   XStr ret;
3025   XStr epName = epStr();
3026   param->marshall(ret, epName);
3027   return ret;
3028 }
3029
3030 XStr Entry::epStr(bool isForRedn, bool templateCall)
3031 {
3032   XStr str;
3033   if (isForRedn)
3034     str<<"redn_wrapper_";
3035   str << name << "_";
3036
3037   if (param->isMessage()) {
3038     str<<param->getBaseName();
3039     str.replace(':', '_');
3040   }
3041   else if (param->isVoid())
3042     str<<"void";
3043   else
3044     str<<"marshall"<<entryCount;
3045
3046   if (tspec && templateCall) {
3047     str << "< ";
3048     tspec->genShort(str);
3049     str << " >";
3050   }
3051
3052   return str;
3053 }
3054
3055 XStr Entry::epIdx(int fromProxy, bool isForRedn)
3056 {
3057   XStr str;
3058   if (fromProxy) {
3059     str << indexName()<<"::";
3060     // If the chare is also templated, then we must avoid a parsing ambiguity
3061     if (tspec)
3062       str << "template ";
3063   }
3064   str << "idx_" << epStr(isForRedn, true) << "()";
3065   return str;
3066 }
3067
3068 XStr Entry::epRegFn(int fromProxy, bool isForRedn)
3069 {
3070   XStr str;
3071   if (fromProxy)
3072     str << indexName() << "::";
3073   str << "reg_" << epStr(isForRedn, true) << "()";
3074   return str;
3075 }
3076
3077 XStr Entry::chareIdx(int fromProxy)
3078 {
3079   XStr str;
3080   if (fromProxy)
3081     str << indexName()<<"::";
3082   str << "__idx";
3083   return str;
3084 }
3085
3086 //Return a templated proxy declaration string for
3087 // this Member's container with the given return type, e.g.
3088 // template<int N,class foo> void CProxy_bar<N,foo>
3089 // Works with non-templated Chares as well.
3090 XStr Member::makeDecl(const XStr &returnType, int forProxy, bool isStatic)
3091 {
3092   XStr str;
3093
3094   if (container->isTemplated())
3095     str << container->tspec() << "\n";
3096   str << generateTemplateSpec(tspec) << "\n";
3097   if (isStatic)
3098     str << "static ";
3099   str << returnType<<" ";
3100   if (forProxy)
3101         str<<container->proxyName();
3102   else
3103         str<<container->indexName();
3104   return str;
3105 }
3106
3107 XStr Entry::syncReturn(void) {
3108   XStr str;
3109   if(retType->isVoid())
3110     str << "  CkFreeSysMsg(";
3111   else
3112     str << "  return ("<<retType<<") (";
3113   return str;
3114 }
3115
3116 /*************************** Chare Entry Points ******************************/
3117
3118 void Entry::genChareDecl(XStr& str)
3119 {
3120   if(isConstructor()) {
3121     genChareStaticConstructorDecl(str);
3122   } else {
3123     // entry method declaration
3124     str << "    " << generateTemplateSpec(tspec) << "\n"
3125         << "    " << retType << " " << name << "(" << paramType(1,1) << ");\n";
3126   }
3127 }
3128
3129 void Entry::genChareDefs(XStr& str)
3130 {
3131   if (isImmediate()) {
3132       cerr << (char *)container->baseName() << ": Chare does not allow immediate message.\n";
3133       exit(1);
3134   }
3135   if (isLocal()) {
3136     cerr << (char*)container->baseName() << ": Chare does not allow LOCAL entry methods.\n";
3137     exit(1);
3138   }
3139
3140   if(isConstructor()) {
3141     genChareStaticConstructorDefs(str);
3142   } else {
3143     XStr params; params<<epIdx()<<", impl_msg, &ckGetChareID()";
3144     // entry method definition
3145     XStr retStr; retStr<<retType;
3146     str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1)<<")\n";
3147     str << "{\n  ckCheck();\n"<<marshallMsg();
3148     if(isSync()) {
3149       str << syncReturn() << "CkRemoteCall("<<params<<"));\n";
3150     } else {//Regular, non-sync message
3151       str << "  if (ckIsDelegated()) {\n";
3152       str << "    int destPE=CkChareMsgPrep("<<params<<");\n";
3153       str << "    if (destPE!=-1) ckDelegatedTo()->ChareSend(ckDelegatedPtr(),"<<params<<",destPE);\n";
3154       str << "  }\n";
3155       XStr opts;
3156       opts << ",0";
3157       if (isSkipscheduler())  opts << "+CK_MSG_EXPEDITED";
3158       if (isInline())  opts << "+CK_MSG_INLINE";
3159       str << "  else CkSendMsg("<<params<<opts<<");\n";
3160     }
3161     str << "}\n";
3162   }
3163 }
3164
3165 void Entry::genChareStaticConstructorDecl(XStr& str)
3166 {
3167   str << "    static CkChareID ckNew("<<paramComma(1)<<"int onPE=CK_PE_ANY"<<eo(1)<<");\n";
3168   str << "    static void ckNew("<<paramComma(1)<<"CkChareID* pcid, int onPE=CK_PE_ANY"<<eo(1)<<");\n";
3169   if (!param->isVoid())
3170     str << "    "<<container->proxyName(0)<<"("<<paramComma(1)<<"int onPE=CK_PE_ANY"<<eo(1)<<");\n";
3171 }
3172
3173 void Entry::genChareStaticConstructorDefs(XStr& str)
3174 {
3175   str << makeDecl("CkChareID",1)<<"::ckNew("<<paramComma(0)<<"int impl_onPE"<<eo(0)<<")\n";
3176   str << "{\n"<<marshallMsg();
3177   str << "  CkChareID impl_ret;\n";
3178   str << "  CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, &impl_ret, impl_onPE);\n";
3179   str << "  return impl_ret;\n";
3180   str << "}\n";
3181
3182   str << makeDecl("void",1)<<"::ckNew("<<paramComma(0)<<"CkChareID* pcid, int impl_onPE"<<eo(0)<<")\n";
3183   str << "{\n"<<marshallMsg();
3184   str << "  CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, pcid, impl_onPE);\n";
3185   str << "}\n";
3186
3187   if (!param->isVoid()) {
3188     str << makeDecl(" ",1)<<"::"<<container->proxyName(0)<<"("<<paramComma(0)<<"int impl_onPE"<<eo(0)<<")\n";
3189     str << "{\n"<<marshallMsg();
3190     str << "  CkChareID impl_ret;\n";
3191     str << "  CkCreateChare("<<chareIdx()<<", "<<epIdx()<<", impl_msg, &impl_ret, impl_onPE);\n";
3192     str << "  ckSetChareID(impl_ret);\n";
3193     str << "}\n";
3194   }
3195 }
3196
3197 /***************************** Array Entry Points **************************/
3198
3199 void Entry::genArrayDecl(XStr& str)
3200 {
3201   if(isConstructor()) {
3202     str << "    " << generateTemplateSpec(tspec) << "\n";
3203     genArrayStaticConstructorDecl(str);
3204   } else {
3205     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
3206     str << "    " << generateTemplateSpec(tspec) << "\n";
3207     if(isIget())
3208       str << "    "<<"CkFutureID"<<" "<<name<<"("<<paramType(1,1)<<") ;\n"; //no const
3209     else if(isLocal())
3210       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1,0)<<") ;\n";
3211     else
3212       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1)<<") ;\n"; //no const
3213   }
3214 }
3215
3216 void Entry::genArrayDefs(XStr& str)
3217 {
3218   if(isIget() && !container->isForElement()) return;
3219   if (isImmediate()) {
3220       cerr << (char *)container->baseName() << ": Chare Array does not allow immediate message.\n";
3221       exit(1);
3222   }
3223
3224   if (isConstructor())
3225     genArrayStaticConstructorDefs(str);
3226   else
3227   {//Define array entry method
3228     const char *ifNot="CkArray_IfNotThere_buffer";
3229     if (isCreateHere()) ifNot="CkArray_IfNotThere_createhere";
3230     if (isCreateHome()) ifNot="CkArray_IfNotThere_createhome";
3231
3232     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
3233
3234     XStr retStr; retStr<<retType;
3235     if(isIget())
3236       str << makeDecl("CkFutureID ",1)<<"::"<<name<<"("<<paramType(0,1)<<") \n"; //no const
3237     else if(isLocal())
3238       str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1,0)<<") \n";
3239     else
3240       str << makeDecl(retStr,1)<<"::"<<name<<"("<<paramType(0,1)<<") \n"; //no const
3241     str << "{\n  ckCheck();\n";
3242     if (!isLocal()) {
3243       str << marshallMsg();
3244       str << "  CkArrayMessage *impl_amsg=(CkArrayMessage *)impl_msg;\n";
3245       str << "  impl_amsg->array_setIfNotThere("<<ifNot<<");\n";
3246     } else {
3247       XStr unmarshallStr; param->unmarshall(unmarshallStr);
3248       str << "  LDObjHandle objHandle;\n  int objstopped=0;\n";
3249       str << "  "<<container->baseName()<<" *obj = ckLocal();\n";
3250       str << "#if CMK_ERROR_CHECKING\n";
3251       str << "  if (obj==NULL) CkAbort(\"Trying to call a LOCAL entry method on a non-local element\");\n";
3252       str << "#endif\n";
3253       if (!isNoTrace())
3254           str << "  _TRACE_BEGIN_EXECUTE_DETAILED(0,ForArrayEltMsg," << epIdx()
3255               << ",CkMyPe(), 0, ((CkArrayIndex&)ckGetIndex()).getProjectionID(((CkGroupID)ckGetArrayID()).idx));\n";
3256       str << "#if CMK_LBDB_ON\n  objHandle = obj->timingBeforeCall(&objstopped);\n#endif\n";
3257       str << "#if CMK_CHARMDEBUG\n"
3258       "  CpdBeforeEp("<<epIdx()<<", obj, NULL);\n"
3259       "#endif\n   ";
3260       if (!retType->isVoid()) str << retType<< " retValue = ";
3261       str << "obj->"<<name<<"("<<unmarshallStr<<");\n";
3262       str << "#if CMK_CHARMDEBUG\n"
3263       "  CpdAfterEp("<<epIdx()<<");\n"
3264       "#endif\n";
3265       str << "#if CMK_LBDB_ON\n  obj->timingAfterCall(objHandle,&objstopped);\n#endif\n";
3266       if (!isNoTrace()) str << "  _TRACE_END_EXECUTE();\n";
3267       if (!retType->isVoid()) str << "  return retValue;\n";
3268     }
3269     if(isIget()) {
3270             str << "  CkFutureID f=CkCreateAttachedFutureSend(impl_amsg,"<<epIdx()<<",ckGetArrayID(),ckGetIndex(),&CProxyElement_ArrayBase::ckSendWrapper);"<<"\n";
3271     }
3272
3273     if(isSync()) {
3274       str << syncReturn() << "ckSendSync(impl_amsg, "<<epIdx()<<"));\n";
3275     }
3276     else if (!isLocal())
3277     {
3278       XStr opts;
3279       opts << ",0";
3280       if (isSkipscheduler())  opts << "+CK_MSG_EXPEDITED";
3281       if (isInline())  opts << "+CK_MSG_INLINE";
3282       if(!isIget()) {
3283       if (container->isForElement() || container->isForSection()) {
3284         str << "  ckSend(impl_amsg, "<<epIdx()<<opts<<");\n";
3285       }
3286       else
3287         str << "  ckBroadcast(impl_amsg, "<<epIdx()<<opts<<");\n";
3288       }
3289     }
3290     if(isIget()) {
3291             str << "  return f;\n";
3292     }
3293     str << "}\n";
3294   }
3295 }
3296
3297 void Entry::genArrayStaticConstructorDecl(XStr& str)
3298 {
3299   if (container->getForWhom()==forIndividual)
3300       str<< //Element insertion routine
3301       "    void insert("<<paramComma(1,0)<<"int onPE=-1"<<eo(1)<<");";
3302   else if (container->getForWhom()==forAll) {
3303       str<< //With options
3304       "    static CkArrayID ckNew("<<paramComma(1,0)<<"const CkArrayOptions &opts"<<eo(1)<<");\n";
3305       if (container->isArray()) {
3306         XStr dim = ((Array*)container)->dim();
3307         if (dim==(const char*)"1D") {
3308           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const int s1"<<eo(1)<<");\n";
3309         } else if (dim==(const char*)"2D") {
3310           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const int s1, const int s2"<<eo(1)<<");\n";
3311         } else if (dim==(const char*)"3D") {
3312           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const int s1, const int s2, const int s3"<<eo(1)<<");\n";
3313         /*} else if (dim==(const char*)"4D") {
3314           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4"<<eo(1)<<");\n";
3315         } else if (dim==(const char*)"5D") {
3316           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5"<<eo(1)<<");\n";
3317         } else if (dim==(const char*)"6D") {
3318           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5, const short s6"<<eo(1)<<");\n"; */
3319         }
3320       }
3321   }
3322   else if (container->getForWhom()==forSection) { }
3323 }
3324
3325 void Entry::genArrayStaticConstructorDefs(XStr& str)
3326 {
3327   if (container->getForWhom()==forIndividual)
3328       str<<
3329       makeDecl("void",1)<<"::insert("<<paramComma(0,0)<<"int onPE"<<eo(0)<<")\n"
3330       "{ \n"<<marshallMsg()<<
3331       "   ckInsert((CkArrayMessage *)impl_msg,"<<epIdx()<<",onPE);\n}\n";
3332   else if (container->getForWhom()==forAll){
3333       str<<
3334       makeDecl("CkArrayID",1)<<"::ckNew("<<paramComma(0)<<"const CkArrayOptions &opts"<<eo(0)<<")\n"
3335        "{ \n"<<marshallMsg()<<
3336          "   return ckCreateArray((CkArrayMessage *)impl_msg,"<<epIdx()<<",opts);\n"
3337        "}\n";
3338       if (container->isArray()) {
3339         XStr dim = ((Array*)container)->dim();
3340         if (dim==(const char*)"1D") {
3341           str<<
3342             makeDecl("CkArrayID",1)<<"::ckNew("<<paramComma(0)<<"const int s1"<<eo(0)<<")\n"
3343             "{ \n"<<marshallMsg()<<
3344             "   return ckCreateArray((CkArrayMessage *)impl_msg,"<<epIdx()<<",CkArrayOptions(s1));\n"
3345             "}\n";
3346         } else if (dim==(const char*)"2D") {
3347           str<<
3348             makeDecl("CkArrayID",1)<<"::ckNew("<<paramComma(0)<<"const int s1, const int s2"<<eo(0)<<")\n"
3349             "{ \n"<<marshallMsg()<<
3350             "   return ckCreateArray((CkArrayMessage *)impl_msg,"<<epIdx()<<",CkArrayOptions(s1, s2));\n"
3351             "}\n";
3352         } else if (dim==(const char*)"3D") {
3353           str<<
3354             makeDecl("CkArrayID",1)<<"::ckNew("<<paramComma(0)<<"const int s1, const int s2, const int s3"<<eo(0)<<")\n"
3355             "{ \n"<<marshallMsg()<<
3356             "   return ckCreateArray((CkArrayMessage *)impl_msg,"<<epIdx()<<",CkArrayOptions(s1, s2, s3));\n"
3357             "}\n";
3358         /*} else if (dim==(const char*)"4D") {
3359           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4"<<eo(1)<<");\n";
3360         } else if (dim==(const char*)"5D") {
3361           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5"<<eo(1)<<");\n";
3362         } else if (dim==(const char*)"6D") {
3363           str<<"    static CkArrayID ckNew("<<paramComma(1,0)<<"const short s1, const short s2, const short s3, const short s4, const short s5, const short s6"<<eo(1)<<");\n";
3364         */
3365         }
3366       }
3367   }
3368
3369 }
3370
3371
3372 /******************************** Group Entry Points *********************************/
3373
3374 void Entry::genGroupDecl(XStr& str)
3375 {
3376 #if 0
3377   if (isImmediate() && !container->isNodeGroup()) {
3378       cerr << (char *)container->baseName() << ": Group does not allow immediate message.\n";
3379       exit(1);
3380   }
3381 #endif
3382   if (isLocal() && container->isNodeGroup()) {
3383     cerr << (char*)container->baseName() << ": Nodegroup does not allow LOCAL entry methods.\n";
3384     exit(1);
3385   }
3386
3387   if(isConstructor()) {
3388     str << "    " << generateTemplateSpec(tspec) << "\n";
3389     genGroupStaticConstructorDecl(str);
3390   } else {
3391     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
3392     str << "    " << generateTemplateSpec(tspec) << "\n";
3393     if (isLocal())
3394       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1,0)<<");\n";
3395     else
3396       str << "    "<<retType<<" "<<name<<"("<<paramType(1,1)<<");\n";
3397     // entry method on multiple PEs declaration
3398     if(!container->isForElement() && !container->isForSection() && !isSync() && !isLocal() && !container->isNodeGroup()) {
3399       str << "    " << generateTemplateSpec(tspec) << "\n";
3400       str << "    "<<retType<<" "<<name<<"("<<paramComma(1,0)<<"int npes, int *pes"<<eo(1)<<");\n";
3401       str << "    " << generateTemplateSpec(tspec) << "\n";
3402       str << "    "<<retType<<" "<<name<<"("<<paramComma(1,0)<<"CmiGroup &grp"<<eo(1)<<");\n";
3403     }
3404   }
3405 }
3406
3407 void Entry::genGroupDefs(XStr& str)
3408 {
3409   //Selects between NodeGroup and Group
3410   char *node = (char *)(container->isNodeGroup()?"Node":"");
3411
3412   if(isConstructor()) {
3413     genGroupStaticConstructorDefs(str);
3414   } else {
3415     int forElement=container->isForElement();
3416     XStr params; params<<epIdx()<<", impl_msg";
3417     XStr paramg; paramg<<epIdx()<<", impl_msg, ckGetGroupID()";
3418     XStr parampg; parampg<<epIdx()<<", impl_msg, ckGetGroupPe(), ckGetGroupID()";
3419     // append options parameter
3420     XStr opts; opts<<",0";
3421     if (isImmediate()) opts << "+CK_MSG_IMMEDIATE";
3422     if (isInline())  opts << "+CK_MSG_INLINE";
3423     if (isSkipscheduler())  opts << "+CK_MSG_EXPEDITED";
3424
3425     if ((isSync() || isLocal()) && !container->isForElement()) return; //No sync broadcast
3426
3427     XStr retStr; retStr<<retType;
3428     XStr msgTypeStr;
3429     if (isLocal())
3430       msgTypeStr<<paramType(0,1,0);
3431     else
3432       msgTypeStr<<paramType(0,1);
3433     str << makeDecl(retStr,1)<<"::"<<name<<"("<<msgTypeStr<<")\n";
3434     str << "{\n  ckCheck();\n";
3435     if (!isLocal()) str <<marshallMsg();
3436
3437     if (isLocal()) {
3438       XStr unmarshallStr; param->unmarshall(unmarshallStr);
3439       str << "  "<<container->baseName()<<" *obj = ckLocalBranch();\n";
3440       str << "  CkAssert(obj);\n";
3441       if (!isNoTrace()) str << "  _TRACE_BEGIN_EXECUTE_DETAILED(0,ForBocMsg,"<<epIdx()<<",CkMyPe(),0,NULL);\n";
3442       str << "#if CMK_LBDB_ON\n"
3443 "  // if there is a running obj being measured, stop it temporarily\n"
3444 "  LDObjHandle objHandle;\n"
3445 "  int objstopped = 0;\n"
3446 "  LBDatabase *the_lbdb = (LBDatabase *)CkLocalBranch(_lbdb);\n"
3447 "  if (the_lbdb->RunningObject(&objHandle)) {\n"
3448 "    objstopped = 1;\n"
3449 "    the_lbdb->ObjectStop(objHandle);\n"
3450 "  }\n"
3451 "#endif\n";
3452       str << "#if CMK_CHARMDEBUG\n"
3453       "  CpdBeforeEp("<<epIdx()<<", obj, NULL);\n"
3454       "#endif\n  ";
3455       if (!retType->isVoid()) str << retType << " retValue = ";
3456       str << "obj->"<<name<<"("<<unmarshallStr<<");\n";
3457       str << "#if CMK_CHARMDEBUG\n"
3458       "  CpdAfterEp("<<epIdx()<<");\n"
3459       "#endif\n";
3460       str << "#if CMK_LBDB_ON\n"
3461 "  if (objstopped) the_lbdb->ObjectStart(objHandle);\n"
3462 "#endif\n";
3463       if (!isNoTrace()) str << "  _TRACE_END_EXECUTE();\n";
3464       if (!retType->isVoid()) str << "  return retValue;\n";
3465     } else if(isSync()) {
3466       str << syncReturn() <<
3467         "CkRemote"<<node<<"BranchCall("<<paramg<<", ckGetGroupPe()));\n";
3468     }
3469     else
3470     { //Non-sync entry method
3471       if (forElement)
3472       {// Send
3473         str << "  if (ckIsDelegated()) {\n";
3474         str << "     Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
3475         str << "     ckDelegatedTo()->"<<node<<"GroupSend(ckDelegatedPtr(),"<<parampg<<");\n";
3476         str << "  } else CkSendMsg"<<node<<"Branch"<<"("<<parampg<<opts<<");\n";
3477       }
3478       else if (container->isForSection())
3479       {// Multicast
3480         str << "  if (ckIsDelegated()) {\n";
3481         str << "     Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
3482         str << "     ckDelegatedTo()->"<<node<<"GroupSectionSend(ckDelegatedPtr(),"<<params<<", ckGetNumSections(), ckGetSectionIDs());\n";
3483         str << "  } else {\n";
3484         str << "    void *impl_msg_tmp = (ckGetNumSections()>1) ? CkCopyMsg((void **) &impl_msg) : impl_msg;\n";
3485         str << "    for (int i=0; i<ckGetNumSections(); ++i) {\n";
3486         str << "       impl_msg_tmp= (i<ckGetNumSections()-1) ? CkCopyMsg((void **) &impl_msg):impl_msg;\n";
3487         str << "       CkSendMsg"<<node<<"BranchMulti("<<epIdx()<<", impl_msg_tmp, ckGetGroupIDn(i), ckGetNumElements(i), ckGetElements(i)"<<opts<<");\n";
3488         str << "    }\n";
3489         str << "  }\n";
3490       }
3491       else
3492       {// Broadcast
3493         str << "  if (ckIsDelegated()) {\n";
3494         str << "     Ck"<<node<<"GroupMsgPrep("<<paramg<<");\n";
3495         str << "     ckDelegatedTo()->"<<node<<"GroupBroadcast(ckDelegatedPtr(),"<<paramg<<");\n";
3496         str << "  } else CkBroadcastMsg"<<node<<"Branch("<<paramg<<opts<<");\n";
3497       }
3498     }
3499     str << "}\n";
3500
3501     // entry method on multiple PEs declaration
3502     if(!forElement && !container->isForSection() && !isSync() && !isLocal() && !container->isNodeGroup()) {
3503       str << ""<<makeDecl(retStr,1)<<"::"<<name<<"("<<paramComma(1,0)<<"int npes, int *pes"<<eo(0)<<") {\n";
3504       str << marshallMsg();
3505       str << "  CkSendMsg"<<node<<"BranchMulti("<<paramg<<", npes, pes"<<opts<<");\n";
3506       str << "}\n";
3507       str << ""<<makeDecl(retStr,1)<<"::"<<name<<"("<<paramComma(1,0)<<"CmiGroup &grp"<<eo(0)<<") {\n";
3508       str << marshallMsg();
3509       str << "  CkSendMsg"<<node<<"BranchGroup("<<paramg<<", grp"<<opts<<");\n";
3510       str << "}\n";
3511     }
3512   }
3513 }
3514
3515 void Entry::genGroupStaticConstructorDecl(XStr& str)
3516 {
3517   if (container->isForElement()) return;
3518   if (container->isForSection()) return;
3519
3520   str << "    static CkGroupID ckNew("<<paramType(1,1)<<");\n";
3521   if (!param->isVoid()) {
3522     str << "    "<<container->proxyName(0)<<"("<<paramType(1,1)<<");\n";
3523   }
3524 }
3525
3526 void Entry::genGroupStaticConstructorDefs(XStr& str)
3527 {
3528   if (container->isForElement()) return;
3529   if (container->isForSection()) return;
3530
3531   //Selects between NodeGroup and Group
3532   char *node = (char *)(container->isNodeGroup()?"Node":"");
3533   str << makeDecl("CkGroupID",1)<<"::ckNew("<<paramType(0,1)<<")\n";
3534   str << "{\n"<<marshallMsg();
3535   str << "  return CkCreate"<<node<<"Group("<<chareIdx()<<", "<<epIdx()<<", impl_msg);\n";
3536   str << "}\n";
3537
3538   if (!param->isVoid()) {
3539     str << makeDecl(" ",1)<<"::"<<container->proxyName(0)<<"("<<paramType(0,1)<<")\n";
3540     str << "{\n"<<marshallMsg();
3541     str << "  ckSetGroupID(CkCreate"<<node<<"Group("<<chareIdx()<<", "<<epIdx()<<", impl_msg));\n";
3542     str << "}\n";
3543   }
3544 }