Main Page   Modules   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

dismantle.h

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------
00002 //
00003 //  C-Breeze
00004 //  C Compiler Framework
00005 // 
00006 //  Copyright (c) 2000 University of Texas at Austin
00007 // 
00008 //  Samuel Z. Guyer
00009 //  Daniel A. Jimenez
00010 //  Calvin Lin
00011 // 
00012 //  Permission is hereby granted, free of charge, to any person
00013 //  obtaining a copy of this software and associated documentation
00014 //  files (the "Software"), to deal in the Software without
00015 //  restriction, including without limitation the rights to use, copy,
00016 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00017 //  of the Software, and to permit persons to whom the Software is
00018 //  furnished to do so, subject to the following conditions:
00019 //  
00020 //  The above copyright notice and this permission notice shall be
00021 //  included in all copies or substantial portions of the Software.
00022 //  
00023 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00024 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00025 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00026 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00027 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00028 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00029 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00030 //  THE SOFTWARE.
00031 //
00032 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00033 //  Computer Science for inspiring parts of the C-Breeze design.
00034 //
00035 // ----------------------------------------------------------------------
00036 
00037 #ifndef CBZ_DISMANTLE_H
00038 #define CBZ_DISMANTLE_H
00039 
00040 //
00041 // dismantle.h
00042 //
00043 // class declarations for the dismantling changers
00044 //
00045 
00046 // some flags to control dismantling
00047 // Use at your own risk; they haven't been fully tested, except in
00048 // the default configuration.
00049 
00050 // [] is used as a primitive operator
00051 
00052 #define INDEX_IS_PRIMITIVE              0x00000001
00053 
00054 // expressions like **p are dismantled into tmp = *p; *tmp
00055 
00056 #define NO_MULTIPLE_INDIRECTION         0x00000002
00057 
00058 // &&, || and ?: are dismantled to if/goto
00059 
00060 #define DISMANTLE_LOGICAL_TO_GOTOS      0x00000004
00061 
00062 // if is a special case of if/else
00063 
00064 #define TWO_JUMP_IF                     0x00000008
00065 
00066 // whiles become repeats
00067 
00068 #define LOOP_INVERSION                  0x00000010
00069 
00070 // if (!(a<b)) becomes if (a>=b)
00071 
00072 #define INVERT_CONDITIONALS             0x00000020
00073 
00074 // if (a && b) becomes if (a) if (b)
00075 
00076 #define CONVERT_LOGICALS_TO_IFS         0x00000040
00077 
00078 #define DEFAULT_DISMANTLER_FLAGS        (NO_MULTIPLE_INDIRECTION \
00079                                         |DISMANTLE_LOGICAL_TO_GOTOS \
00080                                         |TWO_JUMP_IF \
00081                                         |CONVERT_LOGICALS_TO_IFS)
00082 
00083 /* took out LOOP_INVERSION so branches would be more biased untaken */
00084 
00085 // abstract class; all the dismantlers subclass off of this one.
00086 
00087 class DismantleChanger: public Changer {
00088 
00089         // incremented to get a unique name for temporaries
00090 
00091         unsigned int label_count;
00092 
00093         // string to prepend to labels, making them unique
00094         // among different subclasses
00095 
00096         string  prepend_to_label;
00097 
00098         // make a new label
00099 
00100         string new_label (void) {
00101                 char    s[20];
00102 
00103                 sprintf (s, "%d", label_count++);
00104                 return prepend_to_label + s;
00105         }
00106 
00107 public:
00108         unsigned int dismantle_flags;
00109 
00110         // prefix for this subclass used to indicate purpose of temp id
00111 
00112         char    *prefix;
00113 
00114         // an empty expression statement; usually used as the statement
00115         // for a label
00116 
00117         blockNode *clone_empty_stmt (void) {
00118                 blockNode *b = new blockNode (NULL, NULL);
00119                 b->stmts().push_back (new exprstmtNode (NULL));
00120                 return b;
00121         }
00122 
00123         // get a new idNode for a temp var or label
00124 
00125         idNode *new_id (char *s = "") {
00126                 string t("__");
00127                 t += s;
00128                 t += new_label();
00129                 idNode  *i = new idNode (t.c_str());
00130                 return i;
00131         }
00132         
00133         // constructor
00134 
00135         DismantleChanger (Order ord, string pre, 
00136                 unsigned int flags = DEFAULT_DISMANTLER_FLAGS) :
00137                 Changer(ord, Subtree, false), 
00138                 label_count(0),
00139                 prepend_to_label(pre),
00140                 dismantle_flags(flags) {}
00141 };
00142 
00143 // dismantle loops
00144 
00145 class LoopDismantleChanger: public DismantleChanger {
00146 private:
00147         idNode *return_label;
00148         idNode *return_val;
00149         returnNode *return_node;
00150 
00151         // dismantle a while or for loop
00152 
00153         Node * dismantle_while_for_loop (whileNode *, idNode *);
00154         Node * dismantle_while_for_loop_with_inversion (whileNode *, idNode *);
00155 
00156         // dismantle a while loop
00157 
00158         Node * dismantle_while_loop (whileNode *);
00159 
00160         // dismantle a for loop
00161 
00162         Node * dismantle_for_loop (forNode *);
00163 
00164         // dismantle a do loop
00165 
00166         Node * dismantle_do_loop (doNode *);
00167 
00168         // changer entry points
00169 
00170         Node * at_loop (loopNode *, Order);
00171         Node * at_return (returnNode *, Order);
00172         Node * at_proc (procNode *, Order);
00173 
00174 public:
00175 
00176         // dismantle one loop (public entry)
00177 
00178         Node * dismantle_loop (loopNode *);
00179 
00180         // return the complement of a conditional expression
00181 
00182         static exprNode * Not (exprNode *);
00183 
00184         // change all breaks and continues to goto's
00185         // (public because it's used by other dismantlers)
00186 
00187         static stmtNode * fix_break_continue 
00188                 (stmtNode *, idNode *, idNode *, bool);
00189 
00190         // The constructor for LoopDismantleChanger
00191         // will call the contructor for Changer
00192         // such that LoopDismantleChanger will visit
00193         // tree in Postorder.
00194 
00195         LoopDismantleChanger (unsigned int flags) : 
00196                 DismantleChanger (Preorder, "L", flags) {}
00197 };
00198 
00199 // dismantle selection statements: if, if/else, switch/case
00200 
00201 class SelectionDismantleChanger: public DismantleChanger {
00202         // dismantle if stmt
00203 
00204         Node * dismantle_if (ifNode *);
00205         Node * dismantle_ifelse (ifNode *);
00206 
00207         // dismantle switch/case stmt
00208 
00209         Node * dismantle_switch (switchNode *);
00210 
00211         // changer entry points
00212 
00213         Node * at_selection (selectionNode *, Order);
00214         Node * at_case (caseNode *, Order);
00215         // Node * at_default (defaultNode *, Order);
00216 
00217 public:
00218 
00219         // dismantle a selection stmt (public entry)
00220 
00221         Node * dismantle_selection (selectionNode *);
00222 
00223         SelectionDismantleChanger (unsigned int flags) : 
00224                 DismantleChanger (Preorder, "S", flags) {}
00225 };
00226 
00227 class IfConverterChanger: public DismantleChanger {
00228         // dismantle if (a && b && ... && z) to if (a) if (b) ... if (z)
00229         Node * at_if (ifNode *, Order);
00230         Node * at_if_noelse (ifNode *, Order);
00231 
00232 public:
00233 
00234         bool change;
00235 
00236         IfConverterChanger (unsigned int flags) :
00237                 change(false),
00238                 DismantleChanger (Preorder, "S", flags) {}
00239 };
00240 
00241 // dismantle "normal" initializer, i.e., to scalars
00242 // also a good time to dismantle any labels that don't label empty
00243 // stmts
00244 
00245 class InitializerDismantleChanger: public DismantleChanger {
00246 public:
00247         Node * at_block (blockNode *, Order);
00248         Node * at_label (labelNode *, Order); 
00249         InitializerDismantleChanger (unsigned int flags) : 
00250                 DismantleChanger (Preorder, "", flags) {}
00251 };
00252 
00253 // by the time we reach this guy, the only expressions should be in
00254 // expression statements (we hope?).  So it will be nice to do it from
00255 // at_block(), so we can have a block into which to insert temps
00256 
00257 class ExpressionDismantleChanger: public DismantleChanger {
00258         blockNode       *code;
00259         int             recursion_level;
00260         void emit_stmt (stmtNode *);
00261         void emit_decl (idNode *, typeNode *);
00262         void emit_expr (exprNode *);
00263         void emit_temp_assign (exprNode *);
00264 
00265         // return the id of a new declared variable the same type as this expr
00266         // return the id of a new declared variable of type int
00267         idNode *make_int (void);
00268         idNode *make_var (exprNode *);
00269 
00270 public:
00271         Node * at_block (blockNode *, Order);
00272         exprNode * dismantle_expr (exprNode *);
00273         exprNode * dismantle_binary (binaryNode *);
00274         exprNode * dismantle_unary (unaryNode *);
00275         exprNode * dismantle_cast (castNode *);
00276         exprNode * dismantle_comma (commaNode *);
00277         exprNode * dismantle_ternary (ternaryNode *);
00278         exprNode * dismantle_call (callNode *);
00279         exprNode * dismantle_opeq (binaryNode *, unsigned int);
00280         ExpressionDismantleChanger (unsigned int flags) : 
00281                 DismantleChanger (Postorder, "E", flags) {}
00282 };
00283 
00284 class FlattenDismantleChanger: public DismantleChanger {
00285 private:
00286         int                     _change;
00287         map <string,bool>       *labels;
00288         bool                    unreachable;
00289 
00290         // find the target of a goto stmt
00291 
00292         stmt_list_p search_target (stmt_list_p, gotoNode *, stmt_list_p);
00293 
00294         // replace all occurences of one label with another in a list of stmts
00295 
00296         void search_and_replace_labels (stmt_list, stmt_list_p, stmt_list_p);
00297 
00298 public:
00299 
00300         Node * at_label (labelNode *, Order);
00301         Node * at_proc (procNode *, Order);
00302         Node * at_unary (unaryNode *, Order);
00303         void flatten_block (blockNode *, blockNode *);
00304         int change (void) { return _change; }
00305 
00306         FlattenDismantleChanger (map<string,bool> *l, unsigned int flags) : 
00307                 DismantleChanger (Both, "", flags),
00308                 _change(0), labels(l) {}
00309 
00310 };
00311 
00312 class UsedLabelWalker: public Walker {
00313 private:
00314 
00315         map<string,bool>        *_labels;
00316 
00317 public:
00318 
00319         map<string,bool> * labels (void) {
00320                 return _labels;
00321         }
00322 
00323         void at_goto (gotoNode *p, Order) {
00324                 (*_labels)[p->name()] = true;
00325         }
00326 
00327         UsedLabelWalker (void): Walker (Preorder, Subtree) {
00328                 _labels = new map<string,bool>;
00329         }
00330 };
00331 
00332 class Dismantle {
00333 public:
00334         static void dismantle (unitNode *, unsigned int flags = 0);
00335 };
00336 
00337 // annotation for nodes that say where they came from, so
00338 // later passes can have a sense of what kind of higher level
00339 // construct is involved.
00340 //
00341 // Most if's will have "from_if", but some will have "from_for_test1", etc.
00342 //
00343 
00344 #define FROM_FOR_TEST1          1
00345 #define FROM_FOR_TEST2          2
00346 #define FROM_WHILE_TEST1        3
00347 #define FROM_WHILE_TEST2        4
00348 #define FROM_DO                 5
00349 #define FROM_WHILE              6
00350 #define FROM_IF                 7
00351 #define FROM_IFELSE             8
00352 #define FROM_SWITCH             9
00353 #define FROM_TERNARY            10
00354 #define FROM_AND1               11
00355 #define FROM_AND2               12
00356 #define FROM_OR1                13
00357 #define FROM_OR2                14
00358 #define FROM_MANY_CASES         15
00359 
00360 class fromAnnote : public Annote {
00361 private:
00362         int     _from;
00363 public:
00364         fromAnnote (int f) : _from(f) { }
00365 
00366         int from (void) { return _from; }
00367         void from (int f) { _from = f; }
00368         bool is_annote_kind (string & name) {
00369                 switch (_from) {
00370                 case FROM_FOR_TEST1: return name == "from_for_test1";
00371                 case FROM_FOR_TEST2: return name == "from_for_test2";
00372                 case FROM_WHILE_TEST1: return name == "from_while_test1";
00373                 case FROM_WHILE_TEST2: return name == "from_while_test2";
00374                 case FROM_DO: return name == "from_do";
00375                 case FROM_IF: return name == "from_if";
00376                 case FROM_IFELSE: return name == "from_ifelse";
00377                 case FROM_SWITCH: return name == "from_switch";
00378                 case FROM_TERNARY: return name == "from_ternary";
00379                 case FROM_AND1: return name == "from_and1";
00380                 case FROM_AND2: return name == "from_and2";
00381                 case FROM_OR1: return name == "from_or1";
00382                 case FROM_OR2: return name == "from_or2";
00383                 case FROM_MANY_CASES: return name == "from_many_cases";
00384                 default: return false;
00385                 }
00386         }
00387 
00388         // search a node's annotation list for something
00389 
00390         static bool find_from (Node *n, string s) {
00391                 annote_list_p a;
00392                 for (a=n->annotations().begin(); 
00393                         a!=n->annotations().end(); a++) {
00394                         if ((*a)->is_annote_kind (s)) return true;
00395                 }
00396                 return false;
00397         }
00398 };
00399 
00400 #endif // CBZ_DISMANTLE_H

Generated on Thu Jan 10 12:06:19 2002 for C-Breeze by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001