CallNodes.cpp

Go to the documentation of this file.
00001 /*
00002  *      CallNodes.cpp -
00003  *
00004  *  Copyright (C) 2002-2003 The Pentagram Team
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #include "pent_include.h"
00022 
00023 #include "CallNodes.h"
00024 #include "Folder.h"
00025 #include "VarNodes.h"
00026 
00027 // FIXME: Fix this
00028 /* 'cause we don't have dynamic binding. c++ sucks. */
00029 void AddSpToDCCallNode(DCCallPostfixNode *cpn, Node *node)
00030 {
00031         DCCallNode *cn = static_cast<DCCallNode *>(node);
00032         cn->setAddSP(cpn);
00033 }
00034 void PushRetValToDCCallNode(DCCallPostfixNode *cpn, Node *node)
00035 {
00036         DCCallNode *cn = static_cast<DCCallNode *>(node);
00037         cn->setRetVal(cpn);
00038 }
00039 void AddFreeToDCCallNode(DCCallPostfixNode *cpn, Node *node)
00040 {
00041         DCCallNode *cn = static_cast<DCCallNode *>(node);
00042         cn->addFree(cpn);
00043 }
00044 
00045 /****************************************************************************
00046         DCCallPostfixNode
00047  ****************************************************************************/
00048 
00049 bool DCCallPostfixNode::fold(DCUnit *unit, std::deque<Node *> &nodes)
00050 {
00051         if(acceptOp(nodes.back()->opcode(), 0x0F, 0x11, 0x57))
00052         {
00053                 switch(ptype)
00054                 {
00055                         case PUSH_RETVAL: PushRetValToDCCallNode(this, nodes.back()); break;
00056                         case FREESTR: AddFreeToDCCallNode(this, nodes.back()); break;
00057                         case ADDSP: AddSpToDCCallNode(this, nodes.back()); break;
00058                         default: assert(print_assert(this));
00059                 }
00060                 nodes.back()->fold(unit, nodes);
00061         }
00062         return false;
00063 }
00064 
00065 void DCCallPostfixNode::print_unk(Console &o, const uint32 /*isize*/, const bool comment) const
00066 {
00067         if(!comment) return; // handle debug output
00068 
00069         switch(ptype)
00070         {
00071                 case PUSH_RETVAL:
00072                         assert(rtype().type()!=Type::T_INVALID);
00073                         switch(rtype().type())
00074                         {
00075                                 case Type::T_BYTE: o.Printf("push_byte_retval_NOPRINT()"); break;
00076                                 case Type::T_WORD: o.Printf("push_retval_NOPRINT()"); break;
00077                                 default: assert(print_assert(this));
00078                         }
00079                         break;
00080                 case FREESTR:
00081                         assert(rtype().type()==Type::T_INVALID);
00082                         o.Printf("free_str_NOPRINT(%s)", suc::print_sp(sp));
00083                         break;
00084                 case ADDSP:
00085                         assert(rtype().type()==Type::T_INVALID);
00086                         o.Printf("addsp_NOPRINT(0x%s%02X)", sp>0x7F?"-":"", sp>0x7F?0x100-sp:sp);
00087                         break;
00088                 default: assert(print_assert(this)); // can't happen
00089         }
00090 }
00091 
00092 void DCCallPostfixNode::print_asm(Console &o) const
00093 {
00094         Node::print_asm(o);
00095         switch(ptype)
00096         {
00097                 case PUSH_RETVAL:
00098                         assert(rtype().type()!=Type::T_INVALID);
00099                         switch(rtype().type())
00100                         {
00101                                 case Type::T_BYTE: o.Printf("push byte\tretval"); break;
00102                                 case Type::T_WORD: o.Printf("push\t\tretval"); break;
00103                                 default: assert(false);
00104                         }
00105                         break;
00106                 case FREESTR:
00107                         assert(rtype().type()==Type::T_INVALID);
00108                         o.Printf("free string\t%s", suc::print_sp(sp));
00109                         break;
00110                 case ADDSP:
00111                         assert(rtype().type()==Type::T_INVALID);
00112                         o.Printf("add sp\t\t%s%02Xh", sp>0x7F?"-":"", sp>0x7F?0x100-sp:sp);
00113                         break;
00114                 default: assert(print_assert(this)); // can't happen
00115         }
00116 }
00117 
00118 void DCCallPostfixNode::print_bin(ODequeDataSource &o) const
00119 {
00120         switch(ptype)
00121         {
00122                 case PUSH_RETVAL:
00123                         assert(rtype().type()!=Type::T_INVALID);
00124                         switch(rtype().type())
00125                         {
00126                                 case Type::T_BYTE: o.write1(0x5D); break;
00127                                 case Type::T_WORD: o.write1(0x5E); break;
00128                                 default: assert(print_assert(this));
00129                         }
00130                         break;
00131                 case FREESTR:
00132                         assert(rtype().type()==Type::T_INVALID);
00133                         o.write1(0x65);
00134                         o.write1(sp);
00135                         break;
00136                 case ADDSP:
00137                         assert(rtype().type()==Type::T_INVALID);
00138                         o.write1(0x6E);
00139                         o.write1(sp);
00140                         break;
00141                 default: assert(print_assert(this)); // can't happen
00142         }
00143 }
00144 
00145 /****************************************************************************
00146         DCCallMutatorNode
00147  ****************************************************************************/
00148 
00149 void DCCallMutatorNode::print_unk(Console &o, const uint32 isize, const bool comment) const
00150 {
00151         if(!comment && mtype!=PROCESS_EXCLUDE) return;
00152         
00153         switch(mtype)
00154         {
00155                 case PUSH_INDIRECT:
00156                         assert(rtype().type()!=Type::T_INVALID);
00157                         o.Printf("push_indirect_NOPRINT(0x%02X, ", numBytes);
00158                         lnode->print_unk(o, isize);
00159                         o.Putchar(')');
00160                         break;
00161                 case SET_INFO:
00162                         assert(rtype().type()==Type::T_INVALID);
00163                         o.Printf("setinfo_NOPRINT(");
00164                         lnode->print_unk(o, isize);
00165                         o.Printf(", ");
00166                         rnode->print_unk(o, isize);
00167                         o.Putchar(')');
00168                         break;
00169                 case PROCESS_EXCLUDE:
00170                         assert(rtype().type()==Type::T_INVALID);
00171                         o.Printf("process_exclude()");
00172                         break;
00173                 default: assert(print_assert(this)); // can't happen
00174         }
00175 }
00176 
00177 void DCCallMutatorNode::print_asm(Console &o) const
00178 {
00179         switch(mtype)
00180         {
00181                 case PUSH_INDIRECT:
00182                         assert(rtype().type()!=Type::T_INVALID);
00183                         lnode->print_asm(o);
00184                         o.Putchar('\n');
00185                         Node::print_asm(o);
00186                         o.Printf("push indirect\t%02Xh bytes",  numBytes);
00187                         break;
00188                 case SET_INFO:
00189                         assert(rtype().type()==Type::T_INVALID);
00190                         lnode->print_asm(o);
00191                         o.Putchar('\n');
00192                         rnode->print_asm(o);
00193                         o.Putchar('\n');
00194                         Node::print_asm(o);
00195                         o.Printf("set info");
00196                         break;
00197                 case PROCESS_EXCLUDE:
00198                         assert(rtype().type()==Type::T_INVALID);
00199                         Node::print_asm(o);
00200                         o.Printf("process exclude");                 
00201                         break;
00202                 default: assert(print_assert(this)); // can't happen
00203         }
00204 }
00205 
00206 void DCCallMutatorNode::print_bin(ODequeDataSource &o) const
00207 {
00208         switch(mtype)
00209         {
00210                 case PUSH_INDIRECT:
00211                         assert(rtype().type()!=Type::T_INVALID);
00212                         lnode->print_bin(o);
00213                         o.write1(0x4C);
00214                         o.write1(numBytes);
00215                         break;
00216                 case SET_INFO:
00217                         assert(rtype().type()==Type::T_INVALID);
00218                         //Node::print_mac(con); // FIXME: Debugging only!
00219                         lnode->print_bin(o);
00220                         rnode->print_bin(o);
00221                         o.write1(0x77);
00222                         break;
00223                 case PROCESS_EXCLUDE:
00224                         assert(rtype().type()==Type::T_INVALID);
00225                         //Node::print_mac(con); // FIXME: Debugging only!
00226                         o.write1(0x78);
00227                         break;
00228                 default: assert(print_assert(this)); // can't happen
00229         }
00230 }
00231 
00232 bool DCCallMutatorNode::fold(DCUnit * /*unit*/, std::deque<Node *> &nodes)
00233 {
00234         switch(mtype)
00235         {
00236                 case PUSH_INDIRECT:
00237                         // technically this type can be anything, but we'll restrict outselves
00238                         // to a dword for simplicity's sake atm.
00239                         assert(nodes.back()->rtype()==Type::T_DWORD);
00240                         grab_l(nodes);
00241                         break;
00242                 case SET_INFO:
00243                         assert(nodes.back()->rtype()==Type::T_WORD);
00244                         grab_r(nodes);
00245                         assert(nodes.back()->rtype()==Type::T_WORD);
00246                         grab_l(nodes);
00247                         break;
00248                 case PROCESS_EXCLUDE:
00249                         break;
00250                 default: assert(print_assert(this));
00251         }
00252         return true;
00253 };
00254 
00255 /****************************************************************************
00256         DCCallNode
00257         Handles 'call', 'calli' opcodes.
00258  ****************************************************************************/
00259 
00260 bool DCCallNode::fold(DCUnit *unit, std::deque<Node *> &nodes)
00261 {
00262         // register ourselves so we're printed as an 'extern', even if we really aren't.
00263         switch(ctype)
00264         {
00265                 case CALL: unit->registerExternFunc(this); break;
00266                 case CALLI: unit->registerExternIntrinsic(this); break;
00267                 case SPAWN: unit->registerExternFunc(this); break;
00268                 default: assert(print_assert(this, unit));
00269         }
00270         
00271         /* if it's the first time we're called, we don't know how
00272                 many bytes of parameters we've got, so we're kinda stuck.
00273                 we also don't know what our return value is either.
00274                 we'll 'fix' this on a latter call once we've got our data. */
00275         if(addSP==0 && retVal==0)
00276                 return true;
00277         // we've just gotten our addsp opcode
00278         else if((addSP!=0 && retVal==0) // normal
00279                 || (ctype==SPAWN && (thispsize>0 && thisP==0)/*&& addSP==0 && retVal==0 && spsize==0*/)) // 'spawn' with thispsize!=0
00280         {
00281                 con.Printf("Op %02X %04X\n", nodes.back()->opcode(), nodes.back()->offset());
00282                 // we need to remove ourselves from the stack before doing anything tricky
00283                 assert(acceptOp(nodes.back()->opcode(), 0x0F, 0x11, 0x57));
00284                 Node *us=nodes.back();
00285                 nodes.pop_back();
00286                 
00287                 // if we're a 'spawn' we need to strip our *this off the stack, before
00288                 // we do anything funky.
00289                 if(thispsize>0 && ctype==SPAWN)
00290                 {
00291                         thisP = grab(nodes);
00292                         //con.Printf("SPAWN THISP GRAB:\n");
00293                         //print_assert(thisP, unit);
00294                         //need to make sure it's a dword too.
00295                         assert(thisP!=0 && thisP->rtype()==Type::T_DWORD);
00296                 }
00297                 // grab the nodes, note the '-', gotta invert the value since it's the number
00298                 // we're _removing_ from the stack
00299                 // if we're a SPAWN, we need to double this
00300                 if(ctype==SPAWN) {
00301                         if(spsize>0)
00302                                 grab_p(nodes, std::abs(static_cast<sint32>(addSP->size()))/* * 2*/);
00303                 } else
00304                         grab_p(nodes, std::abs(static_cast<sint32>(addSP->size())));
00305 
00306                 // add us back to the stack
00307                 nodes.push_back(us);
00308         }
00309         // we've just gotten our return opcode, or there is no return opcode forthcoming...
00310         else if(ctype==CALLI && spsize==0 && addSP==0 && retVal!=0)
00311                 rtype(retVal->rtype());
00312         else if(addSP!=0 && retVal!=0)
00313                 rtype(retVal->rtype());
00314         else if(nodes.size()>0 && acceptOp(nodes.back()->opcode(), 0x65))
00315         { /* do nothing... */ }
00316         else if(retVal!=0 && nodes.size()>0 && acceptOp(nodes.back()->opcode(), 0x57))
00317         { /* do nothing...
00318                 since we're just got the retval of a 'spawn' opcode, and there shouldn't be
00319                 anything else to grab... */
00320         }
00321         else
00322         {
00323                 con.Printf("Fnord: %d\n", freenodes.size());
00324                 assert(print_assert(this, unit)); // need to add the case where there's no return value and/or no addSP.
00325         }
00326         
00327         // potential line numbers come 'before' the pushed values, so we need to grab
00328         // them after the values
00329         fold_linenum(nodes);
00330         
00331         return false;
00332 }
00333 
00334 void DCCallNode::print_extern_unk(Console &o, const uint32 /*isize*/) const
00335 {
00336         switch(ctype)
00337         {
00338                 case CALLI:
00339                         {
00340                                 if(rtype().type()!=Type::T_INVALID)
00341                                 {
00342                                         o.Print(rtype().name()); o.Putchar('\t');
00343                                 }
00344                                 o.Printf("Intrinsic%04X(", intrinsic);
00345                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00346                                 {
00347                                         if(i!=pnode.rbegin()) o.Print(", ");
00348                                         o.Print((*i)->rtype().name());
00349                                 }
00350                                 o.Print(");");
00351                                 break;
00352                         }
00353                 case CALL:
00354                         {
00355                                 if(rtype().type()!=Type::T_INVALID)
00356                                 {
00357                                         o.Print(rtype().name()); o.Putchar('\t');
00358                                 }
00359                                 o.Printf("class_%04X_function_%04X(", uclass, targetOffset);
00360                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00361                                 {
00362                                         if(i!=pnode.rbegin()) o.Print(", ");
00363                                         o.Print((*i)->rtype().name());
00364                                 }
00365                                 o.Print(");");
00366                                 break;
00367                         }
00368                 case SPAWN:
00369                         {
00370                                 o.Print("spawn ");
00371                                 if(rtype().type()!=Type::T_INVALID)
00372                                 {
00373                                         o.Print(rtype().name()); o.Putchar('\t');
00374                                 }
00375                                 if(thisP!=0) o.Print(thisP->rtype().name());
00376                                 o.Printf("->class_%04X_function_%04X(", uclass, targetOffset);
00377                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00378                                 {
00379                                         if(i!=pnode.rbegin()) o.Print(", ");
00380                                         o.Print((*i)->rtype().name());
00381                                 }
00382                                 o.Print(");");
00383                                 break;
00384                         }
00385                 default: assert(print_assert(this)); // can't happen
00386         }
00387 }
00388 
00389 void DCCallNode::print_unk(Console &o, const uint32 isize) const
00390 {
00391         print_linenum_unk(o, isize);
00392         switch(ctype)
00393         {
00394                 case CALLI:
00395                         {
00396                                 #if 0
00397                                 if(rtype().type()!=Type::T_VOID)
00398                                 {
00399                                         rtype().print_unk(o); o.Putchar(' ');
00400                                 }
00401                                 #endif
00402                                 o.Printf("Intrinsic%04X(", intrinsic);
00403                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00404                                 {
00405                                         if(i!=pnode.rbegin()) o.Print(", ");
00406                                         (*i)->print_unk(o, isize);
00407                                 }
00408                                 o.Putchar(')');
00409                                 break;
00410                         }
00411                 case CALL:
00412                         {
00413                                 #if 0
00414                                 if(rtype().type()!=Type::T_VOID)
00415                                 {
00416                                         rtype().print_unk(o); o.Putchar(' ');
00417                                 }
00418                                 #endif
00419                                 o.Printf("class_%04X_function_%04X(", uclass, targetOffset);
00420                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00421                                 {
00422                                         if(i!=pnode.rbegin()) o.Print(", ");
00423                                         (*i)->print_unk(o, isize);
00424                                 }
00425                                 o.Putchar(')');
00426                                 break;
00427                         }
00428                 case SPAWN:
00429                         {
00430                                 o.Print("spawn ");
00431                                 #if 0
00432                                 if(rtype().type()!=Type::T_VOID)
00433                                 {
00434                                         rtype().print_unk(o); o.Putchar(' ');
00435                                 }
00436                                 #endif
00437                                 assert(thispsize>0 || thisP!=0 || print_assert(this));
00438                                 if(thispsize) // only if we have a this we should worry about it.
00439                                         thisP->print_unk(o, isize);
00440                                 o.Printf("->class_%04X_function_%04X(", uclass, targetOffset);
00441                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00442                                 {
00443                                         if(i!=pnode.rbegin()) o.Print(", ");
00444                                         (*i)->print_unk(o, isize);
00445                                 }
00446                                 o.Putchar(')');
00447                                 break;
00448                         }
00449                 default: assert(print_assert(this)); // can't happen
00450         }
00451 }
00452 
00453 void DCCallNode::print_asm(Console &o) const
00454 {
00455         print_linenum_asm(o);
00456         switch(ctype)
00457         {
00458                 case CALLI:
00459                         {
00460                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00461                                 {
00462                                         (*i)->print_asm(o); o.Putchar('\n');
00463                                 }
00464                                 Node::print_asm(o);
00465                                 o.Printf("calli\t\t%02Xh %04Xh", spsize, intrinsic);
00466                                 for(std::list<DCCallPostfixNode *>::const_reverse_iterator i=freenodes.rbegin(); i!=freenodes.rend(); ++i)
00467                                 {
00468                                         o.Putchar('\n'); (*i)->print_asm(o);
00469                                 }
00470                                 //FIXME: o.Printf(" (%s)", convert->intrinsics()[op.i1]);
00471                                 if(addSP!=0)
00472                                 {
00473                                         o.Putchar('\n');
00474                                         addSP->print_asm(o);
00475                                 }
00476                                 if(rtype()!=Type::T_VOID)
00477                                 {
00478                                         assert(retVal!=0);
00479                                         o.Putchar('\n');
00480                                         retVal->print_asm(o);
00481                                 }
00482                                 break;
00483                         }
00484                 case CALL:
00485                         {
00486                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00487                                 {
00488                                         (*i)->print_asm(o); o.Putchar('\n');
00489                                 }
00490                                 if(pnode.size()==0)
00491                                         o.Putchar('\n');
00492 
00493                                 Node::print_asm(o);
00494                                 o.Printf("call\t\t%04X:%04X\n", uclass, targetOffset);
00495                                 //o.Putchar('\n');
00496                                 if(addSP!=0)
00497                                         addSP->print_asm(o);
00498                                 if(rtype()!=Type::T_VOID)
00499                                 {
00500                                         assert(retVal!=0);
00501                                         o.Putchar('\n');
00502                                         retVal->print_asm(o);
00503                                 }
00504                                 //FIXME: o.Printf(" (%s)", convert->UsecodeFunctionAddressToString(uclass, targetOffset, ucfile).c_str());
00505                                 break;
00506                         }
00507                 case SPAWN:
00508                         {
00509                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00510                                 {
00511                                         (*i)->print_asm(o); o.Putchar('\n');
00512                                 }
00513                                 assert((thispsize>0 && thisP!=0) || print_assert(this));
00514                                 if(thispsize) // only if we have a this we should worry about it.
00515                                         thisP->print_asm(o);
00516                                 Node::print_asm(o);
00517                                 o.Printf("call\t\t%04X:%04X", uclass, targetOffset);
00518                                 o.Putchar('\n');
00519                                 if(addSP!=0)
00520                                         addSP->print_asm(o);
00521                                 if(rtype()!=Type::T_VOID)
00522                                 {
00523                                         assert(retVal!=0);
00524                                         o.Putchar('\n');
00525                                         retVal->print_asm(o);
00526                                 }
00527                                 //FIXME: o.Printf(" (%s)", functionaddresstostring(uclass, targetOffset, ucfile).c_str());
00528                                 break;
00529                         }
00530                 default: assert(print_assert(this)); // can't happen
00531         }
00532 }
00533 
00534 void DCCallNode::print_bin(ODequeDataSource &o) const
00535 {
00536         print_linenum_bin(o);
00537         switch(ctype)
00538         {
00539                 case CALLI:
00540                         {
00541                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00542                                 {
00543                                         (*i)->print_bin(o);
00544                                 }
00545                                 o.write1(0x0F);
00546                                 o.write1(spsize);
00547                                 o.write2(intrinsic);
00548                                 if(addSP!=0)
00549                                         addSP->print_bin(o);
00550                                 if(rtype()!=Type::T_VOID)
00551                                 {
00552                                         assert(retVal!=0);
00553                                         retVal->print_bin(o);
00554                                 }
00555                                 break;
00556                         }
00557                 case CALL:
00558                         {
00559                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00560                                 {
00561                                         (*i)->print_bin(o);
00562                                 }
00563                                 o.write1(0x11);
00564                                 o.write2(uclass);
00565                                 o.write2(targetOffset);
00566                                 if(addSP!=0)
00567                                         addSP->print_bin(o);
00568                                 if(rtype()!=Type::T_VOID)
00569                                 {
00570                                         assert(retVal!=0);
00571                                         retVal->print_bin(o);
00572                                 }
00573                                 break;
00574                         }
00575                 case SPAWN:
00576                         {
00577                                 for(std::deque<Node *>::const_reverse_iterator i=pnode.rbegin(); i!=pnode.rend(); ++i)
00578                                 {
00579                                         (*i)->print_bin(o);
00580                                 }
00581                                 assert(thispsize>0 || thisP!=0 || print_assert(this));
00582                                 if(thispsize) // only if we have a this we should worry about it.
00583                                         thisP->print_bin(o);
00584                                 o.write1(0x11);
00585                                 o.write2(uclass);
00586                                 o.write2(targetOffset);
00587                                 if(addSP!=0)
00588                                         addSP->print_bin(o);
00589                                 if(rtype()!=Type::T_VOID)
00590                                 {
00591                                         assert(retVal!=0);
00592                                         retVal->print_bin(o);
00593                                 }
00594                                 break;
00595                         }
00596                 default: assert(print_assert(this)); // can't happen
00597         }
00598 }
00599 
00600 
00602 
00603 /* Takes an opcode number and returns true if it's potential DCCallNode */
00604 /*bool is_call(uint32 op)
00605 {
00606         switch(op)
00607         {
00608                 case 0x0F: // calli
00609                 case 0x57: // spawn
00610                         return true;
00611                 default:   // else...
00612                         return false;
00613         }
00614         return false; // can't happen
00615 }
00616 
00617 class DCCallNode : public ColNode
00618 {
00619         public:
00620                 DCCallNode() : ColNode("Call"), sp_size(0),
00621                         num_bytes(0), intrinsic_num(0),
00622                         target_class(0), target_func(0),
00623                         param_size(0), this_size(0) {};
00624                 ~DCCallNode() {};
00625 
00626                 void print() const;
00627                 void fold(const uint32 pos);
00628 
00629         protected:
00630 
00631         private:
00632                 void get_return(const uint32 end);
00633 
00634                 enum calltype { CALLI, CALL, SPAWN } ctype;
00635 
00636                 uint32 sp_size;
00637 
00638                 // for CALLI
00639                 uint32 num_bytes; // technically should be the same as sp_size, but...
00640                 uint32 intrinsic_num;
00641 
00642                 // for CALL and SPAWN
00643                 uint32 target_class;
00644                 uint32 target_func;
00645 
00646                 // for SPAWN
00647                 uint32 param_size;
00648                 uint32 this_size;
00649 };
00650 
00651 void DCCallNode::fold(const uint32 end)
00652 {
00653         PTRACE(("(Call)\t\tPOS: %4d\tOP: %04X offset: %04X\n", end, foldops[end].op(), foldops[end].offset));
00654         assert(foldops[end].deleted==false);
00655 
00656         _opcode = foldops[end].op(); // store the op locally
00657         _offset = foldops[end].offset; // store the offset locally
00658 
00659         get_return(end); // grab us out return node
00660 
00661         sp_size = foldops[end].sp_size;
00662         sint32 tempsize;
00663 
00664         switch(_opcode)
00665         {
00666                 case 0x0F:
00667                         ctype = CALLI;
00668                         num_bytes = foldops[end].i0;
00669                         intrinsic_num = foldops[end].i1;
00670                         tempsize=sp_size;
00671                         break;
00672                 case 0x57:
00673                         ctype = SPAWN;
00674                         param_size = foldops[end].i0;
00675                         this_size = foldops[end].i1; // probably not. We don't know what it's for.
00676                         target_class = foldops[end].i2;
00677                         target_func = foldops[end].i3;
00678                         tempsize=param_size+4; // +4== size of dword/this pointer (FIXME: #define this or something)
00679                         break;
00680                 default:        assert(false);  // can't happen
00681         }
00682 
00683         grab_p(tempsize, end);
00684         assert(tempsize==0);
00685 }
00686 
00687 void DCCallNode::print() const
00688 {
00689         printf("(%s) ", rtype.name());
00690 
00691         switch(ctype)
00692         {
00693                 case CALLI:
00694                         if(crusader)
00695                                 printf("unknown_%04X(", intrinsic_num);
00696                         else
00697                         {
00698                                 string is(convert->intrinsics()[intrinsic_num]);
00699                                 printf("%s(", is.substr(0, is.find("(")).c_str());
00700                         }
00701                         break;
00702                 case SPAWN:
00703                         printf("spawn_%02X_%02X_class_%04X_function_%04X(", param_size, this_size, target_class, target_func);
00704                         break;
00705                 default:
00706                         assert(false);
00707         }
00708 
00709         for(vector<Node *>::const_iterator n=pnode.begin(); n!=pnode.end(); ++n)
00710         {
00711                 if(n!=pnode.begin()) printf(", ");
00712                 (*n)->print();
00713         }
00714         printf(")");
00715 }
00716 
00717 void DCCallNode::get_return(const uint32 end)
00718 {
00719         // then do the same thing for the three return types.
00720         for(unsigned int ret=end+1; ret<foldops.size(); ++ret)
00721         {
00722                 if(foldops[ret].deleted==false)
00723                 {
00724                         switch(foldops[ret].op())
00725                         {
00726                                 // first the 'proper' return values.
00727                                 // yeah, using PushVarNodes here is somewhat of a hack, but they do exactly what I need.
00728                                 case 0x5D: // push byte return (2 bytes)
00729                                         foldops[ret].node = newNode(ret); // pointless, just to keep things clean
00730                                         foldops[ret].deleted=true; // ... and delete the opcode...
00731                                         rtype=Type::T_BYTE;
00732                                         ret=foldops.size(); // finished
00733                                         break;
00734                                 case 0x5E: // push word return (2 bytes)
00735                                         foldops[ret].node = newNode(ret); // pointless, just to keep things clean
00736                                         foldops[ret].deleted=true; // ... and delete the opcode...
00737                                         rtype=Type::T_WORD;
00738                                         ret=foldops.size(); // finished
00739                                         break;
00740                                 case 0x5F: // push dword return (4 bytes)
00741                                         foldops[ret].node = newNode(ret); // pointless, just to keep things clean
00742                                         foldops[ret].deleted=true; // ... and delete the opcode...
00743                                         rtype=Type::T_DWORD;
00744                                         ret=foldops.size(); // finished
00745                                         break;
00746                                 // then the case where we find a function call,
00747                                 // but no push, so there's been no return value
00748                                 case 0x0F: // calli
00749                                 case 0x11: // call
00750                                 case 0x57: // spawn
00751                                 case 0x58: // spawn inline
00752                                         // if we didn't locate a 'push return' opcode, then it's a 'void' returning function
00753                                         rtype=Type::T_VOID;
00754                                         ret=foldops.size(); // finished
00755                                         break;
00756                                 default: // ignore all other ops.
00757                                         break;
00758                         }
00759                 }
00760         }
00761 }*/
00762 

Generated on Fri Jul 27 22:27:10 2007 for pentagram by  doxygen 1.4.7