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