2d818631ef7ff2b8c6290978214f5403bb184181
[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<WhenConstruct*>::iterator cn = whenList.begin(); cn != whenList.end(); ++cn) {
12     op << "    __cDep->addDepends(" << (*cn)->nodeNum << "," << entryNum << ");\n";
13   }
14 }
15
16 void CEntry::generateCode(XStr& decls, XStr& defs)
17 {
18   CStateVar *sv;
19   int i;
20   int isVoid = 1;
21   int lastWasVoid;
22   i = 0;
23   decls << "  void ";
24
25   templateGuardBegin(false, defs);
26   defs << "void " << decl_entry->getContainer()->baseName() << "::";
27
28   XStr signature;
29   signature <<  *entry << "(";
30   for(list<CStateVar*>::iterator it = myParameters.begin();
31       it != myParameters.end(); ++it, ++i) {
32     sv = *it;
33     isVoid = sv->isVoid;
34     if ((sv->isMsg != 1) && (sv->isVoid != 1)) {
35        if (i >0)
36          signature <<", ";
37        if (sv->byConst)
38          signature << "const ";
39        signature << sv->type << " ";
40        if (sv->arrayLength != 0)
41          signature << "*";
42        else if (sv->byRef != 0) {
43          signature <<"&";
44        }
45        if (sv->numPtrs != 0) {
46          for(int k = 0; k< sv->numPtrs; k++)
47             signature << "*";
48        }
49        if (sv->name != 0)
50          signature << sv->name;
51     }
52     else if (sv->isVoid != 1){
53       if (i < 1) 
54          signature << sv->type << " " << sv->name << "_msg";
55       else
56          printf("ERROR: A message must be the only parameter in an entry function\n");
57     }
58     else
59       signature <<"void";
60   }
61   signature << ")";
62
63   decls << signature << ";\n";
64
65   defs << signature << "{\n";
66   defs << "    CWhenTrigger *tr;\n";
67   defs << "    void* _bgParentLog = NULL;\n";
68 #if CMK_BIGSIM_CHARM
69   defs <<  "    CkElapse(0.01e-6);\n";
70   SdagConstruct::generateTlineEndCall(defs);
71 #endif
72
73   defs << "    CMsgBuffer* cmsgbuf;\n";
74   defs << "    if (!__cDep.get()) _sdag_init();\n";
75
76   int hasArrays = 0;
77   int paramMarshalling = 0;
78   int count = 0;
79   i = 0;
80   if (isVoid == 1) {
81      defs << "    __cDep->bufferMessage("<<entryNum<<", (void *) CkAllocSysMsg(), (void*) _bgParentLog, 0);\n";
82      defs << "    tr = __cDep->getTrigger("<<entryNum<<", 0);\n";
83   }
84   else {
85      for(list<CStateVar*>::iterator it = myParameters.begin();
86          it != myParameters.end(); ++it, ++i) {
87        sv = *it;
88         if ((i==0) && (sv->isMsg !=1)) {
89            defs <<"    int impl_off=0; int impl_arrstart=0;\n";
90            paramMarshalling = 1;
91         }
92         if(sv->arrayLength != 0) {
93            hasArrays++ ;
94            if (sv->numPtrs > 0)
95               printf("ERROR: can't pass pointers across processors \n -- Indicate the array length with []'s, or pass a reference\n");
96            defs << "    int impl_off_" << sv->name << ", impl_cnt_" << sv->name << ";\n";
97            defs << "    impl_off_" << sv->name << "=impl_off=CK_ALIGN(impl_off,sizeof(" << sv->type << "));\n";
98            defs << "    impl_off+=(impl_cnt_" << sv->name << "=sizeof(" << sv->type << ")*(" << sv->arrayLength << "));\n";
99         }
100         if (paramMarshalling ==0) {
101            defs << "    CmiReference(UsrToEnv(" << sv->name << "_msg));\n";
102            if(refNumNeeded) {
103               defs << "    int refnum = CkGetRefNum(" <<sv->name << "_msg);\n";
104               defs << "    cmsgbuf = __cDep->bufferMessage(" << entryNum << ",(void *) " << sv->name << "_msg , (void *) _bgParentLog, refnum);\n";
105               defs << "    tr = __cDep->getTrigger(" << entryNum<<", refnum);\n";
106            } else {
107               defs << "    cmsgbuf = __cDep->bufferMessage(" << entryNum << ", (void *) " << sv->name << "_msg,  (void *) _bgParentLog, 0);\n";
108               defs << "    tr = __cDep->getTrigger(" << entryNum<<", 0);\n";
109            } 
110         }
111         count++;
112      }
113    }
114    if (paramMarshalling == 1) {
115      defs <<"    {\n";
116      defs <<"      PUP::sizer implP1;\n";
117      i = 0;
118  
119      for(list<CStateVar*>::iterator it = myParameters.begin();
120          it != myParameters.end(); ++it, ++i) {
121        sv = *it;
122         if(sv->arrayLength != 0)
123            defs << "      implP1|impl_off_" << sv->name << ";\n";
124         else if(sv->byRef != 0)
125            defs << "      implP1|(" <<sv->type << " &)" <<sv->name << ";\n";
126         else   
127            defs << "      implP1|" << sv->name << ";\n";
128      }
129  
130      if (hasArrays > 0)
131      { //round up pup'd data length--that's the first array
132         defs <<"      impl_arrstart=CK_ALIGN(implP1.size(),16);\n";
133         defs <<"      impl_off+=impl_arrstart;\n";
134      }
135      else  //No arrays--no padding
136         defs <<"      impl_off+=implP1.size();\n";
137   
138      defs <<"    }\n";
139
140      //Now that we know the size, allocate the packing buffer
141      defs <<"    CkMarshallMsg *impl_msg1=CkAllocateMarshallMsg(impl_off,NULL);\n";
142      //Second pass: write the data
143      defs <<"    {\n";
144      defs <<"      PUP::toMem implP1((void *)impl_msg1->msgBuf);\n";
145      i = 0;
146  
147      for(list<CStateVar*>::iterator it = myParameters.begin();
148          it != myParameters.end(); ++it, ++i) {
149        sv = *it;
150         if(sv->arrayLength != 0)
151            defs << "      implP1|impl_off_" << sv->name << ";\n";
152         else if(sv->byRef != 0)
153            defs << "      implP1|(" << sv->type << " &)" << sv->name << ";\n";
154         else   
155            defs << "      implP1|" << sv->name << ";\n";
156      }
157      defs <<"    }\n";
158      if (hasArrays > 0)
159      { //Marshall each array
160        defs <<"    char *impl_buf1=impl_msg1->msgBuf+impl_arrstart;\n";
161        i = 0;
162      for(list<CStateVar*>::iterator it = myParameters.begin();
163          it != myParameters.end(); ++it, ++i) {
164        sv = *it;
165          if(sv->arrayLength != 0) {
166            defs << "    memcpy(impl_buf1+impl_off_" << sv->name << "," << sv->name << ",impl_cnt_" << sv->name << ");\n";
167          }
168        }
169      }
170      
171      // When a reference number is needed and there are parameters
172      // that need marshalling (in other words the parameters of the
173      // entry method are not messages) then the first parameter of the
174      // entry method is an integer that specifies the reference number
175      const char* refNumArg = refNumNeeded ? (*myParameters.begin())->name->charstar() : "0";
176
177      defs << "    cmsgbuf = __cDep->bufferMessage(" << entryNum
178         << ", (void *) impl_msg1, (void*) _bgParentLog, "
179         << refNumArg <<  ");\n";
180      defs << "    tr = __cDep->getTrigger(" << entryNum << ", "
181         << refNumArg << ");\n";
182    }
183
184   defs << "    if (tr == 0)\n";
185   defs << "      return;\n";
186
187   SdagConstruct::generateTraceEndCall(defs);
188 #if CMK_BIGSIM_CHARM
189   SdagConstruct::generateEndExec(defs);
190 #endif
191
192   if(whenList.size() == 1) {
193     defs << "    {\n";
194     (*whenList.begin())->generateWhenCode(defs);
195     defs << "    }\n";
196   }
197   else {   
198     defs << "    switch(tr->whenID) {\n";
199     for(list<WhenConstruct*>::iterator cn = whenList.begin(); cn != whenList.end(); ++cn)
200     {
201       defs << "      case " << (*cn)->nodeNum << ":\n";
202       defs << "      {\n";
203       // This emits a `return;', so no `break' is needed
204       (*cn)->generateWhenCode(defs);
205       defs << "      }\n";
206     }
207     defs << "    }\n";
208   } 
209
210   // actual code ends
211   defs << "}\n\n";
212   templateGuardEnd(defs);
213 }
214
215 }