charmxi: abolish use of TList in SDAG processing
[charm.git] / src / xlat-i / sdag / CEntry.C
1 #include "CEntry.h"
2 #include "xi-symbol.h"
3 #include "CStateVar.h"
4
5 using std::list;
6
7 namespace xi {
8
9 void CEntry::generateDeps(XStr& op)
10 {
11   for(list<SdagConstruct*>::iterator cn = whenList.begin(); cn != whenList.end(); ++cn) {
12     op << "    __cDep->addDepends(" << (*cn)->nodeNum << "," << entryNum << ");\n";
13   }
14 }
15
16 static void generateWhenCode(XStr& op, SdagConstruct *cn)
17 {
18   XStr whenParams = "";
19   CStateVar *sv = cn->stateVars->begin();
20   int i = 0;
21   int iArgs = 0;
22   bool lastWasVoid = false;
23   bool paramMarshalling = false;
24
25 #if CMK_BIGSIM_CHARM
26   // bgLog2 stores the parent dependence of when, e.g. for, olist
27   op <<"  cmsgbuf->bgLog2 = (void*)tr->args[1];\n";
28 #endif
29
30   for(; i<(cn->stateVars->length());i++, sv=(CStateVar *)cn->stateVars->next()) {
31     if ((sv->isMsg == 0) && (paramMarshalling == 0) && (sv->isVoid ==0)){
32       paramMarshalling =1;
33       op << "        CkMarshallMsg *impl_msg" <<cn->nodeNum <<" = (CkMarshallMsg *) tr->args["<<iArgs++<<"];\n";
34       op << "        char *impl_buf" <<cn->nodeNum <<"=((CkMarshallMsg *)impl_msg" <<cn->nodeNum <<")->msgBuf;\n";
35       op << "        PUP::fromMem implP" <<cn->nodeNum <<"(impl_buf" <<cn->nodeNum <<");\n";
36     }
37     if (sv->isMsg == 1) {
38       if((i!=0) && (lastWasVoid == 0))
39         whenParams.append(", ");
40 #if CMK_BIGSIM_CHARM
41       if(i==1) {
42         whenParams.append(" NULL ");
43         lastWasVoid=0;
44         // skip this arg which is supposed to be _bgParentLog
45         iArgs++;
46         continue;
47       }
48 #endif
49       whenParams.append("(");
50       whenParams.append(sv->type->charstar());
51       whenParams.append(") tr->args[");
52       whenParams<<iArgs;
53       whenParams.append("]");
54       iArgs++;
55     }
56     else if (sv->isVoid == 1)
57       // op <<"    CkFreeSysMsg((void  *)tr->args[" <<iArgs++ <<"]);\n";
58       op <<"        tr->args[" <<iArgs++ <<"] = 0;\n";
59     else if ((sv->isMsg == 0) && (sv->isVoid == 0)) {
60       if((i > 0) && (lastWasVoid == 0))
61         whenParams.append(", ");
62       whenParams.append(*(sv->name));
63       if (sv->arrayLength != 0)
64         op<<"        int impl_off"<<cn->nodeNum <<"_"<<sv->name->charstar()<<"; implP"
65           <<cn->nodeNum <<"|impl_off" <<cn->nodeNum <<"_"<<sv->name->charstar()<<";\n";
66       else
67         op<<"        "<<sv->type->charstar()<<" "<<sv->name->charstar()<<"; implP"
68           <<cn->nodeNum <<"|"<<sv->name->charstar()<<";\n";
69     }
70     lastWasVoid = sv->isVoid;
71   }
72   if (paramMarshalling == 1)
73     op<<"        impl_buf"<<cn->nodeNum <<"+=CK_ALIGN(implP" <<cn->nodeNum <<".size(),16);\n";
74   i = 0;
75   sv = (CStateVar *)cn->stateVars->begin();
76   for(; i<(cn->stateVars->length());i++, sv=(CStateVar *)cn->stateVars->next()) {
77     if (sv->arrayLength != 0)
78       op<<"        "<<sv->type->charstar()<<" *"<<sv->name->charstar()<<"=("<<sv->type->charstar()<<" *)(impl_buf" <<cn->nodeNum
79         <<"+impl_off" <<cn->nodeNum <<"_"<<sv->name->charstar()<<");\n";
80   }
81   if (paramMarshalling == 1)
82     op << "        delete (CkMarshallMsg *)impl_msg" <<cn->nodeNum <<";\n";
83   op << "        " << cn->label->charstar() << "(" << whenParams.charstar();
84   op << ");\n";
85   op << "        delete tr;\n";
86
87 #if CMK_BIGSIM_CHARM
88   cn->generateTlineEndCall(op);
89   cn->generateBeginExec(op, "sdagholder");
90 #endif
91   op << "    ";
92   cn->generateDummyBeginExecute(op);
93
94   op << "        return;\n";
95 }
96
97 void CEntry::generateCode(XStr& decls, XStr& defs)
98 {
99   CStateVar *sv;
100   int i;
101   int isVoid = 1;
102   int lastWasVoid;
103   sv = (CStateVar *)myParameters->begin();
104   i = 0;
105   decls << "  void ";
106
107   templateGuardBegin(false, defs);
108   defs << "void " << decl_entry->getContainer()->baseName() << "::";
109
110   XStr signature;
111   signature <<  *entry << "(";
112   for(; i<(myParameters->length());i++, sv=(CStateVar *)myParameters->next()) {
113     isVoid = sv->isVoid;
114     if ((sv->isMsg != 1) && (sv->isVoid != 1)) {
115        if (i >0)
116          signature <<", ";
117        signature << sv->type->charstar() << " ";
118        if (sv->arrayLength != 0)
119          signature << "*";
120        else if (sv->byRef != 0) {
121          signature <<"&";
122        }
123        if (sv->numPtrs != 0) {
124          for(int k = 0; k< sv->numPtrs; k++)
125             signature << "*";
126        }
127        if (sv->name != 0)
128          signature << sv->name->charstar();
129     }
130     else if (sv->isVoid != 1){
131       if (i < 1) 
132          signature << sv->type->charstar() <<" "<<sv->name->charstar() <<"_msg";
133       else
134          printf("ERROR: A message must be the only parameter in an entry function\n");
135     }
136     else
137       signature <<"void";
138   }
139   signature << ")";
140
141   decls << signature << ";\n";
142
143   defs << signature << "{\n";
144   defs << "    CWhenTrigger *tr;\n";
145   defs << "    void* _bgParentLog = NULL;\n";
146 #if CMK_BIGSIM_CHARM
147   defs <<  "    CkElapse(0.01e-6);\n";
148   SdagConstruct::generateTlineEndCall(defs);
149 #endif
150
151   defs << "    CMsgBuffer* cmsgbuf;\n";
152
153   int hasArrays = 0;
154   int paramMarshalling = 0;
155   int count = 0;
156   sv = (CStateVar *)myParameters->begin();
157   i = 0;
158   if (isVoid == 1) {
159      defs << "    __cDep->bufferMessage("<<entryNum<<", (void *) CkAllocSysMsg(), (void*) _bgParentLog, 0);\n";
160      defs << "    tr = __cDep->getTrigger("<<entryNum<<", 0);\n";
161   }
162   else {
163      for(; i<(myParameters->length());i++, sv=(CStateVar *)myParameters->next()) {
164         if ((i==0) && (sv->isMsg !=1)) {
165            defs <<"    int impl_off=0; int impl_arrstart=0;\n";
166            paramMarshalling = 1;
167         }
168         if(sv->arrayLength != 0) {
169            hasArrays++ ;
170            if (sv->numPtrs > 0)
171               printf("ERROR: can't pass pointers across processors \n -- Indicate the array length with []'s, or pass a reference\n");
172            defs <<"    int impl_off_"<<sv->name->charstar()<<", impl_cnt_"<<sv->name->charstar()<<";\n";
173            defs <<"    impl_off_"<<sv->name->charstar()<<"=impl_off=CK_ALIGN(impl_off,sizeof("<<sv->type->charstar()<<"));\n";
174            defs <<"    impl_off+=(impl_cnt_"<<sv->name->charstar()<<"=sizeof("<<sv->type->charstar()<<")*("<<sv->arrayLength->charstar()<<"));\n";
175         }
176         if (paramMarshalling ==0) {
177            defs << "    CmiReference(UsrToEnv(" << sv->name->charstar() << "_msg));\n";
178            if(refNumNeeded) {
179               defs << "    int refnum = CkGetRefNum(" <<sv->name->charstar() <<"_msg);\n";
180               defs << "    cmsgbuf = __cDep->bufferMessage("<<entryNum<<",(void *) "<<sv->name->charstar() <<"_msg , (void *) _bgParentLog, refnum);\n";
181               defs << "    tr = __cDep->getTrigger("<<entryNum<<", refnum);\n";
182            } else {
183               defs << "    cmsgbuf = __cDep->bufferMessage("<<entryNum<<", (void *) "<<sv->name->charstar() <<"_msg,  (void *) _bgParentLog, 0);\n";
184               defs << "    tr = __cDep->getTrigger("<<entryNum<<", 0);\n";
185            } 
186         }
187         count++;
188      }
189    }
190    if (paramMarshalling == 1) {
191      defs <<"    {\n";
192      defs <<"      PUP::sizer implP1;\n";
193      sv = (CStateVar *)myParameters->begin();
194      i = 0;
195  
196      for(; i<(myParameters->length());i++, sv=(CStateVar *)myParameters->next()) {
197         if(sv->arrayLength != 0)
198            defs <<"      implP1|impl_off_"<<sv->name->charstar()<<";\n";
199         else if(sv->byRef != 0)
200            defs <<"      implP1|(" <<sv->type->charstar() <<" &)" <<sv->name->charstar() <<";\n";
201         else   
202            defs <<"      implP1|"<<sv->name->charstar()<<";\n";
203      }
204  
205      if (hasArrays > 0)
206      { //round up pup'd data length--that's the first array
207         defs <<"      impl_arrstart=CK_ALIGN(implP1.size(),16);\n";
208         defs <<"      impl_off+=impl_arrstart;\n";
209      }
210      else  //No arrays--no padding
211         defs <<"      impl_off+=implP1.size();\n";
212   
213      defs <<"    }\n";
214
215      //Now that we know the size, allocate the packing buffer
216      defs <<"    CkMarshallMsg *impl_msg1=CkAllocateMarshallMsg(impl_off,NULL);\n";
217      //Second pass: write the data
218      defs <<"    {\n";
219      defs <<"      PUP::toMem implP1((void *)impl_msg1->msgBuf);\n";
220      sv = (CStateVar *)myParameters->begin();
221      i = 0;
222  
223      for(; i<(myParameters->length());i++, sv=(CStateVar *)myParameters->next()) {
224         if(sv->arrayLength != 0)
225            defs <<"      implP1|impl_off_"<<sv->name->charstar()<<";\n";
226         else if(sv->byRef != 0)
227            defs <<"      implP1|(" <<sv->type->charstar() <<" &)" <<sv->name->charstar() <<";\n";
228         else   
229            defs <<"      implP1|"<<sv->name->charstar()<<";\n";
230      }
231      defs <<"    }\n";
232      if (hasArrays > 0)
233      { //Marshall each array
234        defs <<"    char *impl_buf1=impl_msg1->msgBuf+impl_arrstart;\n";
235        sv = (CStateVar *)myParameters->begin();
236        i = 0;
237        for(; i<(myParameters->length());i++, sv=(CStateVar *)myParameters->next()) {
238          if(sv->arrayLength != 0) {
239            defs <<"    memcpy(impl_buf1+impl_off_"<<sv->name->charstar()<<","<<sv->name->charstar()<<",impl_cnt_"<<sv->name->charstar()<<");\n";
240          }
241        }
242      }
243      
244      // When a reference number is needed and there are parameters
245      // that need marshalling (in other words the parameters of the
246      // entry method are not messages) then the first parameter of the
247      // entry method is an integer that specifies the reference number
248      const char* refNumArg = refNumNeeded ? myParameters->begin()->name->charstar() : "0";
249
250      defs << "    cmsgbuf = __cDep->bufferMessage(" << entryNum
251         << ", (void *) impl_msg1, (void*) _bgParentLog, "
252         << refNumArg <<  ");\n";
253      defs << "    tr = __cDep->getTrigger(" << entryNum << ", "
254         << refNumArg << ");\n";
255    }
256
257   defs << "    if (tr == 0)\n";
258   defs << "      return;\n";
259
260   SdagConstruct::generateTraceEndCall(defs);
261 #if CMK_BIGSIM_CHARM
262   SdagConstruct::generateEndExec(defs);
263 #endif
264
265   if(whenList.size() == 1) {
266     defs << "    {\n";
267     generateWhenCode(defs, *whenList.begin());
268     defs << "    }\n";
269   }
270   else {   
271     defs << "    switch(tr->whenID) {\n";
272     for(list<SdagConstruct*>::iterator cn = whenList.begin(); cn != whenList.end(); ++cn)
273     {
274       defs << "      case " << (*cn)->nodeNum << ":\n";
275       defs << "      {\n";
276       // This emits a `return;', so no `break' is needed
277       generateWhenCode(defs, *cn);
278       defs << "      }\n";
279     }
280     defs << "    }\n";
281   } 
282
283   // actual code ends
284   defs << "}\n\n";
285   templateGuardEnd(defs);
286 }
287
288 }