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