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