C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

dismantle-init.cc

Go to the documentation of this file.
00001 // $Id: dismantle-init.cc,v 1.7 2003/08/11 17:28:44 abrown Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 // 
00009 //  Adam Brown
00010 //  Samuel Z. Guyer
00011 //  Daniel A. Jimenez
00012 //  Calvin Lin
00013 // 
00014 //  Permission is hereby granted, free of charge, to any person
00015 //  obtaining a copy of this software and associated documentation
00016 //  files (the "Software"), to deal in the Software without
00017 //  restriction, including without limitation the rights to use, copy,
00018 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00019 //  of the Software, and to permit persons to whom the Software is
00020 //  furnished to do so, subject to the following conditions:
00021 //  
00022 //  The above copyright notice and this permission notice shall be
00023 //  included in all copies or substantial portions of the Software.
00024 //  
00025 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00026 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00027 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00028 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00029 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00030 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00031 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00032 //  THE SOFTWARE.
00033 //
00034 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00035 //  Computer Science for inspiring parts of the C-Breeze design.
00036 //
00037 // ----------------------------------------------------------------------
00038 //
00039 // dismantle-init.cc
00040 //
00041 
00042 #include "c_breeze.h"
00043 #include "dismantle.h"
00044 #include "ref_clone_changer.h"
00045 
00046 InitializerDismantle::InitializerDismantle(void):
00047   Changer(Both, Subtree, false)
00048 {}
00049 
00050 Node * InitializerDismantle::at_block(blockNode * the_block, Order ord) {
00051   if ( ord == Preorder ) {
00052     _blockStack.push(the_block);
00053   } else { // ord == Postorder
00054     if ( _assgblock.find(the_block) != _assgblock.end() )
00055       the_block->stmts().push_front(_assgblock[the_block]);
00056     assert(_blockStack.top() == the_block);
00057     _blockStack.pop();
00058   }
00059   return the_block;
00060 }
00061 
00062 exprNode * InitializerDismantle::eval_or_cast(exprNode * expr, typeNode * type)
00063 {
00064   assert(type);
00065   if ( !expr->no_tdef_type()
00066        || *(expr->no_tdef_type()) != *type )
00067     expr = new castNode((typeNode *) ref_clone_changer::clone(type, false),
00068                         expr);
00069   expr->eval();
00070   if ( !expr->value().no_val() ) {
00071     return new constNode(expr->value());
00072   }
00073   return expr;
00074 }
00075 
00076 void InitializerDismantle::init_scalar(declNode * the_decl,
00077                                        exprNode * init) {
00078   init = eval_or_cast(init, the_decl->no_tdef_type());
00079 
00080   if ( the_decl->decl_location() == declNode::BLOCK ) {
00081     the_decl->init(NULL);
00082     idNode * id = new idNode(the_decl);
00083     binaryNode * assg = new binaryNode('=', id, init);
00084     assg->type((typeNode *) ref_clone_changer::clone(the_decl->type(),
00085                                                      false));
00086     blockNode * decl_block = _blockStack.top();
00087     if ( _assgblock.find(decl_block) == _assgblock.end() )
00088       _assgblock[decl_block] = new blockNode(NULL, NULL,
00089                                              decl_block->coord(),
00090                                              decl_block->coord());
00091     _assgblock[decl_block]->stmts().push_back(new exprstmtNode(assg));
00092   } else if ( the_decl->decl_location() == declNode::TOP ) {
00093     the_decl->init(init);
00094   }
00095 }
00096 
00097 initializerNode * InitializerDismantle::init_array(arrayNode * the_array, 
00098                                                    expr_list_p & val,
00099                                                    expr_list_p end,
00100                                                    bool inSublist) {
00101   constant array_size;
00102   if ( the_array->dim() ){
00103     the_array->dim()->eval();
00104     array_size = the_array->dim()->value();
00105   }
00106 
00107   int count = 1;
00108   initializerNode * result_init = new initializerNode(NULL);
00109 
00110   while ( val != end
00111           && ( array_size.no_val()
00112                || count <= array_size.Integer() ) ) {
00113     if ( arrayNode * sub_array = 
00114          dynamic_cast<arrayNode *>(the_array->no_tdef_type()) ) {
00115       initializerNode * sub_init = NULL;
00116       if ( initializerNode * cur_val =
00117            dynamic_cast<initializerNode *>(*val) ) {
00118         expr_list_p new_begin = cur_val->exprs().begin();
00119         sub_init = init_array(sub_array, new_begin, cur_val->exprs().end(),
00120                               true);
00121         val++;
00122       } else
00123         sub_init = init_array(sub_array, val, end, false);
00124 
00125       assert(sub_init);
00126       result_init->exprs().push_back(sub_init);
00127     } else if ( structNode * sub_struct =
00128                 dynamic_cast<structNode *>(the_array->no_tdef_type()) ) {
00129       initializerNode * sub_init = NULL;
00130       if ( initializerNode * cur_val =
00131            dynamic_cast<initializerNode *>(*val) ) {
00132         expr_list_p new_begin = cur_val->exprs().begin();
00133         sub_init = init_struct(sub_struct, new_begin, cur_val->exprs().end(),
00134                                true);
00135         val++;
00136       } else
00137         sub_init = init_struct(sub_struct, val, end, false);
00138 
00139       assert(sub_init);
00140       result_init->exprs().push_back(sub_init);
00141     } else {
00142       if ( initializerNode * init_expr = 
00143            dynamic_cast<initializerNode *>(*val) ) {
00144         CBZ::Error(the_array->coord(), "Scalar initialized by list of"
00145                    " initial values");
00146       } else {
00147         // if this is a string, update the count accordingly
00148         if ( isStringLiteral(*val) ) {
00149           const char * str = (dynamic_cast<constNode *>(*val))->value().Str();
00150           count += strlen(str);
00151           result_init->exprs().splice(result_init->exprs().end(),
00152                                       strLit2Init(str)->exprs());
00153         } else {
00154           exprNode * initVal = eval_or_cast(*val, the_array->no_tdef_type());
00155           result_init->exprs().push_back(initVal);
00156         }
00157       }
00158       val++;
00159     }
00160     count++;
00161   } // end while
00162 
00163   if ( array_size.no_val() ) {
00164     the_array->dim(new constNode(constant::constant(count-1)));
00165   } else { 
00166     while ( count <= array_size.Integer() ) {
00167       // initialize to zero
00168       if ( arrayNode * sub_array =
00169            dynamic_cast<arrayNode *>(the_array->no_tdef_type()) )
00170         result_init->exprs().push_back(init_array(sub_array, end, end, false));
00171       else if ( structNode * sub_struct = 
00172                 dynamic_cast<structNode *>(the_array->no_tdef_type()) )
00173         result_init->exprs().push_back(init_struct(sub_struct, end, end,
00174                                                    false));
00175       else {
00176         primNode * elmtType = dynamic_cast<primNode *>(the_array->type());
00177         assert(elmtType);
00178         constant value = constant::cast(elmtType->basic(), constant(0));
00179         result_init->exprs().push_back(new constNode(value));
00180       }
00181       count++;
00182     }
00183   }
00184 
00185   if ( val != end && inSublist) {
00186     CBZ::Error(the_array->coord(), "Too many values in initializer list");
00187   }
00188 
00189   return result_init;
00190 }
00191 
00192 initializerNode * InitializerDismantle::init_struct(structNode * the_struct,
00193                                                     expr_list_p & val,
00194                                                     expr_list_p end,
00195                                                     bool inSublist) {
00196   initializerNode * result_init = new initializerNode(NULL);
00197 
00198   suespecNode * the_spec = the_struct->spec();
00199   decl_list_p field = the_spec->fields().begin();
00200   decl_list_p field_end = the_spec->fields().end();
00201 
00202   while ( val != end
00203           && field != field_end ) {
00204     if ( arrayNode * sub_array =
00205          dynamic_cast<arrayNode *>((*field)->no_tdef_type()) ) {
00206       initializerNode * sub_init = NULL;
00207       if ( initializerNode * cur_val =
00208            dynamic_cast<initializerNode *>(*val) ) {
00209         expr_list_p new_begin = cur_val->exprs().begin();
00210         sub_init = init_array(sub_array, new_begin, cur_val->exprs().end(),
00211                               true);
00212         val++;
00213       } else
00214         sub_init = init_array(sub_array, val, end, false);
00215 
00216       assert(sub_init);
00217       result_init->exprs().push_back(sub_init);
00218     } else if ( structNode * sub_struct =
00219                 dynamic_cast<structNode *>((*field)->no_tdef_type()) ) {
00220       initializerNode * sub_init = NULL;
00221       if ( initializerNode * cur_val =
00222            dynamic_cast<initializerNode *>(*val) ) {
00223         expr_list_p new_begin = cur_val->exprs().begin();
00224         sub_init = init_struct(sub_struct, new_begin, cur_val->exprs().end(),
00225                                true);
00226         val++;
00227       } else
00228         sub_init = init_struct(sub_struct, val, end, false);
00229 
00230       assert(sub_init);
00231       result_init->exprs().push_back(sub_init);
00232     } else {
00233       if ( initializerNode * init_expr =
00234            dynamic_cast<initializerNode *>(*val) ) {
00235         CBZ::Error(the_struct->coord(), "Scalar initialized by list of"
00236                    " initial values");
00237       } else {
00238         // TODO:  add handling of string literals
00239         exprNode * initVal = eval_or_cast(*val, (*field)->no_tdef_type());
00240         result_init->exprs().push_back(initVal);
00241       }
00242       val++;
00243     }
00244     field++;
00245   } // end while
00246 
00247   // pad the end with zeroes
00248   while ( field != field_end ) {
00249     if ( arrayNode * sub_array =
00250          dynamic_cast<arrayNode *>((*field)->no_tdef_type()) )
00251       result_init->exprs().push_back(init_array(sub_array, end, end, false));
00252     else if ( structNode * sub_struct = 
00253               dynamic_cast<structNode *>((*field)->no_tdef_type()) )
00254       result_init->exprs().push_back(init_struct(sub_struct, end, end, false));
00255     else {
00256       primNode * fieldType = dynamic_cast<primNode*>((*field)->no_tdef_type());
00257       assert(fieldType);
00258       constant value = constant::cast(fieldType->basic(), constant(0));
00259       result_init->exprs().push_back(new constNode(value));
00260     }
00261     field++;
00262   }
00263 
00264   if ( val != end && inSublist ) {
00265     CBZ::Error(the_struct->coord(), "Too many values in initializer list");
00266   }
00267 
00268   return result_init;
00269 }
00270 
00271 bool InitializerDismantle::isStringLiteral(exprNode * the_expr) {
00272   if ( constNode * the_const = dynamic_cast<constNode *>(the_expr) ) {
00273     return the_const->value().is_str();
00274   }
00275   return false;
00276 }
00277 
00278 initializerNode * InitializerDismantle::strLit2Init(const char * str) {
00279   initializerNode * newInit = new initializerNode(NULL);
00280   for ( int i = 0; i < strlen(str); i++ ) {
00281     char text[4];
00282     sprintf(text, "'%c'", str[i]);
00283     constNode * newConst = new constNode(constant::constant(str[i]), text);
00284     newConst->type(new primNode(basic_type::Char));
00285     newInit->add_expr(newConst);
00286   }
00287   newInit->add_expr(new constNode(constant::constant('\0')));
00288   return newInit;
00289 }
00290 
00291 // Dismantle "normal" initializers, like int a = 1;, into uninitialized
00292 // declarations and assignment statements
00293 Node * InitializerDismantle::at_decl(declNode * the_decl, Order ord) {
00294   if ( ord == Preorder ) {
00295     exprNode * initExpr = the_decl->init();
00296     if ( initExpr ) {
00297       if ( isStringLiteral(initExpr) 
00298            && the_decl->no_tdef_type()->typ() == Array ) {
00299         // turn the string literal into an array initializer
00300         char * str = (dynamic_cast<constNode *>(initExpr))->value().Str();
00301         initializerNode * newInit = strLit2Init(str);
00302         initExpr = newInit;
00303         the_decl->init(newInit);
00304       }
00305 
00306       // TODO: add handling for union & enum?
00307       if ( initializerNode * the_init 
00308              = dynamic_cast<initializerNode *>(initExpr) ) {
00309         typeNode * top_type = the_decl->no_tdef_type();
00310         if ( top_type->is_aggregate() ) { // struct or array
00311           expr_list_p val = the_init->exprs().begin();
00312           initializerNode * new_init = NULL;
00313           if ( arrayNode * the_array = dynamic_cast<arrayNode *>(top_type) )
00314             new_init = init_array(the_array, val, the_init->exprs().end(),
00315                                   true);
00316           else if ( structNode * the_struct = 
00317                     dynamic_cast<structNode *>(top_type) )
00318             new_init = init_struct(the_struct, val, the_init->exprs().end(),
00319                                    true);
00320           else
00321             assert(false); // TODO: better error reporting
00322 
00323           assert(new_init);
00324           the_decl->init(new_init);
00325         } else if ( top_type->is_scalar() ) {
00326           // it is valid to initailize a scalar with a single value, surrounded
00327           // by braces.
00328           if ( the_init->exprs().size() != 1 )
00329             CBZ::Error(the_decl->coord(), "Too many values in initializer"
00330                        " list");
00331           if ( the_init->exprs().front()->typ() == Initializer )
00332             CBZ::Error(the_decl->coord(), "Scalar initialized with a list"
00333                        " of initial values");
00334 
00335           init_scalar(the_decl, the_init->exprs().front());
00336         }
00337       } else { // the_init is not initializerNode
00338         init_scalar(the_decl, initExpr);
00339       } // end if ( the_init )
00340     } // end if ( initExpr )
00341   } // end if ( ord == Preorder )
00342   return the_decl;
00343 }

Generated on August 27, 2003
Back to the C-Breeze home page