5c837e3b81b415b038e9d7b38fe104c1af15e8ac
[charm.git] / src / xlat-i / sdag / CEntry.C
1 #include "CEntry.h"
2 #include "xi-symbol.h"
3 #include "xi-Chare.h"
4 #include "constructs/Constructs.h"
5 #include "CStateVar.h"
6
7 using std::list;
8
9 namespace xi {
10   void CEntry::generateDeps(XStr& op) {
11     for (list<WhenConstruct*>::iterator cn = whenList.begin(); cn != whenList.end(); ++cn)
12       op << "  __dep->addDepends(" << (*cn)->nodeNum << "," << entryNum << ");\n";
13   }
14
15   void generateLocalWrapper(XStr& decls, XStr& defs, int isVoid, XStr& signature, Entry* entry,
16                             std::list<CStateVar*>* params, XStr* next) {
17     // generate wrapper for local calls to the function
18     templateGuardBegin(false, defs);
19     defs << entry->getContainer()->tspec() << "void " << entry->getContainer()->baseName() << "::" << signature << "{\n";
20     defs << "  " << *entry->genClosureTypeNameProxyTemp << "*" <<
21       " genClosure = new " << *entry->genClosureTypeNameProxyTemp << "()" << ";\n";
22     if (params) {
23       int i = 0;
24       for (std::list<CStateVar*>::iterator it = params->begin(); it != params->end(); ++it, ++i) {
25         CStateVar& var = **it;
26         if (var.name)
27           defs << "  genClosure->getP" << i << "() = " << var.name << ";\n";
28       }
29     }
30
31     defs << "  " << *next << "(genClosure);\n";
32     defs << "  genClosure->deref();\n";
33     defs << "}\n\n";
34     templateGuardEnd(defs);
35   }
36
37   void CEntry::generateCode(XStr& decls, XStr& defs) {
38     CStateVar *sv;
39     int i = 0;
40     int isVoid = 1;
41     int lastWasVoid;
42
43     XStr signature;
44     signature <<  *entry << "(";
45     for(list<CStateVar*>::iterator it = myParameters.begin();
46         it != myParameters.end(); ++it, ++i) {
47       sv = *it;
48       isVoid = sv->isVoid;
49       if ((sv->isMsg != 1) && (sv->isVoid != 1)) {
50         if (i >0)
51           signature <<", ";
52         if (sv->byConst)
53           signature << "const ";
54         signature << sv->type << " ";
55         if (sv->arrayLength != 0)
56           signature << "*";
57         else if (sv->declaredRef) {
58           signature <<"&";
59         }
60         if (sv->numPtrs != 0) {
61           for(int k = 0; k< sv->numPtrs; k++)
62             signature << "*";
63         }
64         if (sv->name != 0)
65           signature << sv->name;
66       }
67       else if (sv->isVoid != 1){
68         if (i < 1) 
69           signature << sv->type << "* " << sv->name << "_msg";
70         else
71           printf("ERROR: A message must be the only parameter in an entry function\n");
72       }
73       else
74         signature <<"void";
75     }
76
77     signature << ")";
78
79     XStr newSig;
80
81     if (isVoid) {
82       newSig << *entry << "()";
83       decls << "  void " <<  newSig << ";\n";
84     } else if (needsParamMarshalling) {
85       newSig << *entry << "(" << *decl_entry->genClosureTypeNameProxyTemp << "* genClosure)";
86       decls << "  void " <<  newSig << ";\n";
87       // generate local wrapper decls
88       decls << "  void " <<  signature << ";\n";
89       generateLocalWrapper(decls, defs, isVoid, signature, decl_entry, &myParameters, entry);
90     } else { // a message
91       newSig << signature << "";
92       decls << "  void " <<  newSig << ";\n";
93     }
94
95     templateGuardBegin(false, defs);
96     defs << decl_entry->getContainer()->tspec() << "void " << decl_entry->getContainer()->baseName() << "::" << newSig << "{\n";
97     defs << "  if (!__dep.get()) _sdag_init();\n";
98
99
100 #if CMK_BIGSIM_CHARM
101       defs << "  void* _bgParentLog = NULL;\n";
102       defs << "  CkElapse(0.01e-6);\n";
103       SdagConstruct::generateTlineEndCall(defs);
104 #endif
105
106     if (needsParamMarshalling || isVoid) {
107       // add the incoming message to a buffer
108
109 #if CMK_BIGSIM_CHARM
110       defs << "  SDAG::Buffer* cmsgbuf = ";
111 #endif
112
113       // note that there will always be a closure even when the method has no
114       // parameters for consistency
115       defs << "  __dep->pushBuffer(" << entryNum << ", " << (isVoid ? "0" : "genClosure") << ", " <<
116         (refNumNeeded ? "genClosure->getP0()" : "0") <<");\n";
117     } else {
118       defs << "  CMK_REFNUM_TYPE refnum = ";
119       if (refNumNeeded)
120         defs << "CkGetRefNum(" << sv->name << "_msg);\n";
121       else
122         defs << "0;\n";
123
124       // possible memory pressure problem: this message will be kept as long as
125       // it is a state parameter! there are ways to remediate this, but it
126       // involves either live variable analysis (which is not feasible) or
127       // keeping a meta-structure for every message passed in
128
129       //increase reference count by one for the state parameter
130       defs << "  CmiReference(UsrToEnv(" << sv->name << "_msg));\n";
131
132 #if CMK_BIGSIM_CHARM
133       defs << "  SDAG::Buffer* cmsgbuf = ";
134 #endif
135
136       defs << "  __dep->pushBuffer(" << entryNum << ", new SDAG::MsgClosure(" << sv->name << "_msg" << "), refnum);\n";
137     }
138     // @todo write the code to fetch the message with the ref num
139
140     // search for a continuation to restart execution
141     defs << "  SDAG::Continuation* c = __dep->tryFindContinuation(" << entryNum << ");\n";
142
143     // found a continuation
144     defs << "  if (c) {\n";
145
146     SdagConstruct::generateTraceEndCall(defs, 2);
147 #if CMK_BIGSIM_CHARM
148     SdagConstruct::generateEndExec(defs);
149 #endif
150
151     if (whenList.size() == 1) {
152       (*whenList.begin())->generateWhenCode(defs, 2);
153     } else {
154       // switch on the possible entry points for the continuation
155       // each continuation entry knows how to generate its own code
156       defs << "    switch(c->whenID) {\n";
157       for(list<WhenConstruct*>::iterator cn = whenList.begin(); cn != whenList.end(); ++cn) {
158         defs << "    case " << (*cn)->nodeNum << ":\n";
159         (*cn)->generateWhenCode(defs, 3);
160         defs << "    break;\n";
161       }
162       defs << "    }\n";
163     }
164
165     SdagConstruct::generateDummyBeginExecute(defs, 2);
166
167     // delete the continuation now that we are finished with it
168     defs << "    delete c;\n";
169     defs << "  }\n";
170
171     defs << "}\n\n";
172     templateGuardEnd(defs);
173   }
174
175 list<Entry*> CEntry::getCandidates()
176 {
177   return candidateEntries_;
178 }
179
180 void CEntry::addCandidate(Entry *e)
181 {
182   candidateEntries_.push_front(e);
183 }
184
185 void CEntry::check()
186 {
187   if (decl_entry == NULL) {
188     XStr str;
189     paramlist->printTypes(str);
190     std::string msg = "no matching declaration for entry method \'" +
191       std::string(entry->get_string_const()) +
192       "(" + std::string(str.get_string_const()) + ")\'";
193     XLAT_ERROR_NOCOL(msg, first_line_);
194
195     std::list<Entry*> clist = getCandidates();
196     if (!clist.empty())
197       for (std::list<Entry*>::iterator it = clist.begin(); it != clist.end(); ++it)
198         XLAT_NOTE("candidate method not viable: type signatures must match exactly",
199                   (*it)->first_line_);
200   }
201 }
202
203 }