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  

lir_gen_walker.cc

Go to the documentation of this file.
00001 // $Id: lir_gen_walker.cc,v 1.10 2003/08/11 17:38:52 abrown Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2002 University of Texas at Austin
00008 // 
00009 //  Chuck Tsen
00010 //  Charles Nevill
00011 //  Paul Arthur Navratil
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 #include <functional>
00040 #include <algorithm>
00041 #include "c_breeze.h"
00042 #include "ref_clone_changer.h"
00043 #include "lir_gen_walker.h"
00044 #include "lirutil.h"
00045 
00046 map<unsigned int, BinaryInstProc> lir_gen_walker::binary_map;
00047 map<unsigned int, UnaryInstProc> lir_gen_walker::unary_map;
00048 map<unsigned int, Compare_type> lir_gen_walker::opid_cmptype_map;
00049 
00050 lir_gen_walker::lir_gen_walker() : 
00051   Walker(Both, Subtree),
00052   _unit(0),
00053   _proc(0)
00054 {
00055   if ( binary_map.empty() 
00056        || unary_map.empty() 
00057        || opid_cmptype_map.empty() )
00058     init_maps();
00059 }
00060 
00061 void lir_gen_walker::init_maps(void) {
00062   binary_map['+'] = &LIR::Add;
00063   binary_map['*'] = &LIR::Mul;
00064   binary_map['/'] = &LIR::Div;
00065   binary_map['-'] = &LIR::Sub;
00066   binary_map['%'] = &LIR::Mod;
00067   binary_map['&'] = &LIR::BitwiseAND;
00068   binary_map['|'] = &LIR::BitwiseOR;
00069   binary_map['^'] = &LIR::BitwiseXOR;
00070   binary_map[Operator::LS] = &LIR::BitwiseShiftLeft;
00071   binary_map[Operator::RS] = &LIR::BitwiseShiftRight;
00072 
00073   unary_map['~'] = &LIR::BitwiseNOT;
00074   unary_map[Operator::UMINUS] = &LIR::Neg;
00075 
00076   opid_cmptype_map[Operator::EQ] = cmp_EQ;
00077   opid_cmptype_map[Operator::NE] = cmp_NE;
00078   opid_cmptype_map['<'] = cmp_LT;
00079   opid_cmptype_map[Operator::LE] = cmp_LE;
00080   opid_cmptype_map['>'] = cmp_GT;
00081   opid_cmptype_map[Operator::GE] = cmp_GE;
00082 }
00083 
00084 void lir_gen_walker::at_unit(unitNode * the_unit, Order ord) {
00085   if ( ord == Preorder ) {
00086     the_unit->instructions().clear();
00087     _unit = the_unit;
00088 
00089     AllocSizeChanger::size(the_unit);
00090 
00091     for ( def_list_p p = the_unit->defs().begin();
00092           p != the_unit->defs().end();
00093           p++ )
00094       gen_global_decl(*p);
00095 
00096     SizeofChanger soc;
00097     the_unit->change(soc);
00098   } else { // ord == Postorder
00099     _unit = NULL;
00100 
00101 #ifdef DEBUG
00102     // print out all LIR instructions at the unit level
00103     cout << "Initial unit LIR instruction listing:" << endl;
00104     instruction_list::const_iterator it = the_unit->instructions().begin();
00105     int num = 0;
00106     while ( it != the_unit->instructions().end() )
00107       cout << num++ << " " << **(it++) << endl;
00108     cout << endl << endl;
00109 #endif /* DEBUG */
00110   }
00111 }
00112 
00113 void lir_gen_walker::at_proc(procNode * the_proc, Order ord) {
00114   if ( ord == Preorder ) {
00115     _alloc.reset();
00116 
00117     _proc = the_proc;
00118     the_proc->instructions().clear();
00119     the_proc->lir_blocks().clear(); // ???
00120     int stackOffset = -1 * CBZ::ArchInfo.get_stack_extra_top();
00121     the_proc->set_initial_stack_local_offset(stackOffset);
00122 
00123     // determine what variables must be allocated to memory
00124     AllocToMemWalker atmw;
00125     the_proc->walk(atmw);
00126 
00127     the_proc->instructions().push_back(LIR::BeginProc(the_proc));
00128 
00129     // declare & allocate space for local variables
00130     for ( decl_list_p p = the_proc->body()->decls().begin();
00131           p != the_proc->body()->decls().end();
00132           p++ )
00133       gen_local_decl(*p, atmw);
00134     
00135     // declare (& allocate space) for formal arguments
00136     if ( funcNode * the_func =
00137          dynamic_cast<funcNode *>(the_proc->decl()->type()) ) {
00138       for ( decl_list_p p = the_func->args().begin();
00139             p != the_func->args().end();
00140             p++ )
00141         gen_arg_decl(*p, atmw);
00142         ;
00143     } else
00144       CBZFAIL(("procNode doesn't contain expected funcNode"));
00145 
00146   } else { // ord == Postorder
00147     the_proc->instructions().push_back(LIR::EndProc(the_proc));
00148     _proc = NULL;
00149 
00150 #ifdef DEBUG
00151     // print out all of the instructions
00152     cout << "Initial proc LIR instruction listing:" << endl;
00153     instruction_list::const_iterator it = the_proc->instructions().begin();
00154     int num = 0;
00155     while ( it != the_proc->instructions().end() )
00156       cout << num++ << " " << **(it++) << endl;
00157     cout << endl << endl;
00158 #endif /* DEBUG */
00159   }
00160 }
00161 
00162 void lir_gen_walker::at_threeAddr(threeAddrNode * the_3addr, Order ord) {
00163   if ( ord == Preorder ) {
00164     if ( the_3addr->lhs() )
00165       gen_assignment(the_3addr);
00166     else if ( the_3addr->op()
00167               && the_3addr->op()->id() == Operator::FUNC_CALL )
00168       gen_call(the_3addr);
00169     else
00170       CBZFAIL(("Ill-formed threeAddrNode"));
00171   }
00172 }
00173 
00174 void lir_gen_walker::at_goto(gotoNode *the_goto, Order ord){
00175   if ( ord == Preorder ) {
00176     assert(the_goto->label());
00177     gen_goto(the_goto);
00178   }
00179 }
00180 
00181 void lir_gen_walker::at_label(labelNode *the_label, Order ord){
00182   if (ord == Preorder)
00183     gen_label(the_label);
00184 }
00185 
00186 void lir_gen_walker::at_conditiongoto(conditiongotoNode * the_condgoto,
00187                                       Order ord) {
00188   if ( ord == Preorder ) {
00189     assert(the_condgoto->left() && the_condgoto->right()
00190            && the_condgoto->label() && the_condgoto->op()->is_comparison());
00191     gen_conditional_branch(the_condgoto);
00192   }
00193 }
00194 
00195 void lir_gen_walker::at_return(returnNode *the_return, Walker::Order ord) {
00196   if (ord == Preorder ) {
00197     assert(the_return->proc_exit());
00198     gen_return(the_return);
00199   }
00200 }
00201 
00202 expr_list * lir_gen_walker::flatten_init(exprNode * expr) {
00203   expr_list * retlist = new expr_list;
00204   if ( initializerNode * init =
00205        dynamic_cast<initializerNode *>(expr) ) {
00206     for ( expr_list_p p = init->exprs().begin(); 
00207           p != init->exprs().end(); 
00208           p++) {
00209       expr_list * sublist = flatten_init(*p);
00210       retlist->splice(retlist->end(), *sublist);
00211       delete sublist;
00212     }
00213   } else 
00214     retlist->push_back(expr);
00215   return retlist;
00216 }
00217 
00218 void lir_gen_walker::gen_global_decl(defNode * the_def) {
00219   if ( declNode * the_decl = dynamic_cast<declNode *>(the_def) ) {
00220     if ( the_decl->decl_location() == declNode::TOP 
00221          && the_decl->storage_class() != declNode::TYPEDEF 
00222          && the_decl->storage_class() != declNode::EXTERN ) {
00223       declNode::Storage_location & loc = the_decl->storage_location();
00224       loc._type = declNode::Storage_location::storageloc_mem_global;
00225 //       loc._global_size = the_decl->type()->alloc_size();
00226 //       loc._global_align = the_decl->type()->alloc_align();
00227       if ( the_decl->init() ) {
00228         _unit->instructions().push_back(LIR::DeclareGlobal(the_decl));
00229         _unit->instructions().push_back(LIR::Label(the_decl->name()));
00230         expr_list * inits = flatten_init(the_decl->init());
00231 
00232         for (expr_list_p p = inits->begin(); p != inits->end(); p++ ) {
00233           // we rely on the proper type information, either in the constNode
00234           // or as a castNode is present in the initializer list.  in this
00235           // way, we only need to traverse the initializer list, and not
00236           // the declNode type()
00237           (*p)->eval();
00238           assert(!(*p)->value().no_val());
00239           
00240           LirInst * newInst = NULL;
00241 
00242           // TODO: turn this into a lookup table
00243           typeNode * type = (*p)->no_tdef_type();
00244           if ( type->is_pointer() )
00245             if ( type->is_aggregate() )
00246               newInst = LIR::StaticDataString((*p)->value());
00247             else
00248               newInst = LIR::StaticDataInt((*p)->value());
00249           else if ( primNode * prim = dynamic_cast<primNode *>(type) ) {
00250             basic_type basic = prim->basic();
00251             if ( basic.is_char() )
00252               newInst = LIR::StaticDataChar((*p)->value());
00253             else if ( basic.is_int() )
00254               if ( basic.is_short() )
00255                 newInst = LIR::StaticDataShort((*p)->value());
00256               else if ( basic.is_long() )
00257                 newInst = LIR::StaticDataLong((*p)->value());
00258               else
00259                 newInst = LIR::StaticDataInt((*p)->value());
00260             else if ( basic.is_float() )
00261               if ( basic.is_long() )
00262                 newInst = LIR::StaticDataDouble((*p)->value());
00263               else
00264                 newInst = LIR::StaticDataSingle((*p)->value());
00265           }
00266           assert(newInst);
00267           _unit->instructions().push_back(newInst);
00268         } // end for ( ... inits ... )
00269 
00270         delete inits;
00271       } else {
00272         LirInst * newInst = 
00273           LIR::StaticDataUninit(the_decl->name(),
00274                                 the_decl->type()->alloc_size());
00275         _unit->instructions().push_back(newInst);
00276       }
00277     } 
00278   }
00279 }
00280 
00281 void lir_gen_walker::gen_arg_decl(declNode * the_decl,
00282                                   AllocToMemWalker & atmw) {
00283   if ( the_decl->type()->is_void() )
00284     return;
00285 
00286   assert(the_decl->decl_location() == declNode::FORMAL);
00287 
00288   declNode::Storage_location & loc = the_decl->storage_location();
00289   assert(loc._type == declNode::Storage_location::storageloc_unknown);
00290 
00291   Register reg;
00292   typeNode * type = the_decl->no_tdef_type();
00293 
00294   assert(!type->is_ellipsis());
00295 
00296   if ( _alloc.assign_arg_register(type, reg) ) {
00297     // argument will be assigned to a register
00298     loc._type = declNode::Storage_location::storageloc_register;
00299     loc._register = reg;
00300   } else {
00301     // argument will be pushed onto the stack
00302     int stackLoc = _alloc.assign_arg_stack(type);
00303     loc._type = declNode::Storage_location::storageloc_stack;
00304     loc._stack_offset = stackLoc;
00305   }
00306 
00307   _proc->instructions().push_back(LIR::DeclareLocal(the_decl));
00308 
00309   if ( ( CBZ::NoRegAlloc || atmw.needsMem(the_decl) ) 
00310        && loc._type != declNode::Storage_location::storageloc_stack ) {
00311     // it must live on the stack, but currently doesn't, so store it to the
00312     // stack upon entry to procedure
00313     assert(loc._type == declNode::Storage_location::storageloc_register);
00314 
00315     // create a temporary stack variable, so that we can allocate it
00316     declNode * tempDecl = LirUtil::new_auto_decl(type);
00317     _proc->alloc_stack_local(tempDecl);
00318 
00319     // use the storage allocated to the temporary for the argument
00320     declNode::Storage_location oldLoc = loc;
00321     loc = tempDecl->storage_location();
00322     delete tempDecl;
00323 
00324     _proc->instructions().push_back(LIR::Store(type, oldLoc._register,
00325                                                the_decl, Register::getRegFp(),
00326                                                DATA_CONTENTS_FRAMEP,
00327                                                loc._stack_offset,
00328                                                NULL));
00329   }
00330 }
00331 
00332 void lir_gen_walker::gen_local_decl(declNode * the_decl,
00333                                     AllocToMemWalker & atmw) {
00334   assert(the_decl->storage_class() != declNode::STATIC);
00335   assert(the_decl->decl_location() == declNode::BLOCK);
00336 
00337   declNode::Storage_location & loc = the_decl->storage_location();
00338   assert(loc._type == declNode::Storage_location::storageloc_unknown);
00339 
00340   if ( the_decl == _proc->return_decl() ) {
00341     // this is the decl for the return value from the procedure
00342     Register reg;
00343     if ( Register::getRegRetVal(the_decl->no_tdef_type(), reg) ) {
00344       loc._type = declNode::Storage_location::storageloc_register;
00345       loc._register = reg;
00346     } else {
00347       // must return the value on the stack
00348       // TODO
00349       assert(false);
00350     }
00351   } else if ( atmw.needsMem(the_decl) || CBZ::NoRegAlloc ) {
00352     _proc->alloc_stack_local(the_decl);
00353   } else {
00354     _alloc.assign_register(the_decl);
00355   }
00356   _proc->instructions().push_back(LIR::DeclareLocal(the_decl));
00357   if ( the_decl->init() ) {
00358     // it has a non-scalar initializer
00359     assert(false);
00360   }
00361 }
00362 
00363 // a = ...
00364 void lir_gen_walker::gen_assignment(threeAddrNode * the_3addr) {
00365   if ( ! the_3addr->op() )
00366     gen_simple_assignment(the_3addr);
00367   else if ( the_3addr->op()->is_binary() )
00368     gen_binary_assignment(the_3addr);
00369   else if ( the_3addr->op()->is_unary() )
00370     gen_unary_assignment(the_3addr);
00371   else if ( the_3addr->op()->id() == Operator::FUNC_CALL )
00372     gen_call_assignment(the_3addr);
00373   else
00374     CBZFAIL(("Unknown assignment"));
00375 }
00376 
00377 // a = b
00378 void lir_gen_walker::gen_simple_assignment(threeAddrNode * the_3addr) {
00379   assert(the_3addr->rhs1());
00380   typeNode * type = the_3addr->lhs()->type();
00381   if ( type->is_scalar() ) {
00382     // really a simple assignment
00383     pair<Register, declNode *> loaded = gen_load(the_3addr->rhs1());
00384     gen_store(the_3addr->lhs(), loaded.first, loaded.second);
00385   } else if ( structNode * the_struct = dynamic_cast<structNode *>(type) ) {
00386     // actually an assignment from one struct to another 
00387     // TODO: implement a Memcpy LIR instruction & use it here
00388     assert(false);
00389   } else
00390     CBZFAIL(("Invalid simple assignment"));
00391 }
00392 
00393 // a = <unop> b
00394 void lir_gen_walker::gen_unary_assignment(threeAddrNode * the_3addr) {
00395   pair<Register, declNode *> rhsLoaded = gen_load(the_3addr->rhs1());
00396   
00397   // do the operation
00398   Register resultReg;
00399   declNode * resultDecl = NULL;
00400   _alloc.get_temp_var(the_3addr->lhs()->type(), resultReg, resultDecl);
00401   LirInst * new_inst =
00402     unary_map[the_3addr->op()->id()](the_3addr->lhs()->type(),
00403                                      resultReg, resultDecl,
00404                                      rhsLoaded.first,
00405                                      rhsLoaded.second);
00406   _proc->instructions().push_back(new_inst);
00407   gen_store(the_3addr->lhs(), resultReg, resultDecl);
00408 }
00409 
00410 // a = b <binop> c
00411 void lir_gen_walker::gen_binary_assignment(threeAddrNode * the_3addr) {
00412   pair<Register, declNode *> rhs1Loaded;
00413   pair<Register, declNode *> rhs2Loaded;
00414 
00415   bool rhs1Pointer = ( the_3addr->rhs1()->type()->typ() == Ptr );
00416   bool rhs2Pointer = ( the_3addr->rhs2()->type()->typ() == Ptr );
00417   // handle pointer arithmetic
00418   if ( ( rhs1Pointer && ! rhs2Pointer ) 
00419        || ( rhs2Pointer && !rhs1Pointer ) ) {
00420     // TODO:  check C lang. spec. about this.
00421     assert(the_3addr->op()->id() == '-'
00422            || the_3addr->op()->id() == '+');
00423     operandNode * ptrNode = NULL;
00424     operandNode * intNode = NULL;
00425     if ( rhs1Pointer ) {
00426       ptrNode = the_3addr->rhs1();
00427       intNode = the_3addr->rhs2();
00428     } else {
00429       ptrNode = the_3addr->rhs2();
00430       intNode = the_3addr->rhs1();
00431     }
00432     typeNode * typePointed = ptrNode->noncast_type(false)->type();
00433     int size = typePointed->alloc_size();
00434     if ( size != 1 ) {
00435       // TODO: fold the potential constants here (or later in constant
00436       // prop/folding phase)
00437       pair<Register, declNode *> ptrLoaded = gen_load(ptrNode);
00438       pair<Register, declNode *> intLoaded = gen_load(intNode);
00439 
00440       Register prodReg;
00441       declNode * prodDecl;
00442       _alloc.get_temp_var(intNode->type(), prodReg, prodDecl);
00443       reg_or_const sizeConst = constant::constant(size);
00444       _proc->instructions().push_back(LIR::Mul(intNode->type(),
00445                                                prodReg, prodDecl,
00446                                                intLoaded.first,
00447                                                intLoaded.second,
00448                                                sizeConst, NULL));
00449 
00450       // TODO: correct/safe?
00451       rhs1Loaded = ptrLoaded;
00452       rhs2Loaded = pair<Register, declNode *>(prodReg, prodDecl);
00453     } else { // size == 1
00454       rhs1Loaded = gen_load(the_3addr->rhs1());
00455       rhs2Loaded = gen_load(the_3addr->rhs2());
00456     }
00457   } else {
00458     // not dealing with pointer arithmetic, just normal
00459     rhs1Loaded = gen_load(the_3addr->rhs1());
00460     // TODO:  avoid 'reloading' if same as rhs1
00461     rhs2Loaded = gen_load(the_3addr->rhs2());
00462   }
00463 
00464   // do the actual operation
00465   Register resultReg;
00466   declNode * resultDecl = NULL;
00467   _alloc.get_temp_var(the_3addr->lhs()->type(), resultReg, resultDecl);
00468   LirInst * new_inst = 
00469     binary_map[the_3addr->op()->id()](the_3addr->lhs()->type(),
00470                                       resultReg, resultDecl,
00471                                       rhs1Loaded.first,
00472                                       rhs1Loaded.second,
00473                                       rhs2Loaded.first,
00474                                       rhs2Loaded.second);
00475   _proc->instructions().push_back(new_inst);
00476   gen_store(the_3addr->lhs(), resultReg, resultDecl);
00477 }
00478 
00479 // a = b(...)
00480 void lir_gen_walker::gen_call_assignment(threeAddrNode * the_3addr) {
00481   gen_call(the_3addr);
00482 
00483   typeNode * type = the_3addr->lhs()->type();
00484   if ( type->is_scalar() ) {
00485     Register reg;
00486     if ( Register::getRegRetVal(type, reg) ) {
00487       gen_store(the_3addr->lhs(), reg, DATA_CONTENTS_RETVAL);
00488     } else
00489       CBZFAIL(("No return register for scalar type"));
00490   } else {
00491     // return value is NOT in a register
00492     assert(false);
00493   }
00494 }
00495 
00496 void lir_gen_walker::gen_conditional_branch(conditiongotoNode * the_condgoto) {
00497   pair<Register, declNode *> leftLoaded = gen_load(the_condgoto->left());
00498   pair<Register, declNode *> rightLoaded = gen_load(the_condgoto->right());
00499   _proc->instructions().push_back(LIR::Compare(leftLoaded.first, 
00500                                                leftLoaded.second,
00501                                                rightLoaded.first,
00502                                                rightLoaded.second));
00503   LirInst * new_inst =
00504     LIR::Branch(opid_cmptype_map[the_condgoto->op()->id()],
00505                 the_condgoto->label()->name());
00506   _proc->instructions().push_back(new_inst);
00507 }
00508 
00509 void lir_gen_walker::gen_goto(gotoNode * the_goto) {
00510   _proc->instructions().push_back(LIR::Jmp(the_goto->name()));
00511 }
00512 
00513 void lir_gen_walker::gen_label(labelNode * the_label) {
00514   _proc->instructions().push_back(LIR::Label(the_label->name()));
00515 }
00516 
00517 void lir_gen_walker::gen_return(returnNode * the_return) {
00518   // if a value is returned, it will have been taken care of by
00519   // the register (or stack) allocation of the declNode corresponding
00520   // to the return value for the proc, so we just need to put the 'Return' in
00521 
00522   _proc->instructions().push_back(LIR::Return(_proc));
00523 }
00524 
00525 void lir_gen_walker::gen_call(threeAddrNode * the_3addr) {
00526   // add sequencing instruction
00527   _proc->instructions().push_back(LIR::CallPre());
00528   
00529   operand_list & args = the_3addr->arg_list();
00530   operand_list_p currArg = args.begin();
00531   int nextFixed = 0;
00532   int nextFloat = 0;
00533   Register currReg;
00534   const arch_info::register_info_list & fixedRegs =
00535     CBZ::ArchInfo.get_regs_param_fixed();
00536   const arch_info::register_info_list & floatRegs =
00537     CBZ::ArchInfo.get_regs_param_float();
00538 
00539   int stack_arg_bytes = 0;
00540   int nextStackOffset = CBZ::ArchInfo.get_stack_extra_bottom();
00541   while ( currArg != args.end() ) {
00542     bool isFloat = (*currArg)->type()->is_float();
00543     bool isFixed = (*currArg)->type()->is_integer() 
00544       || (*currArg)->type()->is_pointer();
00545 
00546     if ( isFloat && nextFloat < floatRegs.size() ) {
00547       currReg = *(floatRegs[nextFloat++]);
00548       pair<Register, declNode *> argLoaded = gen_load(*currArg);
00549       gen_move(currReg, DATA_CONTENTS_REG_OUT, argLoaded.first,
00550                argLoaded.second);
00551     } else if ( isFixed && nextFixed < fixedRegs.size() ) {
00552       currReg = *(fixedRegs[nextFixed++]);
00553       pair<Register, declNode *> argLoaded = gen_load(*currArg);
00554       gen_move(currReg, DATA_CONTENTS_REG_OUT, argLoaded.first,
00555                argLoaded.second);
00556     } else {
00557       // push the argument onto the stack
00558 
00559       // update stack_arg_bytes
00560       typeNode * argType = (*currArg)->type();
00561       AllocSizeChanger::size(argType);
00562       int align = argType->alloc_align();
00563       int size = argType->alloc_size();
00564       nextStackOffset = ((nextStackOffset + align - 1) / align ) * align;
00565 
00566       if ( (*currArg)->type()->is_scalar() ) {
00567         pair<Register, declNode *> argLoaded = gen_load(*currArg);
00568         _proc->instructions().push_back(LIR::Store((*currArg)->type(),
00569                                                    argLoaded.first,
00570                                                    argLoaded.second,
00571                                                    Register::getRegSp(),
00572                                                    DATA_CONTENTS_STACKP,
00573                                                    nextStackOffset,
00574                                                    NULL));
00575       } else {
00576         // copy the arg onto the stack
00577         // TODO: implement Memcpy LIR instruction & use it here
00578         assert(false);
00579       }
00580       nextStackOffset += size;
00581       stack_arg_bytes += size;
00582     }
00583     currArg++;
00584   } // end while ( currArg != args.end() )
00585 
00586   _proc->instructions().push_back(LIR::Call(the_3addr, stack_arg_bytes));
00587 }
00588 
00589 pair<Register, declNode *> lir_gen_walker::gen_load(indexNode * the_index) {
00590   if ( idNode * the_id = dynamic_cast<idNode *>(the_index) ) {
00591     if ( the_id->decl()->decl_location() == declNode::TOP )
00592       return load_global_var(the_id);
00593     else
00594       return load_stack_var(the_id);
00595   } else if ( constNode * the_const = dynamic_cast<constNode *>(the_index) ) {
00596     return load_const(the_const);
00597   } else
00598     CBZFAIL(("Unknown indexNode"));
00599 }
00600 
00601 pair<Register, declNode *> lir_gen_walker::gen_load(operandNode * the_oper) {
00602   if ( idNode * the_id = dynamic_cast<idNode *>(the_oper->var()) ) {
00603     if ( the_id->decl()->decl_location() == declNode::TOP )
00604       return load_global(the_oper);
00605     else
00606       return load_stack(the_oper);
00607   } 
00608   else if (constNode * the_const = dynamic_cast<constNode*>(the_oper->var())) {
00609     assert(the_oper->fields().empty() && !the_oper->index());
00610     return load_const(the_const);
00611   } else
00612     CBZFAIL(("Malformed operandNode"));
00613 }
00614 
00615 int lir_gen_walker::field_offset(operandNode * the_oper) {
00616   int offset = 0;
00617  
00618   typeNode * containingType = the_oper->var()->type()->follow_tdefs();
00619   if ( the_oper->star() )
00620     containingType = containingType->type()->follow_tdefs();
00621 
00622   for ( id_list_p operField = the_oper->fields().begin();
00623         operField != the_oper->fields().end();
00624         operField++ ) {
00625     if ( structNode * containingStruct = 
00626          dynamic_cast<structNode *>(containingType) ) {
00627       suespecNode * suespec = containingStruct->spec();
00628       assert(suespec);
00629       for ( decl_list_p structField = suespec->fields().begin();
00630             structField != suespec->fields().end()
00631               && (*structField) != (*operField)->decl();
00632             structField++ ) {
00633         int align = (*structField)->type()->alloc_align();
00634         int size = (*structField)->type()->alloc_size();
00635         offset = (( (offset + size) + align - 1) / align) * align;
00636 //      cout << size << " / " << align << " @ " << offset << endl;
00637       }
00638     }
00639     containingType = (*operField)->decl()->type()->follow_tdefs();
00640   }
00641   typeNode * type = the_oper->type(); // the_oper->noncast_type(false)?
00642   AllocSizeChanger::size(type);
00643   int align = type->alloc_align();
00644   offset = (( offset + align - 1) / align) * align;
00645 
00646 //   cout << ">>>>>>>>" <<  offset << endl;
00647   return offset;
00648 }
00649 
00650 pair<reg_or_const, declNode *> lir_gen_walker::index_offset
00651 (
00652  operandNode * the_oper
00653  ) 
00654 {
00655   if ( the_oper->index() ) {
00656     typeNode * elmtType = the_oper->noncast_type(false);
00657 
00658     // must ensure that potentially new ptrNode has the right size
00659     int elmtSize = elmtType->alloc_size();
00660     if ( idNode * idIndex = dynamic_cast<idNode *>(the_oper->index()) ) {
00661       pair<Register, declNode *> indexLoaded = gen_load(idIndex);
00662 
00663       Register resultReg;
00664       declNode * resultDecl;
00665       primNode * intType = new primNode(basic_type::Int);
00666       _alloc.get_temp_var(intType, resultReg, resultDecl);
00667       _proc->instructions().push_back(LIR::Mul(intType, resultReg, resultDecl,
00668                                                indexLoaded.first,
00669                                                indexLoaded.second,
00670                                                constant::constant(elmtSize),
00671                                                NULL));
00672       return pair<reg_or_const, declNode *>(resultReg, resultDecl);
00673     } else {
00674       constNode * constIndex = dynamic_cast<constNode *>(the_oper->index());
00675       assert(constIndex);
00676       constant constVal = elmtSize * constIndex->value().Integer();
00677 
00678       return pair<reg_or_const, declNode *>(constVal, NULL);
00679     }
00680   } // !the_oper->index()
00681   return pair<reg_or_const, declNode *>(constant::constant(0), NULL);
00682 }
00683 
00684 pair<Register, declNode *> lir_gen_walker::load_global(operandNode * the_oper)
00685 {
00686   if ( the_oper->addr() ) { // want the effective address of the thing
00687     return load_global_ea(the_oper);
00688   } else if ( arrayNode * arrayType = 
00689               dynamic_cast<arrayNode *>(the_oper->noncast_type(false)) ) {
00690     // result is an "array", aka: a pointer into an array
00691     return load_global_ea(the_oper);
00692   } else { // we want the value in the location
00693     return load_global_value(the_oper);
00694   }
00695 }
00696 
00697 // TODO: factor common code from load_stack_ea
00698 pair<Register, declNode *> lir_gen_walker::load_global_ea
00699 (
00700  operandNode * the_oper
00701  )
00702 {
00703   idNode * the_id = dynamic_cast<idNode *>(the_oper->var());
00704   assert(the_id);
00705   int fieldOffset = field_offset(the_oper);
00706   pair<reg_or_const, declNode *> indexOffset = index_offset(the_oper);
00707 
00708   pair<Register, declNode *> base;
00709   if ( the_oper->star() )
00710     base = load_global_var(the_id);
00711   else
00712     base = load_global_addr(the_id);
00713 
00714   if ( indexOffset.first._is_const ) {
00715     int offset = fieldOffset + indexOffset.first._const.Integer();
00716     if ( offset ) {
00717       Register addrReg;
00718       declNode * addrDecl;
00719       _alloc.get_temp_ptr(addrReg, addrDecl);
00720       // TODO: determine when to add the immediate directly w/o load
00721       constNode * offsetConst = new constNode(constant::constant(offset));
00722       pair<Register, declNode *> offLoaded = load_const(offsetConst);
00723       _proc->instructions().push_back(LIR::Add(LirUtil::newVoidPtr(),
00724                                                addrReg, addrDecl,
00725                                                base.first, base.second,
00726                                                offLoaded.first,
00727                                                offLoaded.second));
00728       return pair<Register, declNode *>(addrReg, addrDecl);
00729     } else { // offset == 0
00730       return base;
00731     }
00732   } else { // indexOffset is in a register
00733     if ( fieldOffset ) {
00734       Register tempReg;
00735       declNode * tempDecl;
00736       _alloc.get_temp_ptr(tempReg, tempDecl);
00737       // TODO:  determine when to add the immediate directly w/o load
00738       constNode * offsetConst = new constNode(constant::constant(fieldOffset));
00739       pair<Register, declNode *> offLoaded = load_const(offsetConst);
00740       _proc->instructions().push_back(LIR::Add(LirUtil::newVoidPtr(),
00741                                                tempReg, tempDecl,
00742                                                base.first, base.second,
00743                                                offLoaded.first,
00744                                                offLoaded.second));
00745       base = pair<Register, declNode *>(tempReg, tempDecl);
00746     }
00747     Register addrReg;
00748     declNode * addrDecl;
00749     _alloc.get_temp_ptr(addrReg, addrDecl);
00750     _proc->instructions().push_back(LIR::Add(LirUtil::newVoidPtr(),
00751                                              addrReg, addrDecl,
00752                                              base.first, base.second,
00753                                              indexOffset.first._reg,
00754                                              indexOffset.second));
00755     return pair<Register, declNode *>(addrReg, addrDecl);
00756   }
00757 }
00758 
00759 // TODO: factor common code from load_stack_value
00760 pair<Register, declNode *> lir_gen_walker::load_global_value
00761 (
00762  operandNode * the_oper
00763  )
00764 {
00765   idNode * the_id = dynamic_cast<idNode *>(the_oper->var());
00766   assert(the_id);
00767   int fieldOffset = field_offset(the_oper);
00768 
00769   Register loadReg;
00770   declNode * loadDecl;
00771   _alloc.get_temp_var(the_oper->noncast_type(), loadReg, loadDecl);
00772   const declNode::Storage_location & loc = the_id->decl()->storage_location();
00773   assert(loc._type == declNode::Storage_location::storageloc_mem_global);
00774 
00775   if ( the_oper->index() ) {
00776     pair<reg_or_const, declNode *> indexOffset = index_offset(the_oper);
00777     int offset = fieldOffset;
00778     pair<Register, declNode *> base;
00779 
00780     if ( the_id->type()->typ() == Ptr ) {
00781       base = load_global_var(the_id);
00782       if ( the_oper->star() ) {
00783         // handles (*global) [.field]* '[' index ']'
00784         Register tempReg;
00785         declNode * tempDecl;
00786         _alloc.get_temp_ptr(tempReg, tempDecl);
00787         _proc->instructions().push_back(LIR::Load(LirUtil::newVoidPtr(),
00788                                                   tempReg, tempDecl,
00789                                                   base.first, base.second,
00790                                                   constant::constant(0),
00791                                                   NULL));
00792         base = pair<Register, declNode *>(tempReg, tempDecl);
00793       }
00794     } else {
00795       base = load_global_addr(the_id);
00796     }
00797 
00798     if ( indexOffset.first._is_const )
00799       offset += indexOffset.first._const.Integer();
00800     else { // indexOffset is in a register
00801       // TODO: see note w/ LIR::LoadStatic
00802       Register tempReg;
00803       declNode * tempDecl;
00804       _alloc.get_temp_ptr(tempReg, tempDecl);
00805       _proc->instructions().push_back(LIR::Add(LirUtil::newVoidPtr(),
00806                                                tempReg, tempDecl,
00807                                                base.first, base.second,
00808                                                indexOffset.first._reg,
00809                                                indexOffset.second));
00810       base = pair<Register, declNode *>(tempReg, tempDecl);
00811     }
00812 
00813     _proc->instructions().push_back(LIR::Load(the_oper->noncast_type(),
00814                                               loadReg, loadDecl,
00815                                               base.first, base.second,
00816                                               constant::constant(offset),
00817                                               NULL));
00818   } else {
00819     if ( the_oper->star() ) {
00820       pair<Register, declNode *> base = load_global_var(the_id);
00821       LirInst * newInst = LIR::Load(the_oper->noncast_type(),
00822                                     loadReg, loadDecl,
00823                                     base.first, base.second,
00824                                     constant::constant(fieldOffset),
00825                                     NULL);
00826       _proc->instructions().push_back(newInst);
00827     } else {
00828       LirInst * newInst = LIR::LoadStatic(the_oper->noncast_type(), 
00829                                           loadReg, loadDecl,
00830                                           the_id->name(), the_id->decl(),
00831                                           constant::constant(fieldOffset),
00832                                           NULL);
00833       _proc->instructions().push_back(newInst);
00834     }
00835   }
00836 
00837   if ( needs_conversion(the_oper->noncast_type(), the_oper->type()) )
00838     return gen_conversion(the_oper->type(), loadReg, loadDecl);
00839   else
00840     return pair<Register, declNode *>(loadReg, loadDecl);
00841 }
00842 
00843 pair<Register, declNode *> lir_gen_walker::load_global_var(idNode * the_id) {
00844   const declNode::Storage_location & loc = the_id->decl()->storage_location();
00845   assert(loc._type == declNode::Storage_location::storageloc_mem_global);
00846 
00847   Register reg;
00848   declNode * regDecl;
00849   _alloc.get_temp_var(the_id->type(), reg, regDecl);
00850   _proc->instructions().push_back(LIR::LoadStatic(the_id->type(), reg, regDecl,
00851                                                   the_id->name(), 
00852                                                   the_id->decl(),
00853                                                   constant::constant(0),
00854                                                   NULL));
00855   return pair<Register, declNode *>(reg, regDecl);
00856 }
00857 
00858 pair<Register, declNode *> lir_gen_walker::load_global_addr(idNode * the_id) {
00859   const declNode::Storage_location & loc = the_id->decl()->storage_location();
00860   assert(loc._type == declNode::Storage_location::storageloc_mem_global);
00861 
00862   Register reg;
00863   declNode * regDecl;
00864   _alloc.get_temp_ptr(reg, regDecl);
00865   _proc->instructions().push_back(LIR::GetGlobalAddress(reg, regDecl,
00866                                                         the_id->name(),
00867                                                         the_id->decl(),
00868                                                         constant::constant(0),
00869                                                         NULL));
00870   return pair<Register, declNode *>(reg, regDecl);
00871 }
00872 
00873 pair<Register, declNode *> lir_gen_walker::load_stack(operandNode * the_oper) {
00874   if ( the_oper->addr() ) { // we want the effective address of the thing
00875     return load_stack_ea(the_oper);
00876   } else if ( arrayNode * arrayType =
00877               dynamic_cast<arrayNode *>(the_oper->noncast_type(false)) ) {
00878     // result is an "array", aka: a pointer into an array
00879     return load_stack_ea(the_oper);
00880   } else { // we want the value in the location
00881     return load_stack_value(the_oper);
00882   }
00883 }
00884 
00885 // TODO: factor common code from load_global_ea
00886 pair<Register, declNode *> lir_gen_walker::load_stack_ea
00887 (
00888  operandNode * the_oper
00889  )
00890 {
00891   idNode * the_id = dynamic_cast<idNode *>(the_oper->var());
00892   assert(the_id);
00893   int fieldOffset = field_offset(the_oper);
00894   pair<reg_or_const, declNode *> indexOffset = index_offset(the_oper);
00895 
00896   pair<Register, declNode *> base;
00897   if ( the_oper->star() )
00898     base = load_stack_var(the_id);
00899   else
00900     base = load_stack_addr(the_id);
00901   if ( indexOffset.first._is_const ) {
00902     int offset = fieldOffset + indexOffset.first._const.Integer();
00903     if ( offset ) {
00904       Register addrReg;
00905       declNode * addrDecl;
00906       _alloc.get_temp_ptr(addrReg, addrDecl);
00907       // TODO: determine when to add the immediate directly w/o load
00908       constNode * offsetConst = new constNode(constant::constant(offset));
00909       pair<Register, declNode *> offLoaded = load_const(offsetConst);
00910       _proc->instructions().push_back(LIR::Add(LirUtil::newVoidPtr(),
00911                                                addrReg, addrDecl,
00912                                                base.first, base.second,
00913                                                offLoaded.first,
00914                                                offLoaded.second));
00915       return pair<Register, declNode *>(addrReg, addrDecl);
00916     } else { // offset == 0
00917       return base;
00918     }
00919   } else { // indexOffset is in a register
00920     if ( fieldOffset ) {
00921       Register tempReg;
00922       declNode * tempDecl;
00923       _alloc.get_temp_ptr(tempReg, tempDecl);
00924       // TODO: determine when to add the immediate directly w/o load
00925       constNode * offsetConst = new constNode(constant::constant(fieldOffset));
00926       pair<Register, declNode *> offLoaded = load_const(offsetConst);
00927       _proc->instructions().push_back(LIR::Add(LirUtil::newVoidPtr(),
00928                                                tempReg, tempDecl,
00929                                                base.first, base.second,
00930                                                offLoaded.first,
00931                                                offLoaded.second));
00932       base = pair<Register, declNode *>(tempReg, tempDecl);
00933     }
00934     Register addrReg;
00935     declNode * addrDecl;
00936     _alloc.get_temp_ptr(addrReg, addrDecl);
00937     _proc->instructions().push_back(LIR::Add(LirUtil::newVoidPtr(),
00938                                              addrReg, addrDecl,
00939                                              base.first, base.second,
00940                                              indexOffset.first._reg,
00941                                              indexOffset.second));
00942     return pair<Register, declNode *>(addrReg, addrDecl);
00943   }
00944 }
00945 
00946 // TODO: factor common code from load_global_value
00947 pair<Register, declNode *> lir_gen_walker::load_stack_value
00948 (
00949  operandNode * the_oper
00950  )
00951 {
00952   idNode * the_id = dynamic_cast<idNode *>(the_oper->var());
00953   assert(the_id);
00954   int fieldOffset = field_offset(the_oper);
00955 
00956   Register loadReg;
00957   declNode * loadDecl;
00958   _alloc.get_temp_var(the_oper->noncast_type(), loadReg, loadDecl);
00959   const declNode::Storage_location & loc = the_id->decl()->storage_location();
00960 
00961   pair<Register, declNode *> base;
00962   int offset = fieldOffset;
00963 
00964   if ( the_oper->index() ) {
00965     pair<reg_or_const, declNode *> indexOffset = index_offset(the_oper);
00966     if ( the_id->type()->typ() == Ptr ) {
00967       base = load_stack_var(the_id);
00968       if ( the_oper->star() ) {
00969         // handles:  (*var) [.field]* '[' index ']'
00970         Register tempReg;
00971         declNode * tempDecl;
00972         _alloc.get_temp_ptr(tempReg, tempDecl);
00973         _proc->instructions().push_back(LIR::Load(LirUtil::newVoidPtr(),
00974                                                   tempReg, tempDecl,
00975                                                   base.first, base.second,
00976                                                   constant::constant(0),
00977                                                   NULL));
00978         base = pair<Register, declNode *>(tempReg, tempDecl);
00979       }
00980     } else {
00981       base = pair<Register, declNode *>(Register::getRegFp(),
00982                                         DATA_CONTENTS_FRAMEP);
00983       offset += loc._stack_offset;
00984     }
00985     
00986     if ( indexOffset.first._is_const )
00987       offset += indexOffset.first._const.Integer();
00988     else { // indexOffset is in a register
00989       // TODO:  this really should be handled as a register indirect with
00990       //        register offset (see note w/ LIR::Load)
00991       Register tempReg;
00992       declNode * tempDecl;
00993       _alloc.get_temp_ptr(tempReg, tempDecl);
00994       _proc->instructions().push_back(LIR::Add(LirUtil::newVoidPtr(),
00995                                                tempReg, tempDecl,
00996                                                base.first, base.second,
00997                                                indexOffset.first._reg,
00998                                                indexOffset.second));
00999       base = pair<Register, declNode *>(tempReg, tempDecl);
01000     }
01001   } else {
01002     if ( the_oper->star() )
01003       base = load_stack_var(the_id);
01004     else if ( loc._type == declNode::Storage_location::storageloc_register ) {
01005       // we already have a register-allocated variable, so just return the
01006       // register it lives int
01007       assert(the_oper->fields().empty());
01008       return pair<Register, declNode *>(loc._register, the_id->decl());
01009     } else {
01010       base = pair<Register, declNode *>(Register::getRegFp(),
01011                                         DATA_CONTENTS_FRAMEP);
01012       offset += loc._stack_offset;
01013     }
01014   }
01015   _proc->instructions().push_back(LIR::Load(the_oper->noncast_type(),
01016                                             loadReg, loadDecl,
01017                                             base.first, base.second,
01018                                             constant::constant(offset),
01019                                             NULL));
01020 
01021   if ( needs_conversion(the_oper->noncast_type(), the_oper->type()) )
01022     return gen_conversion(the_oper->type(), loadReg, loadDecl);
01023   else
01024     return pair<Register, declNode *>(loadReg, loadDecl);
01025 }
01026 
01027 pair<Register, declNode *> lir_gen_walker::load_stack_var(idNode * the_id) {
01028   const declNode::Storage_location & loc = the_id->decl()->storage_location();
01029 
01030   if ( loc._type == declNode::Storage_location::storageloc_register )
01031     // already in a register
01032     return pair<Register, declNode *>(loc._register, the_id->decl());
01033   else if ( loc._type == declNode::Storage_location::storageloc_stack ) {
01034     Register reg;
01035     declNode * regDecl;
01036     _alloc.get_temp_var(the_id->type(), reg, regDecl);
01037     _proc->instructions().push_back(LIR::Load(the_id->type(), reg, regDecl,
01038                                               Register::getRegFp(), 
01039                                               DATA_CONTENTS_FRAMEP,
01040                                               loc._stack_offset, NULL));
01041     return pair<Register, declNode *>(reg, regDecl);
01042   } else
01043     CBZFAIL(("Incorrect Storage_location for a local variable."));
01044 }
01045 
01046 pair<Register, declNode *> lir_gen_walker::load_stack_addr(idNode * the_id) {
01047   const declNode::Storage_location & loc = the_id->decl()->storage_location();
01048   assert(loc._type == declNode::Storage_location::storageloc_stack);
01049 
01050   Register reg;
01051   declNode * regDecl;
01052   _alloc.get_temp_ptr(reg, regDecl);
01053   LirInst * new_inst = LIR::GetEffectiveAddress(reg, regDecl,
01054                                                 Register::getRegFp(),
01055                                                 DATA_CONTENTS_FRAMEP,
01056                                                 loc._stack_offset, NULL);
01057   _proc->instructions().push_back(new_inst);
01058   return pair<Register, declNode *>(reg, regDecl);
01059 }
01060 
01061 // use when you are SURE that you want the constant loaded into a register
01062 pair<Register, declNode *> lir_gen_walker::load_const(constNode * the_const) {
01063   assert(the_const);
01064   Register destReg;
01065   declNode * destDecl;
01066   _alloc.get_temp_var(the_const->type(), destReg, destDecl);
01067 
01068   constant & const_val = the_const->value();
01069   assert(!const_val.no_val());
01070 
01071   if ( const_val.is_str() ) {
01072     // create a global declaration for this string literal & load the
01073     // effective address of the global into the variable
01074     declNode * temp_decl = LirUtil::new_static_global(the_const->type(),
01075                                                       the_const);
01076     gen_global_decl(temp_decl);
01077 //     _proc->instructions().push_back(LIR::LoadStatic(LirUtil::newVoidPtr(),
01078 //                                                  destReg, destDecl,
01079 //                                                  temp_decl->name(),
01080 //                                                  temp_decl,
01081 //                                                  constant::constant(0),
01082 //                                                  NULL));
01083     _proc->instructions().push_back(LIR::GetGlobalAddress(destReg, destDecl,
01084                                                           temp_decl->name(),
01085                                                           temp_decl,
01086                                                           constant(0),
01087                                                           NULL));
01088   } else if ( CBZ::ArchInfo.instruction_supports_immediate(mn_LoadImmediate,
01089                                                            the_const->type(),
01090                                                            const_val) ) {
01091     // we can handle this with loadimmediate
01092     _proc->instructions().push_back(LIR::LoadImmediate(the_const->type(), 
01093                                                        destReg,
01094                                                        destDecl,
01095                                                        const_val));
01096   } else {
01097     // we must declare a static value & load it
01098     declNode * temp_decl = LirUtil::new_static_global(the_const->type(),
01099                                                       the_const);
01100     gen_global_decl(temp_decl);
01101     _proc->instructions().push_back(LIR::LoadStatic(the_const->type(),
01102                                                     destReg, destDecl,
01103                                                     temp_decl->name(),
01104                                                     temp_decl,
01105                                                     constant::constant(0),
01106                                                     NULL));
01107   }
01108 
01109   return pair<Register, declNode *>(destReg, destDecl);
01110 }
01111 
01112 void lir_gen_walker::gen_store(operandNode * dest, Register reg,
01113                                declNode * regDecl) {
01114   if ( idNode * the_id = dynamic_cast<idNode *>(dest->var()) ) {
01115     if ( the_id->decl()->decl_location() == declNode::TOP )
01116       store_global(dest, reg, regDecl);
01117     else
01118       store_stack(dest, reg, regDecl);
01119   } else
01120     CBZFAIL(("Malformed operandNode for storing"));
01121 }
01122 
01123 // TODO: factor common code with store_stack
01124 void lir_gen_walker::store_global(operandNode * dest, Register reg,
01125                                   declNode * regDecl) {
01126   idNode * the_id = dynamic_cast<idNode *>(dest->var());
01127   assert(the_id);
01128   int fieldOffset = field_offset(dest);
01129 
01130   const declNode::Storage_location & loc = the_id->decl()->storage_location();
01131   assert(loc._type == declNode::Storage_location::storageloc_mem_global);
01132 
01133   if ( dest->index() ) {
01134     pair<reg_or_const, declNode *> indexOffset = index_offset(dest);
01135     pair<Register, declNode *> base;
01136 
01137     if ( the_id->type()->typ() == Ptr ) {
01138       base = load_global_var(the_id);
01139       if ( dest->star() ) {
01140         // handles:  (*global) [.field]* '[' index ']'
01141         Register tempReg;
01142         declNode * tempDecl;
01143         _alloc.get_temp_ptr(tempReg, tempDecl);
01144         _proc->instructions().push_back(LIR::Load(LirUtil::newVoidPtr(),
01145                                                   tempReg, tempDecl,
01146                                                   base.first, base.second,
01147                                                   constant::constant(0),
01148                                                   NULL));
01149         base = pair<Register, declNode *>(tempReg, tempDecl);
01150       }
01151     } else {
01152       if ( indexOffset.first._is_const ) {
01153         int offset = fieldOffset + indexOffset.first._const.Integer();
01154         LirInst * newInst = LIR::StoreStatic(dest->type(),
01155                                              reg, regDecl,
01156                                              the_id->name(),
01157                                              the_id->decl(),
01158                                              constant::constant(offset),
01159                                              NULL);
01160         _proc->instructions().push_back(newInst);
01161         return; 
01162       } else
01163         base = load_global_addr(the_id);
01164     }
01165     
01166     if ( indexOffset.first._is_const ) {
01167       int offset = fieldOffset + indexOffset.first._const.Integer();
01168       LirInst * newInst = LIR::Store(dest->type(), reg, regDecl,
01169                                      base.first, base.second,
01170                                      constant::constant(offset),
01171                                      NULL);
01172       _proc->instructions().push_back(newInst);
01173     } else {
01174       // TODO:  see note w/ LIR::StoreStatic
01175       Register tempReg;
01176       declNode * tempDecl;
01177       _alloc.get_temp_ptr(tempReg, tempDecl);
01178       _proc->instructions().push_back(LIR::Add(LirUtil::newVoidPtr(),
01179                                                tempReg, tempDecl,
01180                                                base.first, base.second,
01181                                                indexOffset.first._reg,
01182                                                indexOffset.second));
01183       LirInst * newInst = LIR::Store(dest->type(),
01184                                      reg, regDecl,
01185                                      tempReg, tempDecl,
01186                                      constant::constant(fieldOffset),
01187                                      NULL);
01188       _proc->instructions().push_back(newInst);
01189     }
01190   } else {
01191     if ( dest->star() ) {
01192       pair<Register, declNode *> base = load_global_var(the_id);
01193       LirInst * newInst = LIR::Store(dest->type(),
01194                                      reg, regDecl,
01195                                      base.first, base.second,
01196                                      constant::constant(fieldOffset),
01197                                      NULL);
01198       _proc->instructions().push_back(newInst);
01199     } else {
01200       LirInst * newInst = LIR::StoreStatic(dest->type(),
01201                                            reg, regDecl,
01202                                            the_id->name(),
01203                                            the_id->decl(),
01204                                            constant::constant(fieldOffset),
01205                                            NULL);
01206       _proc->instructions().push_back(newInst);
01207     }
01208   }
01209 }
01210 
01211 // TODO: factor common code with store_global
01212 void lir_gen_walker::store_stack(operandNode * dest, Register reg,
01213                                  declNode * regDecl) {
01214   idNode * the_id = dynamic_cast<idNode *>(dest->var());
01215   assert(the_id);
01216   int fieldOffset = field_offset(dest);
01217 
01218   const declNode::Storage_location & loc = the_id->decl()->storage_location();
01219 
01220   pair<Register, declNode *> base;
01221   int offset = fieldOffset;
01222 
01223   if ( dest->index() ) {
01224     pair<reg_or_const, declNode *> indexOffset = index_offset(dest);
01225     if ( the_id->type()->typ() == Ptr ) {
01226       base = load_stack_var(the_id);
01227       if ( dest->star() ) {
01228         // handles:  (*var) [.field]* '[' index ']'
01229         Register tempReg;
01230         declNode * tempDecl;
01231         _alloc.get_temp_ptr(tempReg, tempDecl);
01232         _proc->instructions().push_back(LIR::Load(LirUtil::newVoidPtr(),
01233                                                   tempReg, tempDecl,
01234                                                   base.first, base.second,
01235                                                   constant::constant(0),
01236                                                   NULL));
01237         base = pair<Register, declNode *>(tempReg, tempDecl);
01238       }
01239     } else {
01240       base = pair<Register, declNode *>(Register::getRegFp(),
01241                                         DATA_CONTENTS_FRAMEP);
01242       offset += loc._stack_offset;
01243     }
01244     
01245     if ( indexOffset.first._is_const )
01246       offset += indexOffset.first._const.Integer();
01247     else { // indexOffset is in a register
01248       // TODO:  this really should be handled as a register indirect with
01249       //        register offset (see note w/ LIR::Load)
01250       Register tempReg;
01251       declNode * tempDecl;
01252       _alloc.get_temp_ptr(tempReg, tempDecl);
01253       _proc->instructions().push_back(LIR::Add(LirUtil::newVoidPtr(),
01254                                                tempReg, tempDecl,
01255                                                base.first, base.second,
01256                                                indexOffset.first._reg,
01257                                                indexOffset.second));
01258       base = pair<Register, declNode *>(tempReg, tempDecl);
01259     }
01260   } else {
01261     if ( dest->star() )
01262       base = load_stack_var(the_id);
01263     else if ( loc._type == declNode::Storage_location::storageloc_register ) {
01264       // we already have a register-allocated variable, so just perform
01265       // a register-to-register move
01266       assert(dest->fields().empty());
01267       gen_move(loc._register, the_id->decl(), reg, regDecl);
01268       return;
01269     } else {
01270       base = pair<Register, declNode *>(Register::getRegFp(),
01271                                         DATA_CONTENTS_FRAMEP);
01272       offset += loc._stack_offset;
01273     }
01274   }
01275   _proc->instructions().push_back(LIR::Store(dest->type(), reg, regDecl,
01276                                              base.first, base.second,
01277                                              constant::constant(offset),
01278                                              NULL));
01279 }
01280 
01281 void lir_gen_walker::gen_move(Register dest, declNode * destDecl, Register src,
01282                               declNode * srcDecl) {
01283   _proc->instructions().push_back(LIR::Move(dest, destDecl, src, srcDecl));
01284 }
01285 
01286 bool lir_gen_walker::needs_conversion(typeNode * in_memory, typeNode * in_reg)
01287 {
01288   return ( *in_memory != *in_reg );
01289 }
01290 
01291 pair<Register, declNode *> lir_gen_walker::gen_conversion
01292 (
01293  typeNode * targetType,
01294  Register srcReg,
01295  declNode * srcDecl
01296  )
01297 {
01298   Register resultReg;
01299   declNode * resultDecl;
01300   _alloc.get_temp_var(targetType, resultReg, resultDecl);
01301   _proc->instructions().push_back(LIR::ConvertType(srcDecl->type(),
01302                                                    srcReg, srcDecl,
01303                                                    targetType,
01304                                                    resultReg, resultDecl));
01305   return pair<Register, declNode *>(resultReg, resultDecl);
01306 }
01307 
01308 AllocSizeChanger::AllocSizeChanger(void) :
01309   Changer(Both, Subtree, false)
01310 {}
01311 
01312 Node * AllocSizeChanger::at_prim(primNode * the_prim, Order ord) {
01313   if ( ord == Postorder ) {
01314     the_prim->alloc_size(CBZ::ArchInfo.get_data_size(the_prim));
01315     the_prim->alloc_align(CBZ::ArchInfo.get_data_align(the_prim));
01316   }
01317 
01318   return the_prim;
01319 }
01320 
01321 Node * AllocSizeChanger::at_decl(declNode * the_decl, Order ord) {
01322   if ( ord == Preorder ) {
01323     _decls.push(the_decl);
01324   } else { // ord == Postorder 
01325     assert(_decls.top() == the_decl);
01326     _decls.pop();
01327   }
01328   
01329   return the_decl;
01330 }
01331 
01332 Node * AllocSizeChanger::at_array(arrayNode * the_array, Order ord) {
01333   if ( ord == Postorder ) {
01334     if ( _decls.empty()
01335          || ( _decls.top()->decl_location() != declNode::FORMAL
01336                && _decls.top()->storage_class() != declNode::EXTERN ) ) {
01337       assert(the_array->dim());
01338       the_array->dim()->eval();
01339       assert(!the_array->dim()->value().no_val());
01340       the_array->alloc_size(the_array->type()->alloc_size() 
01341                             * the_array->dim()->value().Integer());
01342       the_array->alloc_align(the_array->type()->alloc_align());
01343     } else {
01344       // it's really a pointer, from our point of view
01345       // TODO:  should we make it a pointer?
01346       the_array->alloc_size(CBZ::ArchInfo.get_data_size_ptr());
01347       the_array->alloc_align(CBZ::ArchInfo.get_data_align_ptr());
01348     }
01349   }
01350 
01351   return the_array;
01352 }
01353 
01354 Node * AllocSizeChanger::at_ptr(ptrNode * the_ptr, Order ord) {
01355   if ( ord == Postorder ) {
01356     the_ptr->alloc_size(CBZ::ArchInfo.get_data_size(the_ptr));
01357     the_ptr->alloc_align(CBZ::ArchInfo.get_data_align(the_ptr));
01358   }
01359 
01360   return the_ptr;
01361 }
01362 
01363 Node * AllocSizeChanger::at_enum(enumNode * the_enum, Order ord) {
01364   if ( ord == Postorder ) {
01365     primNode unsignedInt(typeNode::NONE, basic_type::UInt);
01366     the_enum->alloc_size(CBZ::ArchInfo.get_data_size(&unsignedInt));
01367     the_enum->alloc_align(CBZ::ArchInfo.get_data_align(&unsignedInt));
01368   }
01369 
01370   return the_enum;
01371 }
01372 
01373 Node * AllocSizeChanger::at_union(unionNode * the_union, Order ord) {
01374   if ( ord == Postorder ) {
01375     int maxSize = -1;
01376     int maxAlign = -1;
01377     for ( decl_list_p p = the_union->spec()->fields().begin();
01378           p != the_union->spec()->fields().end();
01379           p++ ) {
01380       maxSize = max(maxSize, (*p)->type()->alloc_size());
01381       maxAlign = max(maxAlign, (*p)->type()->alloc_align());
01382     }
01383     the_union->alloc_size(maxSize);
01384     the_union->alloc_align(maxAlign);
01385   }
01386 
01387   return the_union;
01388 }
01389 
01390 Node * AllocSizeChanger::at_struct(structNode * the_struct, Order ord) {
01391   if ( ord == Postorder ) {
01392     int size = 0;
01393     int align = 0;
01394     for ( decl_list_p p = the_struct->spec()->fields().begin();
01395           p != the_struct->spec()->fields().end();
01396           p++ ) {
01397       size += (*p)->type()->alloc_size();
01398       align = max(align, (*p)->type()->alloc_align()); // TODO: ??? 
01399     }
01400     the_struct->alloc_size(size);
01401     the_struct->alloc_align(align);
01402   }
01403 
01404   return the_struct;
01405 }
01406 
01407 Node * AllocSizeChanger::at_tdef(tdefNode * the_tdef, Order ord) {
01408   if ( ord == Postorder ) {
01409     the_tdef->alloc_size(the_tdef->def()->alloc_size());
01410     the_tdef->alloc_align(the_tdef->def()->alloc_align());
01411   }
01412 
01413   return the_tdef;
01414 }
01415 
01416 Node * AllocSizeChanger::at_unary(unaryNode * the_unary, Order ord) {
01417   if ( ord == Postorder ) {
01418     if ( the_unary->op()
01419          && the_unary->op()->id() == Operator::SIZEOF ) {
01420       typeNode * sizeof_type = the_unary->sizeof_type();
01421       assert(sizeof_type);
01422       ostringstream ost;
01423       ost << sizeof_type->alloc_size();
01424       return new constNode(constant::constant(sizeof_type->alloc_size()),
01425                            ost.str().c_str(), the_unary->coord());
01426     }
01427   }
01428   
01429   return the_unary;
01430 }
01431 
01432 SizeofChanger::SizeofChanger(void) :
01433   Changer(Preorder, Subtree, false)
01434 {}
01435 
01436 Node * SizeofChanger::at_threeAddr(threeAddrNode * the_3addr, Order ord) {
01437   if ( typeNode * size_type = the_3addr->sizeof_type() ) {
01438     ostringstream ost;
01439     ost << size_type->alloc_size();
01440     constNode * sizeConst = 
01441       new constNode(constant::constant(size_type->alloc_size()), 
01442                     ost.str().c_str(),
01443                     the_3addr->coord());
01444     the_3addr->rhs1(new operandNode(sizeConst, the_3addr->coord()));
01445     the_3addr->sizeof_type(static_cast<typeNode *>(0));
01446   }
01447   return the_3addr;
01448 }
01449 
01450 AllocToMemWalker::AllocToMemWalker(void) :
01451   Walker(Preorder, Subtree)
01452 {}
01453 
01454 bool AllocToMemWalker::needsMem(declNode * the_decl) {
01455   return ( find(_decls.begin(), _decls.end(), the_decl) != _decls.end() );
01456 }
01457 
01458 void AllocToMemWalker::at_decl(declNode * the_decl, Order ord) {
01459   if ( the_decl->type()->is_aggregate() 
01460        || the_decl->type()->typ() == Union ) {
01461     _decls.push_back(the_decl);
01462     cout << "Must alloc to memory " << the_decl->name() << endl;
01463   }
01464 }
01465 
01466 void AllocToMemWalker::at_operand(operandNode * the_oper, Order ord) {
01467   if ( the_oper->addr() 
01468        && the_oper->fields().empty() 
01469        && !the_oper->index() ) {
01470     if ( idNode * the_id = dynamic_cast<idNode *>(the_oper->var()) ) {
01471       typeNode * type = the_oper->type();
01472       if ( ( type->is_float() 
01473              || type->is_integer()
01474              || type->is_pointer() )
01475            && the_id->decl()->decl_location() == declNode::BLOCK  )
01476         // we have a local variable whose address is taken, so it
01477         // must live in memory
01478         _decls.push_back(the_id->decl());
01479       cout << "Must alloc to memory " << the_id->name() << endl;
01480     }
01481   }
01482 }

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