GenericNodes.h

Go to the documentation of this file.
00001 /*
00002  *      GenericNodes.h - The base node types from which all other nodes are derived.
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 #ifndef GENERICNODES_H
00022 #define GENERICNODES_H
00023 
00024 #include "Type.h"
00025 
00026 #include <deque>
00027 #include <vector>
00028 #include "Console.h"
00029 
00030 // 'cause I'm sick of this ugly construct overrunning everything...
00031 #define FOR_CONST_DEQUE(CLAS, DEQ, I) for(std::deque<CLAS *>::const_iterator I=(DEQ).begin(); (I)!=DEQ.end(); ++(I))
00032 #define FOR_CONST_SET(CLAS, SET, I)   for(std::set<CLAS *>::const_iterator   I=(SET).begin(); (I)!=SET.end(); ++(I))
00033 
00034 class DCUnit;
00035 
00036 inline bool acceptOp(const uint32 opcode, const uint32 want1)
00037         { return ((opcode==want1) ? true : false); };
00038 inline bool acceptOp(const uint32 opcode, const uint32 want1, const uint32 want2)
00039         { return (acceptOp(opcode, want1) ? true :
00040                 (opcode==want2) ? true : false); };
00041 inline bool acceptOp(const uint32 opcode, const uint32 want1, const uint32 want2, const uint32 want3)
00042         { return (acceptOp(opcode, want1, want2) ? true :
00043                         (opcode==want3) ? true : false); };
00044 inline bool acceptOp(const uint32 opcode, const uint32 want1, const uint32 want2, const uint32 want3, const uint32 want4)
00045         { return (acceptOp(opcode, want1, want2, want3) ? true :
00046                                 (opcode==want4) ? true : false); };
00047 
00048 /*inline bool acceptOp(const uint32 opcode, const uint32 want1)
00049 { return acceptIt(opcode, want1); }
00050 inline bool acceptOp(const uint32 opcode, const uint32 want1, const uint32 want2)
00051 { return acceptIt(opcode, want1, want2); }
00052 inline bool acceptOp(const uint32 opcode, const uint32 want1, const uint32 want2, const uint32 want3)
00053 { return acceptIt(opcode, want1, want2, want3); }
00054 inline bool acceptOp(const uint32 opcode, const uint32 want1, const uint32 want2, const uint32 want3, const uint32 want4)
00055 { return acceptIt(opcode, want1, want2, want3, want4); }*/
00056 
00057 
00058 inline void indent(Console &o, uint32 size)
00059 {
00060         switch(size) {
00061                 case 0: break;
00062                 case 1: o.Print("\t"); break;
00063                 case 2: o.Print("\t\t"); break;
00064                 case 3: o.Print("\t\t\t"); break;
00065                 case 4: o.Print("\t\t\t\t"); break;
00066                 case 5: o.Print("\t\t\t\t\t"); break;
00067                 case 6: o.Print("\t\t\t\t\t\t"); break;
00068                 case 7: o.Print("\t\t\t\t\t\t\t"); break;
00069                 case 8: o.Print("\t\t\t\t\t\t\t\t"); break;
00070                 case 9: o.Print("\t\t\t\t\t\t\t\t\t"); break;
00071                 default: assert(false);
00072         }
00073 }
00074 
00075 class PrintHelperNode
00076 {
00077         public:
00078                 inline void print_asm_header(Console &o, const uint32 h_off, const uint32 h_op) const
00079                 {
00080                         o.Printf("    %04X: %02X\t", h_off, h_op);
00081                 }
00082                 inline void print_mac_header(Console &o, const uint32 h_off, const uint32 h_op) const
00083                 {
00084                         o.Printf("    (%04X: %02X)\t", h_off, h_op);
00085                 }
00086 
00087 };
00088 
00089 class Node;
00090 
00091 /****************************************************************************
00092         Node
00093         The basic node type.
00094  ****************************************************************************/
00095 class Node : public PrintHelperNode
00096 {
00097         public:
00098                 Node(const sint32 newOpcode=-1, const uint32 newOffset=0, const Type newRType=Type())
00099                         : _opcode(newOpcode), _offset(newOffset), _rtype(newRType), linenum(0) {};
00100                 virtual ~Node() {};
00101                 
00102                 inline sint32 opcode() const { return _opcode; };
00103                 inline uint32 offset() const { return _offset; };
00104                 
00105                 inline const Type &rtype() const { return _rtype; };
00106                 inline void rtype(const Type &newRType) { _rtype=newRType; };
00107                 
00108                 /* 'folds' the opcodes back into their original structure. returns
00109                         'true' if the opcode needs to be pushed on the processing stack,
00110                         'false' if it doesn't.
00111                         Most fold functions will return true, since most opcodes will be
00112                         pushed, but there are exeptional opcodes that will include
00113                         themselves in the previous opcode, these will return false.
00114                 */
00115                 virtual bool fold(DCUnit *unit, std::deque<Node *> &nodes)=0;
00116                 
00117                 // outputs 'unk' formatted script
00118                 virtual void print_unk(Console &o, const uint32 isize) const=0;
00119                 // outputs psuedo assembler code
00120                 virtual void print_asm(Console &o) const;
00121                 // outputs nothing interesting...
00122                 virtual void print_mac(Console &o) const;
00123                 // outputs raw binary code
00124                 virtual void print_bin(ODequeDataSource &o) const=0;
00125                 
00126                 inline void fold_linenum(std::deque<Node *> &nodes);
00127                 
00128                 inline void print_linenum_unk(Console &o, const uint32 isize) const;
00129                 inline void print_linenum_asm(Console &o) const;
00130                 inline void print_linenum_bin(ODequeDataSource &o) const;
00131 
00132                 //enum NodeType { IS_ERROR=0, IS_CALL, IS_FUNC
00133                 //const NodeType isA() const=0;
00134                 
00135         protected:
00136                 Node *grab(std::deque<Node *> &nodes)
00137                 {
00138                         assert(nodes.size()>0); // always a good thing *grin*
00139                         Node *n = nodes.back();
00140                         nodes.pop_back();
00141                         return n;
00142                 };
00143                 
00144                 sint32  _opcode;
00145                 uint32  _offset;
00146                 Type    _rtype;
00147                 Node *linenum;
00148         
00149         private:
00150 };
00151 
00152 inline void Node::print_asm(Console &o) const
00153 {
00154         print_asm_header(o, _offset, _opcode);
00155 }
00156 
00157 inline void Node::print_mac(Console &o) const
00158 {
00159         print_mac_header(o, _offset, _opcode);
00160 }
00161 
00162 inline void Node::print_linenum_unk(Console &o, const uint32 isize) const
00163 {
00164         if(linenum!=0)
00165         {
00166                 linenum->print_unk(o, isize);
00167         }
00168 }
00169 
00170 inline void Node::print_linenum_asm(Console &o) const
00171 {
00172         if(linenum!=0)
00173         {
00174                 linenum->print_asm(o);
00175                 o.Putchar('\n');
00176         }
00177 }
00178 
00179 inline void Node::print_linenum_bin(ODequeDataSource &o) const
00180 {
00181         if(linenum!=0) linenum->print_bin(o);
00182 }
00183 
00184 inline void Node::fold_linenum(std::deque<Node *> &nodes)
00185 {
00186         // no point if we don't have any nodes to work with
00187         if(nodes.size()==0)
00188                 return;
00189         // if we _are_ a line number opcode, we don't have a line number
00190         if(opcode()==0x5B)
00191                 return;
00192         
00193         // HACK: FIXME: remove the line number if there's one before
00194         // doesn't handle multiple line numbers getting in the way,
00195         // but works.
00196         if(linenum==0)
00197         {
00198                 Node *tnode=0;
00199                 // if we're the last item on the stack, we need to remove
00200                 // ourselves first
00201                 if(nodes.back()->offset()==offset())
00202                 {
00203                         tnode = nodes.back();
00204                         nodes.pop_back();
00205                 }
00206                 // then we grab the line number
00207                 // need to make sure we've got an opcode now...
00208                 if(nodes.size()>0)
00209                         if(acceptOp(nodes.back()->opcode(), 0x5B))
00210                         {
00211                                 linenum = nodes.back();
00212                                 nodes.pop_back();
00213                         }
00214                 // then we put ourselves back onto the stack, if we've removed us
00215                 if(tnode!=0)
00216                         nodes.push_back(tnode);
00217         }
00218 }
00219 
00220 /****************************************************************************
00221         UniNode
00222         Just a general 'node' to handle uniary operators.
00223  ****************************************************************************/
00224 
00225 class UniNode : public Node
00226 {
00227         public:
00228                 UniNode(const sint32 newOpcode=-1, const uint32 newOffset=0,
00229                         const Type newRType=Type())
00230                         : Node(newOpcode, newOffset, newRType), node(0) {};
00231                 virtual ~UniNode() { /* don't delete node */ };
00232 
00233         protected:
00234                 void grab_n(std::deque<Node *> &nodes) { node=grab(nodes); };
00235                 Node *node;
00236 
00237         private:
00238 };
00239 
00240 /****************************************************************************
00241         BinNode
00242         Just a general 'node' to handle binary operators.
00243  ****************************************************************************/
00244 
00245 class BinNode : public Node
00246 {
00247         public:
00248                 BinNode(const sint32 newOpcode=-1, const uint32 newOffset=0,
00249                         const Type newRType=Type())
00250                         : Node(newOpcode, newOffset, newRType), lnode(0), rnode(0) {};
00251                 virtual ~BinNode() { /* don't delete lnode, rnode */ };
00252 
00253         protected:
00254                 void grab_l(std::deque<Node *> &nodes) { lnode=grab(nodes); };
00255                 void grab_r(std::deque<Node *> &nodes) { rnode=grab(nodes); };
00256 
00257                 Node *lnode;
00258                 Node *rnode;
00259 
00260         private:
00261 };
00262 
00263 /****************************************************************************
00264         ColNode
00265         A base class to hold the variable sized arrays of nodes (a 'collection'),
00266         for function parameters and the like.
00267  ****************************************************************************/
00268 
00269 class ColNode : public Node
00270 {
00271         public:
00272                 ColNode(const sint32 newOpcode=-1, const uint32 newOffset=0,
00273                         const Type newRType=Type())
00274                         : Node(newOpcode, newOffset, newRType), pnode(0) {};
00275                 virtual ~ColNode() {};
00276 
00277         protected:
00278                 void grab_p(std::deque<Node *> &nodes, sint32 tempsize)
00279                 {
00280                         while(tempsize>0)
00281                         {
00282                                 con.Printf("tempsize=%d\n", tempsize);
00283                                 pnode.push_back(grab(nodes));
00284                                 con.Printf("nodesize=%d\n", pnode.back()->rtype().size());
00285                                 pnode.back()->print_asm(con);
00286                                 tempsize-=pnode.back()->rtype().size();
00287                         }
00288                         assert(tempsize==0);
00289                 };
00290 
00291                 std::deque<Node *> pnode;
00292 
00293         private:
00294 };
00295 
00296 /****************************************************************************
00297         Useful Funcs
00298         Defnitions in Folder.cpp, for 'obvious' reasons.
00299  ****************************************************************************/
00300 
00301 class DCUnit;
00302 
00303 bool print_assert(const Node *n, const DCUnit *u=0);
00304 bool print_assert_nodes(std::deque<Node *> &nodes, uint32 index);
00305 
00306 #endif
00307 

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