00001 #include "CEntry.h"
00002 #include "CStateVar.h"
00003 #include "constructs/Constructs.h"
00004 #include "xi-Chare.h"
00005 #include "xi-symbol.h"
00006 
00007 using std::list;
00008 
00009 namespace xi {
00010 void CEntry::generateDeps(XStr& op) {
00011   for (list<WhenConstruct*>::iterator cn = whenList.begin(); cn != whenList.end(); ++cn)
00012     op << "  __dep->addDepends(" << (*cn)->nodeNum << "," << entryNum << ");\n";
00013 }
00014 
00015 void generateLocalWrapper(XStr& decls, XStr& defs, int isVoid, XStr& signature,
00016                           Entry* entry, std::list<CStateVar*>* params, XStr* next, bool isDummy) {
00017   int numRdmaParams = 0;
00018   for (std::list<CStateVar*>::iterator it = params->begin(); it != params->end(); ++it) {
00019     CStateVar& var = **it;
00020     if (var.isRdma) numRdmaParams++;
00021   }
00022   
00023   templateGuardBegin(false, defs);
00024   defs << entry->getContainer()->tspec() << "void " << entry->getContainer()->baseName()
00025        << "::" << signature << "{\n";
00026 
00027   if(isDummy) {
00028     
00029     
00030     defs << "  " << "CkPrintf(\"Error> Direct call to SDAG entry method \\\'%s::%s\\\'!\\n\", \""
00031          << entry->getContainer()->baseName() << "\", \"" << signature << "\"); \n";
00032     defs << "  " << "CkAbort(\"Direct SDAG call is not allowed for SDAG entry methods having when constructs. Call such SDAG methods using a proxy\"); \n";
00033   } else {
00034     defs << "  " << *entry->genClosureTypeNameProxyTemp << "*"
00035          << " genClosure = new " << *entry->genClosureTypeNameProxyTemp << "()"
00036          << ";\n";
00037     if (params) {
00038       int i = 0;
00039       for (std::list<CStateVar*>::iterator it = params->begin(); it != params->end();
00040            ++it, ++i) {
00041         CStateVar& var = **it;
00042         if (var.name) {
00043           if (var.isRdma) {
00044             defs << "#if CMK_ONESIDED_IMPL\n";
00045             if (var.isFirstRdma)
00046               defs << "  genClosure->getP" << i++ << "() = " << numRdmaParams << ";\n";
00047             defs << "  genClosure->getP" << i << "() = "
00048                  << "ncpyBuffer_" << var.name << ";\n";
00049             defs << "#else\n";
00050             defs << "  genClosure->getP" << i << "() = "
00051                  << "(" << var.type << "*)"
00052                  << "ncpyBuffer_" << var.name << ".ptr"
00053                  << ";\n";
00054             defs << "#endif\n";
00055           } else
00056             defs << "  genClosure->getP" << i << "() = " << var.name << ";\n";
00057         }
00058       }
00059     }
00060     defs << "  " << ( entry->containsWhenConstruct ? "_sdag_fnc_" : "") << *next << "(genClosure);\n";
00061     defs << "  genClosure->deref();\n";
00062   }
00063   defs << "}\n\n";
00064   templateGuardEnd(defs);
00065 }
00066 
00067 void CEntry::generateCode(XStr& decls, XStr& defs) {
00068   CStateVar* sv;
00069   int i = 0;
00070   int isVoid = 1;
00071   int lastWasVoid;
00072 
00073   XStr signature;
00074   signature << *entry << "(";
00075   for (list<CStateVar*>::iterator it = myParameters.begin(); it != myParameters.end();
00076        ++it, ++i) {
00077     sv = *it;
00078     isVoid = sv->isVoid;
00079     if ((sv->isMsg != 1) && (sv->isVoid != 1)) {
00080       if (i > 0) signature << ", ";
00081       if (sv->byConst) signature << "const ";
00082 
00083       if (sv->isRdma)
00084         signature << "CkNcpyBuffer ";
00085       else
00086         signature << sv->type << " ";
00087       if (sv->arrayLength != 0)
00088         signature << "*";
00089       else if (sv->declaredRef) {
00090         signature << "&";
00091       }
00092       if (sv->numPtrs != 0) {
00093         for (int k = 0; k < sv->numPtrs; k++) signature << "*";
00094       }
00095       if (sv->name != 0) {
00096         if (sv->isRdma) {
00097           signature << "ncpyBuffer_" << sv->name;
00098         } else {
00099           signature << sv->name;
00100         }
00101       }
00102     } else if (sv->isVoid != 1) {
00103       if (i < 1)
00104         signature << sv->type << "* " << sv->name << "_msg";
00105       else
00106         printf("ERROR: A message must be the only parameter in an entry function\n");
00107     } else
00108       signature << "void";
00109   }
00110 
00111   signature << ")";
00112 
00113   XStr newSig;
00114 
00115   if (isVoid || needsParamMarshalling) {
00116     newSig << *entry << "(" << *decl_entry->genClosureTypeNameProxyTemp
00117            << "* genClosure)";
00118     decls << "  void " << newSig << ";\n";
00119     
00120     decls << "  void " << signature << ";\n";
00121     generateLocalWrapper(decls, defs, isVoid, signature, decl_entry, &myParameters,
00122                          entry);
00123   } else {  
00124     newSig << signature << "";
00125     decls << "  void " << newSig << ";\n";
00126   }
00127 
00128   templateGuardBegin(false, defs);
00129   defs << decl_entry->getContainer()->tspec() << "void "
00130        << decl_entry->getContainer()->baseName() << "::" << newSig << "{\n";
00131   defs << "  if (!__dep.get()) _sdag_init();\n";
00132 
00133 #if CMK_BIGSIM_CHARM
00134   defs << "  void* _bgParentLog = NULL;\n";
00135   defs << "  CkElapse(0.01e-6);\n";
00136   SdagConstruct::generateTlineEndCall(defs);
00137 #endif
00138 
00139   if (needsParamMarshalling || isVoid) {
00140     
00141     
00142     if (refNumNeeded && !isVoid)
00143       defs << "  if (!genClosure->hasRefnum) "
00144               "genClosure->setRefnum(genClosure->getP0());\n";
00145 
00146 
00147 #if CMK_BIGSIM_CHARM
00148     defs << "  SDAG::Buffer* cmsgbuf = ";
00149 #endif
00150 
00151     
00152     
00153     defs << "  __dep->pushBuffer(" << entryNum << ", genClosure);\n";
00154   } else {
00155     
00156     
00157     
00158     
00159 
00160     
00161     defs << "  CmiReference(UsrToEnv(" << sv->name << "_msg));\n";
00162 
00163 #if CMK_BIGSIM_CHARM
00164     defs << "  SDAG::Buffer* cmsgbuf = ";
00165 #endif
00166     
00167     defs << "  __dep->pushBuffer(" << entryNum << ", new SDAG::MsgClosure(" << sv->name
00168          << "_msg"
00169          << "));\n";
00170   }
00171   
00172 
00173   
00174   defs << "  SDAG::Continuation* c = __dep->tryFindContinuation(" << entryNum << ");\n";
00175 
00176   
00177   defs << "  if (c) {\n";
00178 
00179 #if USE_CRITICAL_PATH_HEADER_ARRAY
00180   defs << "    MergeablePathHistory *currentSaved = c->getPath();\n";
00181   defs << "    mergePathHistory(currentSaved);\n";
00182 #endif
00183   SdagConstruct::generateTraceEndCall(defs, 2);
00184 #if CMK_BIGSIM_CHARM
00185   SdagConstruct::generateEndExec(defs);
00186 #endif
00187 
00188   if (whenList.size() == 1) {
00189     (*whenList.begin())->generateWhenCode(defs, 2);
00190   } else {
00191     
00192     
00193     defs << "    switch(c->whenID) {\n";
00194     for (list<WhenConstruct*>::iterator cn = whenList.begin(); cn != whenList.end();
00195          ++cn) {
00196       defs << "    case " << (*cn)->nodeNum << ":\n";
00197       (*cn)->generateWhenCode(defs, 3);
00198       defs << "    break;\n";
00199     }
00200     defs << "    }\n";
00201   }
00202 
00203   SdagConstruct::generateDummyBeginExecute(defs, 2, decl_entry);
00204 
00205   
00206   defs << "    delete c;\n";
00207   defs << "  }\n";
00208 
00209 #if USE_CRITICAL_PATH_HEADER_ARRAY
00210   defs << "else {\n";
00211   defs << "    MergeablePathHistory *currentSaved = saveCurrentPath();\n";
00212   defs << "    buff0->setPath(currentSaved);\n";
00213   defs << "}\n";
00214 #endif
00215   defs << "}\n\n";
00216   templateGuardEnd(defs);
00217 }
00218 
00219 list<Entry*> CEntry::getCandidates() { return candidateEntries_; }
00220 
00221 void CEntry::addCandidate(Entry* e) { candidateEntries_.push_front(e); }
00222 
00223 void CEntry::check() {
00224   if (decl_entry == NULL) {
00225     XStr str;
00226     paramlist->printTypes(str);
00227     std::string msg = "no matching declaration for entry method \'" +
00228                       std::string(entry->get_string_const()) + "(" +
00229                       std::string(str.get_string_const()) + ")\'";
00230     XLAT_ERROR_NOCOL(msg, first_line_);
00231 
00232     std::list<Entry*> clist = getCandidates();
00233     if (!clist.empty())
00234       for (std::list<Entry*>::iterator it = clist.begin(); it != clist.end(); ++it)
00235         XLAT_NOTE("candidate method not viable: type signatures must match exactly",
00236                   (*it)->first_line_);
00237   }
00238 }
00239 
00240 }