IfNode.cpp

Go to the documentation of this file.
00001 /*
00002  *      IfNode.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 "IfNode.h"
00024 #include "OperatorNodes.h"
00025 #include "Folder.h"
00026 
00027 #include <deque>
00028 using   std::deque;
00029 
00030 //#define DEBUG_JUNK
00031 
00032 /****************************************************************************
00033         IfNode
00034  ****************************************************************************/
00035 
00036 void IfNode::print_unk(Console &o, const uint32 isize) const
00037 {
00038         assert(rtype().type()==Type::T_INVALID);
00039         
00040         // in case we need to print 'else if(...' instead...
00041         switch(itype)
00042         {
00043                 case I_IF:
00044                 case I_IF_ELSE:
00045                 case I_IF_ELSE_IF:
00046                         break;
00047                 case I_ELSE_IF:
00048                 case I_ELSE_IF_ELSE:
00049                 case I_ELSE:
00050                         o.Print("else ");
00051                         break;
00052                 default: assert(false);
00053         }
00054 
00055         switch(itype)
00056         {
00057                 case I_IF:
00058                 case I_IF_ELSE:
00059                 case I_IF_ELSE_IF:
00060                 case I_ELSE_IF:
00061                 case I_ELSE_IF_ELSE:
00062                         assert(node!=0);
00063                         // print the if(...) { header
00064                         o.Print("if(");
00065                         // add an extra 'not' since the things inverted.
00066                         // FIXME: at some point in time we need to strip the extra not node,
00067                         // if there is one, rather then just dropping an extra 'not ' on the front
00068                         o.Print("not ");
00069                         
00070                         node->print_unk(o, isize);
00071                         o.Print(")");
00072                         break;
00073                 case I_ELSE: // print nuthin'
00074                         break;
00075                 default: assert(false);
00076         }
00077         o.Print("\n");
00078         indent(o, isize);
00079         o.Print("{");
00080         Node::print_linenum_unk(o, isize);
00081         #ifdef DEBUG_JUNK
00082         if(itype!=I_ELSE)
00083                 o.Printf(" //jne_NOPRINT(0x%04X)", targetOffset);
00084         #endif
00085         o.Print("\n");
00086         // print the internal operations
00087         for(std::deque<Node *>::const_iterator i=ifnodes.begin(); i!=ifnodes.end(); ++i)
00088         {
00089                 indent(o, isize+1);
00090                 (*i)->print_unk(o, isize+1);
00091                 o.Putchar('\n');
00092         }
00093         // print the terminating structure '}\n' or '} else'
00094         indent(o, isize);
00095         o.Putchar('}');
00096         #ifdef DEBUG_JUNK
00097         o.Printf("/*%02X*/", itype);
00098         #endif
00099         switch(itype)
00100         {
00101                 case I_IF:
00102                 case I_ELSE_IF:
00103                         assert(jmpnode==0);
00104                         break;
00105                 case I_IF_ELSE:
00106                 case I_ELSE_IF_ELSE:
00107                 case I_IF_ELSE_IF:
00108                         assert(jmpnode!=0);
00109                         #ifdef DEBUG_JUNK
00110                         jmpnode->print_unk(o, isize);
00111                         #endif
00112                         //o.Print(" else ");
00113                         #ifdef DEBUG_JUNK
00114                         if(elsenode!=0) o.Print("/*(elsenode)*/");
00115                         #endif
00116                         /*assert(elsenode!=0);
00117                         if(elsenode)
00118                         {
00119                                 o.Putchar('\n');
00120                                 indent(o, isize);
00121                                 elsenode->print_unk(o, isize);
00122                         }*/
00123                         break;
00124                 case I_ELSE: // again, nothing special
00125                         break;
00126                 default: assert(false); // can't happen
00127         }
00128 }
00129 
00130 void IfNode::print_asm(Console &o) const
00131 {
00132         assert(rtype().type()==Type::T_INVALID);
00133         switch(itype)
00134         {
00135                 case I_IF:
00136                 case I_IF_ELSE:
00137                 case I_IF_ELSE_IF:
00138                 case I_ELSE_IF:
00139                 case I_ELSE_IF_ELSE:
00140                         {
00141                                 Node::print_linenum_asm(o);
00142                                 assert(node!=0);
00143                                 node->print_asm(o);
00144                                 o.Putchar('\n');
00145                                 Node::print_asm(o);
00146                                 o.Printf("jne\t\t%04Xh\t(to %04X)", targetOffset - _offset - 3, targetOffset);
00147                                 for(std::deque<Node *>::const_iterator i=ifnodes.begin(); i!=ifnodes.end(); ++i)
00148                                 {
00149                                         o.Putchar('\n');
00150                                         (*i)->print_asm(o);
00151                                 }
00152                                 if(jmpnode!=0)
00153                                 {
00154                                         o.Putchar('\n');
00155                                         jmpnode->print_asm(o);
00156                                 }
00157                                 break;
00158                         }
00159                 case I_ELSE:
00160                         {
00161                                 for(std::deque<Node *>::const_iterator i=ifnodes.begin(); i!=ifnodes.end(); ++i)
00162                                 {
00163                                         if(i!=ifnodes.begin()) o.Putchar('\n');
00164                                         (*i)->print_asm(o);
00165                                 }
00166                                 break;
00167                         }
00168                 default: assert(false); // can't happen
00169         }
00170 }
00171 
00172 void IfNode::print_bin(ODequeDataSource &o) const
00173 {
00174         assert(rtype().type()==Type::T_INVALID);
00175         Node::print_linenum_bin(o);
00176         switch(itype)
00177         {
00178                 case I_IF:
00179                 case I_IF_ELSE:
00180                 case I_IF_ELSE_IF:
00181                 case I_ELSE_IF:
00182                 case I_ELSE_IF_ELSE:
00183                         {
00184                                 assert(node!=0);
00185                                 node->print_bin(o);
00186                                 o.write1(0x51);
00187                                 o.write2(targetOffset - _offset - 3);
00188                                 if(jmpnode!=0)
00189                                         jmpnode->print_bin(o);
00190                                 for(std::deque<Node *>::const_iterator i=ifnodes.begin(); i!=ifnodes.end(); ++i)
00191                                 {
00192                                         (*i)->print_bin(o);
00193                                 }
00194                                 break;
00195                         }
00196                 default: assert(false); // can't happen
00197         }
00198 }
00199 
00200 bool IfNode::fold(DCUnit *unit, std::deque<Node *> &nodes)
00201 {
00202         //print_assert(this, unit);
00203         //con.Printf("\n>>> Nodes: %d <<<\n", nodes.size());
00204         //print_assert(nodes.back(), unit);
00205 
00206         switch(itype)
00207         {
00208                 // "If I were an ifnode, lalala lalalaLAlaLAlala. I would be a very iffy ifnode..." *ahem*
00209                 case I_IF:
00210                 case I_ELSE_IF:
00211                         // if this is the first time we do this, the only thing we grab
00212                         // is the parameters of the if.
00213                         if(node==0)
00214                         {
00215                                 assert(nodes.size()>0);
00216                                 grab_n(nodes);
00217                                 fold_linenum(nodes);
00218 
00219                                 // test if we need to alter the state of our previous ifnode, if there's one there.
00220                                 if(/*(itype!=I_ELSE_IF) &&*/ nodes.size()>0 && nodes.back()->opcode()==0x51)
00221                                 {
00222                                         // Bad Darke! Time to get out the whips and paddles...
00223                                         IfNode *n=static_cast<IfNode *>(nodes.back());
00224                                         // a hack, let's see if it works...
00225                                         //nodes.pop_back();
00226                                         //unit->setJump(n);
00227                                         
00228                                         assert(n!=this);
00229                                         switch(n->itype)
00230                                         {
00231                                                 case I_IF:           n->itype=I_IF_ELSE;      break;
00232                                                 case I_IF_ELSE:      n->itype=I_IF_ELSE_IF;   break;
00233                                                 case I_ELSE_IF_ELSE: /* leave as is */        break;
00234                                                 //case I_IF_ELSE_IF:   n->itype=I_ELSE_IF_ELSE; break;
00235                                                 default: assert(print_assert(this, unit));
00236                                         }
00237                                         switch(itype)
00238                                         {
00239                                                 case I_IF: itype=I_ELSE_IF; break;
00240                                                 default: assert(print_assert(this, unit));
00241                                         }
00242                                 }
00243                         }
00244                         // handle the pessimal if(true){code}->if(false){}else{code} case
00245                         // we've also got to handle the... 'unique' problem that if we get a cmp
00246                         // node after our jne node, our jmp node will be 'inside' us.
00247                         // the simplest solution then, is to have the jmp append to our 'nodes',
00248                         // then have us be called again through fold() by the loop in Unit::fold()
00249                         // as a special case
00250                         else if(jmpnode==0 && ifnodes.size()>0 && ifnodes.back()->opcode()==0x52)
00251                         {
00252                                 jmpnode=static_cast<EndNode *>(ifnodes.back());
00253                                 ifnodes.pop_back();
00254                                 switch(itype)
00255                                 {
00256                                         case I_IF:      itype = I_IF_ELSE;      break;
00257                                         case I_ELSE_IF: itype = I_ELSE_IF_ELSE; break;
00258                                         default: assert(print_assert(this, unit));
00259                                 }
00260                         }
00261                         //else
00262                         //      assert(print_assert(this, unit));
00263                         break;
00264                         break;
00265                 case I_IF_ELSE:
00266                 case I_IF_ELSE_IF:
00267                 case I_ELSE_IF_ELSE:
00268                         break;
00269                 default: assert(print_assert(this, unit));
00270         }
00271         
00272         return true;
00273 }
00274 
00275 bool IfNode::fold_else(DCUnit *unit, std::deque<Node *> &nodes)
00276 {
00277         switch(itype)
00278         {
00279                 case I_ELSE:
00280                         if(ifnodes.size()==0)
00281                         {
00282                                 bool finished=false;
00283                                 while(!finished)
00284                                 {
00285                                         assert(nodes.size()>0 || print_assert(this, unit));
00286                                         if(nodes.back()->opcode()==0x51 || nodes.back()->opcode()==0x52)
00287                                                 if(static_cast<IfNode *>(nodes.back())->TargetOffset()==TargetOffset())
00288                                                         finished=true;
00289 
00290                                         if(!finished)
00291                                         {
00292                                                 ifnodes.push_front(nodes.back());
00293                                                 nodes.pop_back();
00294                                         }
00295                                         if(nodes.size()==0)
00296                                                 finished = true; // test!
00297                                 }
00298                         }
00299                         break;
00300                 default: assert(print_assert(this, unit));
00301         }
00302         return false; // can't happen
00303 }
00304 
00305 /****************************************************************************
00306         EndNode
00307  ****************************************************************************/
00308 
00309 void EndNode::print_unk(Console &o, const uint32 isize) const
00310 {
00311         assert(rtype().type()==Type::T_INVALID);
00312         Node::print_linenum_unk(o, isize);
00313         switch(etype)
00314         {
00315                 case JMP:
00316                         o.Printf("/*jmp_NOPRINT(0x%04X)*/", targetOffset);
00317                         break;
00318                 default: assert(false); // can't happen
00319         }                                
00320 }
00321 
00322 void EndNode::print_asm(Console &o) const   
00323 {
00324         assert(rtype().type()==Type::T_INVALID);
00325         Node::print_linenum_asm(o);
00326         switch(etype)                                 
00327         {
00328                 case JMP:
00329                         Node::print_asm(o);
00330                         o.Printf("jmp\t\t%04Xh\t(to %04X)", targetOffset - _offset - 3, targetOffset);
00331                         break;
00332                 default: assert(false); // can't happen
00333         }
00334 }
00335 
00336 void EndNode::print_bin(ODequeDataSource &o) const
00337 {
00338         assert(rtype().type()==Type::T_INVALID);
00339         Node::print_linenum_bin(o);
00340         switch(etype)
00341         {
00342                 case JMP:
00343                         o.write1(0x52);
00344                         o.write2(targetOffset - _offset - 3);
00345                         break;
00346                 default: assert(false); // can't happen
00347         }
00348 }
00349 
00350 bool EndNode::fold(DCUnit * /*unit*/, std::deque<Node *> &nodes)
00351 {
00352         fold_linenum(nodes);
00353 
00354         return true;
00355 }
00356 

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