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  

arch_info.cc

Go to the documentation of this file.
00001 // $Id: arch_info.cc,v 1.13 2003/08/11 17:38:51 abrown Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2002 University of Texas at Austin
00008 // 
00009 //  Charles Nevill
00010 //  Paul Arthur Navratil
00011 //  Calvin Lin
00012 //  Adam C. Brown
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 "c_breeze.h"
00040 #include "arch_info.h"
00041 #include "arch_info_parser.h"
00042 #include "lirutil.h"
00043 
00044 // because I'm lazy
00045 typedef arch_info::register_info                register_info;
00046 typedef arch_info::register_info_list   register_info_list;
00047 
00048 // these are needed so that we can parse Kill list in Lir2Asm record
00049 register_info arch_info::pseudo_reg_dest( (unsigned int)-2, "dest" );
00050 register_info arch_info::pseudo_reg_src1( (unsigned int)-4, "src1" );
00051 register_info arch_info::pseudo_reg_src2( (unsigned int)-5, "src2" );
00052 
00053 
00054 // for handling errors when we parse the desc
00055 #define PARSE_ERROR( format ) \
00056         CBZ::Fail( __FILE__, __LINE__, \
00057                cbz_util::string_format( "error parsing architecture spec"\
00058                                          " (near line %d): ", _currentLine ));
00059 
00060 arch_info::arch_info() {
00061   // internal initial values
00062   _nextRegId = 0;
00063 
00064   // init our state
00065   reset_info();
00066 }
00067 
00068 arch_info::~arch_info() 
00069 {}
00070 
00071 void 
00072 arch_info::reset_info() {
00073   // we are no longer valid
00074   _valid = false;
00075 
00076   // kill everything
00077   _asmLineComment.clear();
00078   _asmRegPrefixAdd.clear();
00079   _asmRegPrefixRemove.clear();
00080   _asmRegPrefixRemoveSplit.clear();
00081   _asmConstPrefix.clear();
00082   _regsAll.clear();
00083   _regMap.clear();
00084   _regsGpr.clear();
00085   _regsFpr.clear();
00086   _regSp = NULL;
00087   _regFp = NULL;
00088   _regsParamFixed.clear();
00089   _regsParamFloat.clear();
00090   _regRetvalFixed = NULL;
00091   _regRetvalFloat = NULL;
00092   _regDataTypeGpr = NULL;
00093   _regDataTypeFpr = NULL;
00094   _dataSizeLong = 8;
00095   _dataSizeInt = 4;
00096   _dataSizeShort= 2;
00097   _dataSizeDouble = 8;
00098   _dataSizeFloat = 4;
00099   _dataSizePtr = 4;
00100   _maxDataAlign = (unsigned int)-1;
00101   _dataAlignChar = 1;
00102   _dataAlignShort = 2;
00103   _dataAlignInt = 4;
00104   _dataAlignLong = 8;
00105   _dataAlignFloat = 4;
00106   _dataAlignDouble = 8;
00107   _dataAlignPtr = 4;
00108   _stackFrameMinSize = 0;
00109   _stackExtraTop = 0;
00110   _stackExtraBottom = 0;
00111   _stackAlign = 0;
00112   _stackFormalsOffset = 0;
00113   _emulate3Address = false;
00114   _Lir2Asm_records.clear();
00115   _Lir2Asm_mnemonicLookup.clear();
00116 }
00117 
00118 const char * 
00119 arch_info::get_asm_line_comment() const {
00120   return _asmLineComment.c_str();
00121 }
00122 
00123 const char * 
00124 arch_info::get_asm_const_prefix() const {
00125   return _asmConstPrefix.c_str();
00126 }
00127 
00128 const register_info_list & 
00129 arch_info::get_all_regs() const {
00130   return _regsAll;
00131 }
00132 
00133 const register_info_list & 
00134 arch_info::get_regs_gpr() const {
00135   return _regsGpr;
00136 }
00137 
00138 const register_info_list & 
00139 arch_info::get_regs_fpr() const {
00140   return _regsFpr;
00141 }
00142 
00143 const register_info* 
00144 arch_info::get_reg_sp() const {
00145   return _regSp;
00146 }
00147 
00148 const register_info* 
00149 arch_info::get_reg_fp() const {
00150   return _regFp;
00151 }
00152 
00153 const register_info_list & 
00154 arch_info::get_regs_param_fixed() const {
00155   return _regsParamFixed;
00156 }
00157 
00158 const register_info_list & 
00159 arch_info::get_regs_param_float() const {
00160   return _regsParamFloat;
00161 }
00162 
00163 const register_info* 
00164 arch_info::get_reg_retval_fixed() const {
00165   return _regRetvalFixed;
00166 }
00167 
00168 const register_info* 
00169 arch_info::get_reg_retval_float() const {
00170   return _regRetvalFloat;
00171 }
00172 
00173 const register_info_list & 
00174 arch_info::get_regs_caller_save() const {
00175   return _regsCallerSave;
00176 }
00177 
00178 const register_info_list & 
00179 arch_info::get_regs_callee_save() const {
00180   return _regsCalleeSave;
00181 }
00182 
00183 typeNode * 
00184 arch_info::get_reg_data_type_gpr() const {
00185   return _regDataTypeGpr;
00186 }
00187 
00188 typeNode * 
00189 arch_info::get_reg_data_type_fpr() const {
00190   return _regDataTypeFpr;
00191 }
00192 
00193 bool 
00194 arch_info::get_reg_name( const Register & reg, string & name, 
00195                          bool wantPrefixAdd, bool wantPrefixRemove ) {
00196   // check bounds first
00197   int num = reg.num();
00198   if ( num < 0 || num >= (int)_regsAll.size() )
00199     return false;
00200 
00201   // return its name, after prefix munging
00202   name = _regsAll[num]->_name;
00203   if ( wantPrefixAdd )
00204     name = _asmRegPrefixAdd + name;
00205   if ( wantPrefixRemove )
00206     for ( size_t i = 0; i < _asmRegPrefixRemoveSplit.size(); ++i )
00207       if ( name.find( _asmRegPrefixRemoveSplit[i] ) == 0 )
00208         name.erase( 0, _asmRegPrefixRemoveSplit[i].size() );
00209   return true;
00210 }
00211 
00212 bool 
00213 arch_info::get_reg_by_index( int realRegIndex, Register & reg )
00214 {
00215   // check bounds first
00216   if ( realRegIndex < 0 || realRegIndex >= (int)_regsAll.size() )
00217     return false;
00218 
00219   // just grab it by pointer
00220   reg = get_register( _regsAll[realRegIndex] );
00221   return true;
00222 }
00223 
00224 // TODO:  fix this to use a lookup table
00225 unsigned int 
00226 arch_info::get_data_size( typeNode * the_type ) const
00227 {
00228   if ( the_type->is_pointer() )
00229     return get_data_size_ptr();
00230   if ( primNode * primType = dynamic_cast<primNode *>(the_type) ) {
00231     if ( primType->is_float() )
00232       if ( primType->basic().is_long() )
00233         return get_data_size_double();
00234       else
00235         return get_data_size_float();
00236     else if ( primType->is_char() )
00237       return 1;
00238     else if ( primType->is_integer() )
00239       if ( primType->basic().is_short() )
00240         return get_data_size_short();
00241       else if ( primType->basic().is_long() )
00242         return get_data_size_long();
00243       else
00244         return get_data_size_int();
00245   }
00246   return 0;
00247 }
00248 
00249 unsigned int
00250 arch_info::get_max_data_align() const
00251 {
00252   // did we already compute it?
00253   if ( _maxDataAlign != -1 )
00254     return _maxDataAlign;
00255 
00256   // compute it
00257   _maxDataAlign = _dataAlignChar;
00258   if ( _maxDataAlign < _dataAlignShort )
00259     _maxDataAlign = _dataAlignShort;
00260   if ( _maxDataAlign < _dataAlignInt )
00261     _maxDataAlign = _dataAlignInt;
00262   if ( _maxDataAlign < _dataAlignLong )
00263     _maxDataAlign = _dataAlignLong;
00264   if ( _maxDataAlign < _dataAlignFloat )
00265     _maxDataAlign = _dataAlignFloat;
00266   if ( _maxDataAlign < _dataAlignDouble )
00267     _maxDataAlign = _dataAlignDouble;
00268   if ( _maxDataAlign < _dataAlignPtr )
00269     _maxDataAlign = _dataAlignPtr;
00270 
00271   return _maxDataAlign;
00272 }
00273 
00274 // TODO: fix this to use a lookup table
00275 unsigned int 
00276 arch_info::get_data_align( typeNode * the_type ) const
00277 {
00278   if ( the_type->is_pointer() )
00279     return get_data_align_ptr();
00280   if ( the_type->is_aggregate() )
00281     return get_max_data_align();
00282   if ( primNode * primType = dynamic_cast<primNode *>(the_type) ) {
00283     if ( primType->is_float() )
00284       if ( primType->basic().is_long() )
00285         return get_data_align_double();
00286       else
00287         return get_data_align_float();
00288     else if ( primType->is_char() )
00289       return get_data_align_char();
00290     else if ( primType->is_integer() )
00291       if ( primType->basic().is_short() )
00292         return get_data_align_short();
00293       else if ( primType->basic().is_long() )
00294         return get_data_align_long();
00295       else 
00296         return get_data_align_int();
00297   }
00298   return 0;
00299 }
00300 
00301 bool 
00302 arch_info::get_code_for_instruction( const LirInst * pInst, 
00303                                      vector<string> & lines ) 
00304 {
00305   // find the Lir2Asm for this instruction
00306   Lir2Asm * pLir2Asm = NULL;
00307   if ( ! get_Lir2Asm_for_instruction( pInst, &pLir2Asm ) || ! pLir2Asm )
00308     return false;
00309 
00310   // copy the lines
00311   cbz_util::vector_copy( pLir2Asm->_codeTemplate, lines );
00312 
00313   // make replacements
00314   make_template_replacements( pInst, pLir2Asm, lines );
00315 
00316   // do formatting - labels are left-justified, all others indented from
00317   // left edge
00318   if ( pInst->instruction != mn_Label ) {
00319     int i, sz = (int)lines.size();
00320     for ( i = 0; i < sz; ++i ) {
00321       // add some space if it is not a label (assume anything with colon
00322       // char is label)
00323       if ( lines[i].find( ':' ) == -1 )
00324         lines[i].insert( 0, 4, ' ' );
00325     }
00326   }
00327 
00328   return true;
00329 }
00330 
00331 bool 
00332 arch_info::get_instruction_kill_regs( const LirInst * pInst, 
00333                                       register_info_list & killRegs ) 
00334 {
00335   // find the Lir2Asm for this instruction
00336   Lir2Asm * pLir2Asm = NULL;
00337   if ( ! get_Lir2Asm_for_instruction( pInst, &pLir2Asm ) || ! pLir2Asm )
00338     return false;
00339 
00340   // copy the register info
00341   cbz_util::vector_copy( pLir2Asm->_killRegs, killRegs );
00342 
00343   return true;
00344 }
00345 
00346 bool 
00347 arch_info::types_need_conversion( typeNode * srcType, typeNode * destType ) 
00348 {
00349   // get a lir2asm for it - if we have none, pretend we need conversion
00350   // so we'll fail later
00351   Lir2Asm * l2a = NULL;
00352   if ( ! get_Lir2Asm_for_instruction( mn_ConvertType, srcType, destType, 
00353                                       false, &l2a ) 
00354        || ! l2a )
00355     return true;
00356 
00357   // are there any instructions for it?  if so, we need conversion.
00358   return (l2a->_codeTemplate.size() != 0);
00359 }
00360 
00361 bool 
00362 arch_info::instruction_supports_immediate( mnemonic instruction, 
00363                                            typeNode * the_type, 
00364                                            const constant & c ) 
00365 {
00366   // no strings as immediates
00367   if ( c.is_str() )
00368     return false;
00369 
00370   // get a lir2asm for it - if we have one, it's supported
00371   Lir2Asm * l2a = NULL;
00372   return ( get_Lir2Asm_for_instruction( instruction, the_type, NULL, 
00373                                         true, &l2a ) 
00374            && l2a != NULL );
00375 }
00376 
00377 bool
00378 arch_info::find_register_info( const char * name, 
00379                                register_info *& regInfoFound ) const
00380 {
00381   // find this one in our set of registers
00382   register_info_map::const_iterator it = _regMap.find( name );
00383   if ( it == _regMap.end() )
00384     return false;
00385 
00386   // give them what we found
00387   regInfoFound = (*it).second;
00388   return true;
00389 }
00390 
00391 Register 
00392 arch_info::get_register( const register_info * pInfo ) 
00393 {
00394   // the value we'll return
00395   Register ret;
00396   if ( ! pInfo )
00397     return ret;
00398 
00399   // copy id and type
00400   ret.num( pInfo->_id );
00401   ret.type( pInfo->_type );
00402   return ret;
00403 }
00404 
00405 bool
00406 arch_info::get_Lir2Asm_for_instruction( const LirInst * pInst, 
00407                                         Lir2Asm ** ppLir2Asm ) 
00408 {
00409   // use other version
00410   return get_Lir2Asm_for_instruction( pInst->instruction, pInst->primaryType, 
00411                                       pInst->convertType, 
00412                                       pInst->opnd2._is_const, ppLir2Asm );
00413 }
00414 
00415 bool 
00416 arch_info::get_Lir2Asm_for_instruction( mnemonic inst, typeNode * srcType, 
00417                                         typeNode * destType, bool isImmed, 
00418                                         Lir2Asm ** ppLir2Asm ) 
00419 {
00420   // find list of possibles for this guy
00421   map_menmonic_to_record_set::const_iterator it = 
00422     _Lir2Asm_mnemonicLookup.find( inst );
00423   if ( it == _Lir2Asm_mnemonicLookup.end() )
00424     return false;
00425 
00426   // find actual match
00427   const vector<int> & possibles = it->second;
00428   int sz = (int)possibles.size();
00429   for ( int i = 0; i < sz; ++i ) {
00430     // sanity check - the values in possibles should be array indices
00431     assert( possibles[i] >= 0 && possibles[i] < (int)_Lir2Asm_records.size() );
00432 
00433     Lir2Asm & l2a = _Lir2Asm_records[ possibles[i] ];
00434 
00435     // this thing had better handle this instruction
00436     assert(find(l2a._lirInstTypes.begin(),
00437                 l2a._lirInstTypes.end(),
00438                 inst) != l2a._lirInstTypes.end());
00439 
00440     // does this template specify an immediate?
00441     if ( l2a._immed != Lir2Asm::Immed_NA ) {
00442       // make sure immediate-ness is matched
00443       if ( l2a._immed == Lir2Asm::Immed_No && isImmed )
00444         continue;
00445       else if ( l2a._immed == Lir2Asm::Immed_Yes && ! isImmed )
00446         continue;
00447     }
00448 
00449     // data types match? (if this thing listed no data types, it matches
00450     // any type)
00451     if ( srcType && l2a._dataTypes.size() > 0 
00452          && !findType(l2a._dataTypes, srcType) )
00453       continue;
00454 
00455     // conversion types match? (conversion types must be explicitly listed)
00456     if ( destType
00457          && !findType(l2a._convertToTypes, destType) )
00458       continue;
00459 
00460     // this one matches
00461     *ppLir2Asm = &l2a;
00462     return true;
00463   }
00464 
00465   return false;
00466 }
00467 
00468 bool arch_info::findType(vector<typeNode *> & types, typeNode * toFind) {
00469   assert(toFind);
00470   if ( toFind->is_pointer() ) {
00471     // all pointers are equivalent at this point & .cba file only deals with
00472     // (void *)
00473     toFind = LirUtil::newVoidPtr();
00474   }
00475 
00476   for ( int i = 0; i < types.size(); i++ ) {
00477     if ( *toFind == *(types[i]) )
00478       return true;
00479   }
00480   return false;
00481 }
00482 
00483 void 
00484 arch_info::make_template_replacements( const LirInst * pInst, 
00485                                        Lir2Asm * pLir2Asm, 
00486                                        code_template & outputTemplate ) 
00487 {
00488   // generate strings for each various token
00489   string dest, op1, op2, base, offset, target, stacksize;  /*, str ; */
00490   string val, size, align;
00491   if ( pInst->has_dest() )
00492     dest = pInst->dest.to_string();
00493   if ( pInst->has_opnd1() )
00494     op1 = pInst->opnd1.to_string();
00495   if ( pInst->has_opnd2( false ) )
00496     op2 = pInst->opnd2.to_string( false, true );
00497   if ( pInst->has_base() )
00498     base = pInst->memBase.to_string();
00499   if ( pInst->has_offset( false ) )
00500     offset = pInst->memOffset.to_string( false, false );
00501   if ( pInst->nodeExtra && pInst->nodeExtra->typ() == Proc ) {
00502     procNode * the_proc = dynamic_cast<procNode *>(pInst->nodeExtra);
00503     assert(the_proc);
00504     stacksize = cbz_util::string_format( "%d", the_proc->stack_frame_size() );
00505   }
00506 
00507   // always read a target and static data
00508   target = pInst->target;
00509 //   str = pInst->dataString;
00510   val = pInst->dataValue.to_string();
00511   size = cbz_util::string_format("%d", pInst->dataSize);
00512   align = cbz_util::string_format("%d", pInst->dataAlign);
00513 
00514   // make replacements in template
00515   int i, sz = (int)outputTemplate.size();
00516   for ( i = 0; i < sz; ++i ) {
00517     // fix various parts of template
00518     cbz_util::string_replace( outputTemplate[i], "$dest", dest );
00519     cbz_util::string_replace( outputTemplate[i], "$opnd1", op1 );
00520     cbz_util::string_replace( outputTemplate[i], "$opnd2", op2 );
00521     cbz_util::string_replace( outputTemplate[i], "$base", base );
00522     cbz_util::string_replace( outputTemplate[i], "$offset", offset );
00523     cbz_util::string_replace( outputTemplate[i], "$target", target );
00524     cbz_util::string_replace( outputTemplate[i], "$stacksize", stacksize );
00525 //     cbz_util::string_replace( outputTemplate[i], "$string", str );
00526     cbz_util::string_replace( outputTemplate[i], "$value", val );
00527     cbz_util::string_replace( outputTemplate[i], "$size", size );
00528     cbz_util::string_replace( outputTemplate[i], "$align", align );
00529 
00530     // fixup any register names that were formatted @name
00531     int reg, szregs = (int)_regsAll.size();
00532     for ( reg = 0; reg < szregs; ++reg ) {
00533       string handyName = '@' + _regsAll[reg]->_name;
00534       string realName;
00535       get_reg_name( *_regsAll[reg], realName, true, true );
00536       cbz_util::string_replace( outputTemplate[i], handyName, realName );
00537     }
00538   }
00539 }
00540 
00541 bool 
00542 arch_info::load_arch_info( const char * pFileName ) 
00543 {
00544   int i, sz;
00545 
00546   // reset ourself first
00547   reset_info();
00548 
00549   // let our parser do the work
00550   arch_info_parser parser;
00551   if ( ! parser.parse( pFileName, this ) )
00552     return false;
00553 
00555   // setup register stuff
00556 
00557   // setup type info for registers
00558   _regSp->_type = reg_stack_ptr;
00559   _regFp->_type = reg_frame_ptr;
00560   sz = (int)_regsGpr.size();
00561   for ( i = 0; i < sz; ++i )
00562     _regsGpr[i]->_type = reg_gpr;
00563   sz = (int)_regsFpr.size();
00564   for ( i = 0; i < sz; ++i )
00565     _regsFpr[i]->_type = reg_fpr;
00566 
00568   // sanity checks
00569 
00570 #define ARCHWARN( expr ) \
00571         cout << cbz_util::string_format expr << endl;
00572 
00573   if ( _regsAll.size() < 1 )
00574     ARCHWARN(( "WARNING: architecture does not appear to have any "
00575                "registers!!" ));
00576   if ( _regsGpr.size() < 1 )
00577     ARCHWARN(( "WARNING: architecture does not appear to have any integer "
00578                "registers!!" ));
00579   if ( ! _regSp || ! _regSp->is_valid() )
00580     ARCHWARN(( "WARNING: architecture does not appear to have a stack "
00581                "pointer register!!" ));
00582   if ( ! _regFp || ! _regFp->is_valid() )
00583     ARCHWARN(( "WARNING: architecture does not appear to have a frame "
00584                "pointer register!!" ));
00585   if ( ! _regDataTypeGpr )
00586     ARCHWARN(( "WARNING: invalid data type specified for general-purpose "
00587                "registers!!" ));
00588   if ( ! _regDataTypeFpr )
00589     ARCHWARN(( "WARNING: invalid data type specified for floating-point "
00590                "registers!!" ));
00591   if ( _dataSizeShort <= 0 )
00592     ARCHWARN(( "WARNING: size of short integer (%d) appears to be "
00593                "ridiculous!!",  _dataSizeShort ));
00594   if ( _dataSizeInt <= 0 )
00595     ARCHWARN(( "WARNING: size of integer (%d) appears to be ridiculous!!",
00596                _dataSizeInt ));
00597   if ( _dataSizeLong <= 0 )
00598     ARCHWARN(( "WARNING: size of long integer (%d) appears to be ridiculous!!",
00599                _dataSizeLong ));
00600   if ( _dataSizeFloat <= 0 )
00601     ARCHWARN(( "WARNING: size of float (%d) appears to be ridiculous!!",
00602                _dataSizeFloat ));
00603   if ( _dataSizeDouble <= 0 )
00604     ARCHWARN(( "WARNING: size of double float (%d) appears to be ridiculous!!",
00605                _dataSizeDouble ));
00606   if ( _dataSizePtr <= 0 )
00607     ARCHWARN(( "WARNING: size of pointer (%d) appears to be ridiculous!!",
00608                _dataSizePtr ));
00609 
00610   // currently we don't handle the case that our data sizes and the
00611   // target data sizes don't match
00612   if ( sizeof(short) != _dataSizeShort )
00613     ARCHWARN(( "WARNING: compiler data size does not match target data "
00614                "size for type 'short'.  "
00615                "This is currently not handled properly by the backend." ));
00616   if ( sizeof(int) != _dataSizeInt )
00617     ARCHWARN(( "WARNING: compiler data size does not match target data "
00618                "size for type 'int'.  "
00619                "This is currently not handled properly by the backend." ));
00620   if ( sizeof(long) != _dataSizeLong )
00621     ARCHWARN(( "WARNING: compiler data size does not match target data "
00622                "size for type 'long'.  "
00623                "This is currently not handled properly by the backend." ));
00624   if ( sizeof(float) != _dataSizeFloat )
00625     ARCHWARN(( "WARNING: compiler data size does not match target data "
00626                "size for type 'float'.  "
00627                "This is currently not handled properly by the backend." ));
00628   if ( sizeof(double) != _dataSizeDouble )
00629     ARCHWARN(( "WARNING: compiler data size does not match target data "
00630                "size for type 'double'.  "
00631                "This is currently not handled properly by the backend." ));
00632   if ( sizeof(void*) != _dataSizePtr )
00633     ARCHWARN(( "WARNING: compiler data size does not match target data "
00634                "size for type 'pointer'.  "
00635                "This is currently not handled properly by the backend." ));
00636 
00637   if ( _dataAlignChar <= 0 )
00638     ARCHWARN(( "WARNING: alignment of character (%d) appears to be "
00639                "ridiculous!!", _dataAlignChar ));
00640   if ( _dataAlignShort <= 0 )
00641     ARCHWARN(( "WARNING: alignment of short integer (%d) appears to be "
00642                "ridiculous!!", _dataAlignShort ));
00643   if ( _dataAlignInt <= 0 )
00644     ARCHWARN(( "WARNING: alignment of integer (%d) appears to be "
00645                "ridiculous!!", _dataAlignInt ));
00646   if ( _dataAlignLong <= 0 )
00647     ARCHWARN(( "WARNING: alignment of long integer (%d) appears to be "
00648                "ridiculous!!", _dataAlignLong ));
00649   if ( _dataAlignFloat <= 0 )
00650     ARCHWARN(( "WARNING: alignment of float (%d) appears to be ridiculous!!",
00651                _dataAlignFloat ));
00652   if ( _dataAlignDouble <= 0 )
00653     ARCHWARN(( "WARNING: alignment of double float (%d) appears to be "
00654                "ridiculous!!", _dataAlignDouble ));
00655   if ( _dataAlignPtr <= 0 )
00656     ARCHWARN(( "WARNING: alignment of pointer (%d) appears to be ridiculous!!",
00657                _dataAlignPtr ));
00658 
00659   if ( _stackFrameMinSize < 0 )
00660     ARCHWARN(( "WARNING: stack frame minimum size (%d) appears to be "
00661                "ridiculous!!", _stackFrameMinSize ));
00662   if ( _stackAlign < 0 )
00663     ARCHWARN(( "WARNING: stack alignment value (%d) appears to be "
00664                "ridiculous!!", _stackAlign ));
00665 
00666   if ( _stackFrameMinSize != 0 
00667        && _stackAlign != 0 
00668        && (_stackFrameMinSize % _stackAlign) != 0 )
00669     ARCHWARN(( "WARNING: stack frame minimum size is not a multiple of "
00670                "stack alignment!!" ));
00671 
00672   // make sure caller-save and callee-save are disjoint and that all regs
00673   // are in one list or another
00674   register_info_list::iterator it = _regsAll.begin();
00675   for ( ; it != _regsAll.end(); ++it ) {
00676     register_info * info = *it;
00677     if ( ! info )
00678       continue;
00679 
00680     // assume neither
00681     bool caller = false, callee = false;
00682 
00683     // see if it's a callee-save
00684     register_info_list::iterator calleeIt = _regsCalleeSave.begin();
00685     for ( ; calleeIt != _regsCalleeSave.end(); ++calleeIt )
00686       if ( info == *calleeIt ) {
00687         callee = true;
00688         break;
00689       }
00690 
00691     // see if it's a caller-save
00692     register_info_list::iterator callerIt = _regsCallerSave.begin();
00693     for ( ; callerIt != _regsCallerSave.end(); ++callerIt )
00694       if ( info == *callerIt ) {
00695         caller = true;
00696         break;
00697       }
00698 
00699     // it should be saved by someone (except fp, sp, retFixed, and retFloat)
00700     if ( ! caller 
00701          && ! callee 
00702          && info != _regFp 
00703          && info != _regSp 
00704          && info != _regRetvalFixed 
00705          && info != _regRetvalFloat )
00706       ARCHWARN(( "WARNING: register %s is not caller-save or callee-save "
00707                  "- is this the intent?", info->_name.c_str() ));
00708 
00709     // but not by both...
00710     if ( caller && callee )
00711       ARCHWARN(( "WARNING: register %s is both caller-save and callee-save "
00712                  "- is this the intent?", info->_name.c_str() ));
00713 
00714     // fp and sp must be handled by arch template code - we do not save
00715     // them for you
00716     if ( (caller || callee) && (info == _regFp || info == _regSp) )
00717       ARCHWARN(( "WARNING: register %s should be handled by architecture "
00718                  "template because it is the frame/stack pointer.", 
00719                  info->_name.c_str() ));
00720 
00721     // retFixed and retFloat should probably be caller-save but for now
00722     // they are neither
00723     if ( (caller || callee) 
00724          && (info == _regRetvalFixed || info == _regRetvalFloat) )
00725       ARCHWARN(( "WARNING: return-value register %s is volatile and will "
00726                  "not be saved even though marked as caller/callee save.",
00727                  info->_name.c_str() ));
00728   }
00729 
00730 #undef ARCHWARN
00731 
00733   // other stuff
00734         
00735   // split up prefix remove stuff - treat as comma-separated list
00736   if ( ! _asmRegPrefixRemove.empty() ) {
00737     int len = _asmRegPrefixRemove.size() + 2;
00738     char * split = new char[ len ];
00739     strcpy( split, _asmRegPrefixRemove.c_str() );
00740     split[ len-1 ] = 0;
00741     char *p1 = split, *p2 = strchr(p1, ',');
00742     while ( (p2 = strchr(p1, ',')) ) {
00743       // kill the comma and add what was before it to array
00744       *p2 = 0;
00745       _asmRegPrefixRemoveSplit.push_back( p1 );
00746       p1 = p2 + 1;
00747     }
00748     _asmRegPrefixRemoveSplit.push_back( p1 );
00749     delete [] split;
00750   }
00751 
00753   // show all of this to the user
00754 
00755   // title
00756   cout << endl;
00757   cout << "will compile for architecture: " << _archName.c_str() << endl;
00758   cout << endl;
00759 
00760   // we are valid now
00761   _valid = true;
00762   return true;
00763 }

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