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