Folder.cpp

Go to the documentation of this file.
00001 /*
00002  *      Folder.cpp - The core of the folding utility
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 "Folder.h"
00024 #include "FuncNodes.h"
00025 
00026 #include <deque>
00027 using   std::deque;
00028 #include <set>
00029 using   std::set;
00030 
00031 /****************************************************************************
00032         Unit
00033  ****************************************************************************/
00034 
00035 void Unit::print_extern_unk(Console &o, const uint32 isize) const
00036 {
00037         o.Print("// External Functions:\n");
00038         FOR_CONST_SET(DCCallNode, externFuncs, i)
00039         //for(std::set<DCCallNode *>::const_iterator i=externFuncs.begin(); i!=externFuncs.end(); ++i)
00040         {
00041                 indent(o, isize+1);
00042                 (*i)->print_extern_unk(o, isize+1);
00043                 o.Putchar('\n');
00044         }
00045         o.Print("// External Intrinsics:\n");
00046         {
00047                 FOR_CONST_SET(DCCallNode, externIntrinsics, i)
00048                 //for(std::set<DCCallNode *>::const_iterator i=externIntrinsics.begin(); i!=externIntrinsics.end(); ++i)
00049                 {
00050                         indent(o, isize+1);
00051                         (*i)->print_extern_unk(o, isize+1);
00052                         o.Putchar('\n');
00053                 }
00054         }
00055 }
00056 
00057 void Unit::print_unk(Console &o, const uint32 isize) const
00058 {
00059         FOR_CONST_DEQUE(DCFuncNode, functions, i)
00060         {
00061                 // function header
00062                 (*i)->print_unk_funcheader(o, isize);
00063 
00064                 // main function body
00065                 indent(o, isize);
00066                 o.Print("{\n");
00067                 
00068                 //indent(o, isize+1);
00069                 (*i)->print_unk(o, isize+1);
00070                 //o.Putchar('\n');
00071                 indent(o, isize);
00072                 o.Print("}\n");
00073         }
00074 }
00075 
00076 void Unit::print_asm(Console &o) const
00077 {
00078         FOR_CONST_DEQUE(DCFuncNode, functions, i)
00079         {
00080                 (*i)->print_asm(o);
00081                 o.Putchar('\n');
00082         }
00083 }
00084 
00085 void Unit::print_bin(ODequeDataSource &o) const
00086 {
00087         FOR_CONST_DEQUE(DCFuncNode, functions, i)
00088         {
00089                 o.clear();
00090                 (*i)->print_mac(con);
00091                 (*i)->print_bin(o);
00092                 // FIXME: The following is a bit of a hack, just so we get some 'real' output
00093                 for(std::deque<char>::const_iterator i=o.buf().begin(); i!=o.buf().end(); ++i)
00094                         con.Printf("%02X ", static_cast<uint8>(*i));
00095                 con.Putchar('\n');
00096         }
00097 }
00098 
00099 /****************************************************************************
00100         DCUnit
00101  ****************************************************************************/
00102 #define UNITDEBUG
00103 /* returns true if we've finished folding the current function */
00104 const bool DCUnit::fold(Node *n)
00105 {
00106         if(n==0)
00107         {
00108                 print_asm(con);
00109                 print_unk(con, 0);
00110                 ODequeDataSource o;
00111                 //print_bin(o);
00112                 print_extern_unk(con, 0);
00113 
00114                 con.Print("assert failed: n!=0\n");
00115                 print_assert(0, this);
00116                 exit(-1);
00117         }
00118         // DEBUGGING. Will produce _lots_ of output.
00119         //print_asm(con);
00120         //print_assert(n, this);
00121         //con.Printf("currop.offset: %04X\tifstack.size: %d\telsestack.size: %d\n", n->offset(), ifstack.size(), elsestack.size());
00122         
00123         while(elsestack.size()>0 && n->offset()==elsestack.back()->TargetOffset())
00124         {
00125                 IfNode *last = elsestack.back();
00126                 elsestack.pop_back();
00127                 #ifdef UNITDEBUG
00128                 con.Printf("Popping elsestack offset: %04X type %d at %04X\n", last->offset(), last->itype, n->offset());
00129                 #endif
00130 
00131                 // bunch of random asserts
00132                 assert(last->itype!=IfNode::I_IF && last->itype!=IfNode::I_ELSE_IF);
00133                 if(elsestack.size()==0)
00134                         assert(last->itype==IfNode::I_IF_ELSE || last->itype==IfNode::I_IF_ELSE_IF);
00135                 if(elsestack.size()>0 && (last->itype==IfNode::I_ELSE_IF || last->itype==IfNode::I_ELSE_IF_ELSE))
00136                         assert(last->TargetOffset()==elsestack.back()->TargetOffset());
00137                 if(elsestack.size()>0)
00138                 {
00139                         assert(elsestack.back()->elsenode==0 || print_assert(elsestack.back(), this));
00140                         elsestack.back()->elsenode=last;
00141                         #ifdef UNITDEBUG
00142                         print_assert(0, this);
00143                         #endif
00144                 }
00145                 //if(!(ifstack.size()>0)) { last->print_asm(con); last->print_unk(con, 3); n->print_unk(con, 5); print_assert(n, this); }//debugging, DELETE:
00146                 //assert(ifstack.size()>0 || print_assert(n, this));
00147                 if(ifstack.size()>0 && last!=ifstack.back() && last->elsenode==0)
00148                 {
00149                         IfNode *newnode = new IfNode(IfNode::I_ELSE, last->TargetOffset());
00150                         //con.Printf(">Fnord<\n");
00151                         //print_assert(ifstack.back(), this);
00152                         //con.Printf(">Fnord<\n");
00153                         newnode->fold_else(this, ifstack.back()->nodes());
00154                         assert(last->elsenode==0 || print_assert(last->elsenode, this));
00155                         assert(ifstack.back()->opcode()==0x51);
00156                         ifstack.back()->nodes().push_back(newnode);
00157                 }
00158                 else if(nodes.size()>0 &&
00159                                 last!=nodes.back() &&
00160                                 last->elsenode==0 //&&
00161                                 //nodes.back()->opcode()!=0x77 &&
00162                                 //nodes.back()->opcode()!=0x78 // 77 and 78 are special.
00163                                 )
00164                                                         // Not sure why they're not being stripped before getting here though...
00165                 {
00166                         IfNode *newnode = new IfNode(IfNode::I_ELSE, last->TargetOffset());
00167                         newnode->fold_else(this, nodes);
00168                         assert(last->elsenode==0 || print_assert(last->elsenode, this));
00169                         assert(nodes.back()->opcode()==0x51);
00170                         nodes.push_back(newnode);
00171                 }
00172         }
00173 
00174         while(ifstack.size()>0 && n->offset()==ifstack.back()->TargetOffset())
00175         {
00176                 IfNode *last = ifstack.back();
00177                 ifstack.pop_back();
00178                 #ifdef UNITDEBUG
00179                 con.Printf("Popping ifstack offset: %04X type %d at %04X\n", last->offset(), last->itype, n->offset());
00180                 #endif
00181                 // fold the last if node once more, with the 'parent' stack,
00182                 // just in case it wants to do anything funky (FIXME: Be just a _tad_ more specific here)
00183                 if(ifstack.size()==0)
00184                         last->fold(this, nodes);
00185                 else
00186                         last->fold(this, ifstack.back()->nodes());
00187                 
00188                 // if we're an else type, append us to the stack
00189                 if(last->itype!=IfNode::I_IF && last->itype!=IfNode::I_ELSE_IF)
00190                 {
00191                         #if 0
00192                         con.Printf("Fnord: %04X\n", last->offset());
00193                         print_assert(last, this);
00194                         #endif
00195                         if(elsestack.size()>0 && (elsestack.back()->itype==IfNode::I_IF_ELSE
00196                                 || elsestack.back()->itype==IfNode::I_ELSE_IF_ELSE))
00197                         {
00198                                 elsestack.back()->elsenode=last;
00199                                 elsestack.pop_back();
00200                         }
00201                         elsestack.push_back(last);
00202                 }
00203         }
00204         
00205         // if we're not nested inside an if, things are relatively simple
00206         if(ifstack.size()==0)
00207         {
00208                 if(n->fold(this, nodes)) // we want to fold it
00209                         nodes.push_back(n); // and _then_ append it to the end of the 'stack' if we're supposed to.
00210         }
00211         else
00212         {
00213                 if(n->fold(this, ifstack.back()->nodes()))
00214                         ifstack.back()->nodes().push_back(n);
00215         }
00216         
00217         // special handling for jmp...
00218         if(n->opcode()==0x51)
00219                 setJump(static_cast<IfNode *>(n));
00220         
00221         // are we at the end of a function...
00222         if(n->opcode()==0x50)
00223         {
00224                 // doesn't handle spawn inline, will have to handle it sometime
00225                 // should just be a case of making sure to pass the appropriate
00226                 // 'nodes' array to fold, like:
00227                 /*if(ifstack.size()==0)
00228                         if(n->fold(this, nodes))
00229                                 nodes.push_back(n);
00230                 else
00231                         if(n->fold(this, ifstack.back()->nodes()))
00232                                 ifstack.back()->nodes().push_back(n);
00233                 */
00234                 
00235                 assert(elsestack.size()==0 || print_assert(n, this));
00236                 DCFuncNode *func = new DCFuncNode();
00237                 assert(ifstack.size()==0);
00238                 
00239                 if(func->fold(this, nodes))
00240                         nodes.push_back(func);
00241         }
00242         
00243         // special handling for 'end' opcodes
00244         if(n->opcode()==0x7A)
00245         {
00246                 //con.Printf("<< Assign func %d\n", functions.size()+1);
00247                 assert(nodes.back()->opcode()==0xFFFF);
00248                 functions.push_back(static_cast<DCFuncNode *>(nodes.back()));
00249                 nodes.pop_back();
00250                 assert(nodes.size()==0);
00251                 return true;
00252         }
00253         return false;
00254 }
00255 
00256 /****************************************************************************
00257         Folder
00258  ****************************************************************************/
00259 
00260 void Folder::fold(Node *n)
00261 {
00262         if(n!=0)
00263                 con.Printf("\t%04X:\t%02X\n", n->offset(), n->opcode());
00264         else
00265                 con.Printf("WARNING: Got a null node, so something's not right, will terminate soon...\n");
00266 
00267         //n->print_asm(con);
00268         if(curr->fold(n))
00269         {
00270                 //assert(curr!=0);
00271                 //units.push_back(curr);
00272                 //curr = 0;
00273                 
00274         }
00275 }
00276 
00277 void Folder::print_unk(Console &o) const
00278 {
00279         con.Printf("Printing... %d\n", units.size());
00280         FOR_CONST_DEQUE(DCUnit, units, i)
00281         {
00282                 (*i)->print_unk(o, 0);
00283         }
00284 }
00285 
00286 void Folder::print_asm(Console &o) const
00287 {
00288         FOR_CONST_DEQUE(DCUnit, units, i)
00289         {
00290                 (*i)->print_asm(o);
00291         }
00292 }
00293 
00294 void Folder::print_bin(ODequeDataSource &o) const
00295 {
00296         FOR_CONST_DEQUE(DCUnit, units, i)
00297         {
00298                 (*i)->print_bin(o);
00299         }
00300 }
00301 
00302 /****************************************************************************
00303         Useful Funcs
00304  ****************************************************************************/
00305 
00306 bool print_assert_nodes(std::deque<Node *> &nodes, uint32 index)
00307 {
00308         indent(con, index);
00309         con.Printf("Nodes:");
00310         FOR_CONST_DEQUE(Node, nodes, i)
00311         {
00312                 con.Putchar('\n');
00313                 indent(con, index+1);
00314                 con.Printf("%04X: %02X", (*i)->offset(), (*i)->opcode());
00315         }
00316         if(nodes.size()) con.Printf("  <-\n");
00317         con.Putchar('\n');
00318         return false;
00319 }
00320 
00321 bool print_assert(const Node *n, const DCUnit *u)
00322 {
00323         if(n!=0)
00324         {
00325                 con.Printf("\n========================================\n");
00326                 con.Printf("  Error with opcode %02X at offset %04X.\n", n->opcode(), n->offset());
00327                 con.Printf("========================================\n");
00328                 //n->print_unk(con, 0);
00329         }
00330 
00331         if(u!=0)
00332         {
00333                 con.Printf("Num functions parsed: %d\n", u->functions.size());
00334                 //for(std::deque<DCFuncNode *>::const_iterator i=u->functions.begin(); i!=u->functions.end(); ++i)
00335                 //{
00336                 //      (*i)->print_unk(con, 1);
00337                 //}
00338                 u->print_asm(con);
00339                 u->print_unk(con, 0);
00340 
00341                 con.Printf("IfStack:");
00342                 {
00343                         FOR_CONST_DEQUE(IfNode, u->ifstack, i)
00344                         {
00345                                 con.Printf("\n    %04X: %02X -> %04X", (*i)->offset(), (*i)->opcode(), (*i)->TargetOffset());
00346                                 FOR_CONST_DEQUE(Node, (*i)->nodes(), j)
00347                                 {
00348                                         con.Printf("\n        %04X: %02X", (*j)->offset(), (*j)->opcode());
00349                                 }
00350                         }
00351                 }
00352                 if(u->ifstack.size()) con.Printf("  <-");
00353                 con.Putchar('\n');
00354                 
00355                 con.Printf("ElseStack:");
00356                 {
00357                         FOR_CONST_DEQUE(IfNode, u->elsestack, i)
00358                         {
00359                                 con.Printf("\n    %04X: %02X -> %04X", (*i)->offset(), (*i)->opcode(), (*i)->TargetOffset());
00360                                 FOR_CONST_DEQUE(Node, (*i)->nodes(), j)
00361                                 {
00362                                         con.Printf("\n        %04X: %02X", (*j)->offset(), (*j)->opcode());
00363                                 }
00364                         }
00365                 }
00366                 if(u->elsestack.size()) con.Printf("  <-");
00367                 con.Putchar('\n');
00368 
00369                 con.Printf("Nodes:");
00370                 {
00371                         FOR_CONST_DEQUE(Node, u->nodes, i)
00372                         {
00373                                 con.Printf("\n    %04X: %02X", (*i)->offset(), (*i)->opcode());
00374                         }
00375                 }
00376                 if(u->nodes.size()) con.Printf("  <-\n");
00377                 con.Putchar('\n');
00378 
00379                 /*con.Printf("FuncStack:");
00380                 for(deque<DCUnit *>::const_iterator k=units.begin(); k!=units.end(); ++k)
00381                 {
00382                         con.Printf("\n    %04X: %02X", (*k)->offset(), (*k)->opcode());
00383                         if((*k)->opcode()==0x51)
00384                         {
00385                         }
00386                 }*/
00387         }
00388         
00389         return false;
00390 }
00391 

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