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.h

Go to the documentation of this file.
00001 // $Id: arch_info.h,v 1.12 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 // 
00013 //  Permission is hereby granted, free of charge, to any person
00014 //  obtaining a copy of this software and associated documentation
00015 //  files (the "Software"), to deal in the Software without
00016 //  restriction, including without limitation the rights to use, copy,
00017 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00018 //  of the Software, and to permit persons to whom the Software is
00019 //  furnished to do so, subject to the following conditions:
00020 //  
00021 //  The above copyright notice and this permission notice shall be
00022 //  included in all copies or substantial portions of the Software.
00023 //  
00024 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00028 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00029 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00030 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00031 //  THE SOFTWARE.
00032 //
00033 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00034 //  Computer Science for inspiring parts of the C-Breeze design.
00035 //
00036 // ----------------------------------------------------------------------
00037 
00038 #ifndef _ARCH_INFO_H
00039 #define _ARCH_INFO_H
00040 
00041 #include "instruction.h"
00042 
00043 class arch_info {
00044   // our parser is our friend
00045   friend class arch_info_parser;
00046 
00047  public:
00048   // object management
00049 
00050   // ctor/dtor
00051   arch_info();
00052   ~arch_info();
00053 
00054  public:
00055   // persistence methods
00056 
00057   // load our architecture information from the specified file
00058   bool load_arch_info( const char * pFile );
00059 
00060   // reset this object
00061   void reset_info();
00062 
00063   // find out if we are valid right now
00064   bool is_valid() { return _valid; }
00065 
00066  public:
00067   // public types
00068 
00069 #define NO_REG ((unsigned int)-1)
00070 
00071   // information about a real register on the machine
00072   struct register_info {
00073     // constructor
00074     register_info() {
00075       reset();
00076     }
00077 
00078     // more useful constructor
00079     register_info( unsigned int id, string name ) :
00080       _id( id ), _name( name ), _type( reg_unknown )
00081     {}
00082 
00083     // reset this register to known state
00084     void reset() {
00085       // set invalid values
00086       _id = NO_REG;
00087       _name.clear();
00088       _type = reg_unknown;
00089     }
00090 
00091     // find out if we are valid
00092     int is_valid() const {
00093       // we are valid if we have a number
00094       return ( _id != NO_REG );
00095     }
00096 
00097     // compare 2 of these
00098     bool operator ==( const register_info & r ) {
00099       // numbers are all that matter
00100       return (_id == r._id);
00101     }
00102 
00103     // the type of this register
00104     Reg_type _type;
00105 
00106     // a logical numeric identifier for this register.
00107     // this is unique among all real registers on the machine
00108     unsigned int _id;
00109 
00110     // the actual name of this register
00111     string _name;
00112 
00113     // get an equivalent Register object
00114     operator Register() const {
00115       // make a new one
00116       return Register( _id, _type );
00117     }
00118   }; // end struct register_info
00119 
00120   // some special psuedo-registers
00121   static register_info pseudo_reg_dest;
00122   static register_info pseudo_reg_src1;
00123   static register_info pseudo_reg_src2;
00124 
00125   // an array of real registers
00126   typedef vector<register_info*> register_info_list;
00127   typedef register_info_list::iterator register_info_list_p;
00128 
00129   // a map from register name to register info
00130   typedef map<string, register_info*> register_info_map;
00131 
00132  public:
00133   // information access methods
00134 
00135   // general asm output stuff
00136   const char * get_asm_line_comment() const;
00137   const char * get_asm_const_prefix() const;
00138 
00139   // get register information
00140   const register_info_list &    get_all_regs() const;
00141   const register_info_list &    get_regs_gpr() const;
00142   const register_info_list &    get_regs_fpr() const;
00143   const register_info*          get_reg_sp() const;
00144   const register_info*          get_reg_fp() const;
00145   const register_info_list &    get_regs_param_fixed() const;
00146   const register_info_list &    get_regs_param_float() const;
00147   const register_info*          get_reg_retval_fixed() const;
00148   const register_info*          get_reg_retval_float() const;
00149   const register_info_list &    get_regs_caller_save() const;
00150   const register_info_list &    get_regs_callee_save() const;
00151   typeNode *                    get_reg_data_type_gpr() const;
00152   typeNode *                    get_reg_data_type_fpr() const;
00153 
00154   // get a Register from a register_info
00155   Register                      get_register( const register_info * pInfo );
00156 
00157   // get the name of the given register, if it represents a real register
00158   // wantPrefixAdd : add extra prefixes specified in arch spec
00159   // wantPrefixRemove : remove extra prefixes specified in arch spec
00160   bool get_reg_name( const Register & reg, string & name, 
00161                      bool wantPrefixAdd = true, 
00162                      bool wantPrefixRemove = false );
00163 
00164   // get the register for a given real register index
00165   bool get_reg_by_index( int realRegIndex, Register & reg );
00166 
00167   // read various data sizes
00168   unsigned int  get_data_size_short() const             
00169     { return _dataSizeShort; }
00170   unsigned int  get_data_size_int() const               
00171     { return _dataSizeInt; }
00172   unsigned int  get_data_size_long() const              
00173     { return _dataSizeLong; }
00174   unsigned int  get_data_size_float() const             
00175     { return _dataSizeFloat; }
00176   unsigned int  get_data_size_double() const    
00177     { return _dataSizeDouble; }
00178   unsigned int  get_data_size_ptr() const               
00179     { return _dataSizePtr; }
00180   unsigned int  get_data_size( typeNode * ) const;
00181 
00182   // read various data alignments
00183   unsigned int  get_max_data_align() const;
00184   unsigned int  get_data_align_char() const             
00185     { return _dataAlignChar; }
00186   unsigned int  get_data_align_short() const    
00187     { return _dataAlignShort; }
00188   unsigned int  get_data_align_int() const              
00189     { return _dataAlignInt; }
00190   unsigned int  get_data_align_long() const             
00191     { return _dataAlignLong; }
00192   unsigned int  get_data_align_float() const    
00193     { return _dataAlignFloat; }
00194   unsigned int  get_data_align_double() const   
00195     { return _dataAlignDouble; }
00196   unsigned int  get_data_align_ptr() const              
00197     { return _dataAlignPtr; }
00198   unsigned int  get_data_align( typeNode * ) const;
00199 
00200   // get stack maintenance parameters
00201   unsigned int  get_stack_frame_min_size() const        
00202     { return _stackFrameMinSize; }
00203   int           get_stack_extra_top() const                     
00204     { return _stackExtraTop; }
00205   int           get_stack_extra_bottom() const          
00206     { return _stackExtraBottom; }
00207   unsigned int  get_stack_align() const                         
00208     { return _stackAlign; }
00209   int           get_stack_formals_offset() const        
00210     { return _stackFormalsOffset; }
00211 
00212   // instruction-mode emulation
00213   bool emulate_3_address() const        
00214     { return _emulate3Address; }
00215 
00216   // get the actual code for a given instruction, returned as an array of
00217   // text lines
00218   bool get_code_for_instruction( const LirInst * pInst, 
00219                                  vector<string> & lines );
00220 
00221   // get the dependency information for an instruction
00222   bool get_instruction_kill_regs( const LirInst * pInst, 
00223                                   register_info_list & killRegs );
00224 
00225   // find out if type conversion is necessary between two lir types
00226   bool types_need_conversion( typeNode * srcType, typeNode * destType );
00227 
00228   // find out if the architecture can handle an immediate for opnd2 of
00229   // the given instruction
00230   bool instruction_supports_immediate( mnemonic instruction, 
00231                                        typeNode * the_type, 
00232                                        const constant & c );
00233 
00234  private:
00235   // internal types
00236 
00237   // the lines of text in a code template
00238   typedef vector<string> code_template;
00239 
00240   /*
00241     The following is a list of tokens that may be used in instruction 
00242     template code:
00243     
00244     $dest               - destination operand
00245     $opnd1              - source operand 1
00246     $opnd2              - source operand 2
00247     $base               - base register for loads/stores
00248     $offset             - offset register or constant for loads/stores
00249     $target             - branch/call target, label name
00250     $stacksize  - the size of the local stack frame
00251   */
00252  
00253   // a Lir2Asm record (maps from LIR to assembler code)
00254   struct Lir2Asm {
00255     // reset this guy
00256     void reset() {
00257       _lirInstTypes.clear();
00258       _killRegs.clear();
00259       _codeTemplate.clear();
00260       _immed = Immed_NA;
00261     }
00262 
00263     // the set of instruction types that this record applies to
00264     vector<mnemonic>    _lirInstTypes;
00265 
00266     // data types
00267     vector<typeNode *>  _dataTypes;
00268     vector<typeNode *>  _convertToTypes;
00269 
00270     // register dependency information
00271     register_info_list  _killRegs;
00272 
00273     // code template for this instruction
00274     code_template               _codeTemplate;
00275 
00276     // the Immed flag for this template, if specified
00277     enum {
00278       Immed_NA = -1,    // value not specified
00279       Immed_No = 0,     // not immediate
00280       Immed_Yes = 1     // immeidate
00281     } _immed;
00282   }; // end struct Lir2Asm
00283 
00284   // a vector of Lir2Asm things
00285   typedef vector<Lir2Asm>       Lir2Asm_list;
00286 
00287  private:
00288   // helper methods
00289 
00290   // init static variables
00291   static void do_init_static();
00292 
00293   // find a register in our set of all registers
00294   // returns nonzero if the register is found, zero otherwise
00295   bool find_register_info( const char * name, 
00296                            register_info *& regInfoFound ) const;
00297 
00298   // find the Lir2Asm block for a given instruction
00299   // returns zero if the instruction is not supported, nonzero otherwise
00300   bool get_Lir2Asm_for_instruction( const LirInst * pInst, 
00301                                     Lir2Asm ** ppLir2Asm );
00302   bool get_Lir2Asm_for_instruction( mnemonic inst, typeNode * srcType, 
00303                                     typeNode * destType, bool isImmed, 
00304                                     Lir2Asm ** ppLir2Asm );
00305   bool findType(vector<typeNode *> &, typeNode *);
00306 
00307   // make replacements in the given code template for the given instruction
00308   void make_template_replacements( const LirInst * pInst, Lir2Asm * pLir2Asm, 
00309                                    code_template & outputTemplate );
00310 
00311  private:
00312   // member data
00313 
00314   // whether or not we currently have valid data
00315   bool                  _valid;
00316 
00317   // the next logical register ID to use
00318   unsigned int  _nextRegId;
00319 
00320   // the name of the architecture
00321   string                        _archName;
00322 
00323   // asm formatting stuff
00324   string                        _asmLineComment;
00325   string                        _asmRegPrefixAdd;
00326   string                        _asmRegPrefixRemove;
00327   vector<string>        _asmRegPrefixRemoveSplit;
00328   string                        _asmConstPrefix;
00329 
00330   // register information
00331   register_info_list    _regsAll;
00332   register_info_map     _regMap;
00333 
00334   // different usages of registers
00335   register_info_list    _regsGpr;
00336   register_info_list    _regsFpr;
00337   register_info*        _regSp;
00338   register_info*        _regFp;
00339   register_info_list    _regsParamFixed;
00340   register_info_list    _regsParamFloat;
00341   register_info*        _regRetvalFixed;
00342   register_info*        _regRetvalFloat;
00343   register_info_list    _regsCallerSave;
00344   register_info_list    _regsCalleeSave;
00345   typeNode *            _regDataTypeGpr;
00346   typeNode *            _regDataTypeFpr;
00347 
00348   // data size information
00349   int                   _dataSizeLong;
00350   int                   _dataSizeInt;
00351   int                   _dataSizeShort;
00352   int                   _dataSizeDouble;
00353   int                   _dataSizeFloat;
00354   int                   _dataSizePtr;
00355 
00356   // data alignment information
00357   mutable int           _maxDataAlign;
00358   int                   _dataAlignChar;
00359   int                   _dataAlignShort;
00360   int                   _dataAlignInt;
00361   int                   _dataAlignLong;
00362   int                   _dataAlignFloat;
00363   int                   _dataAlignDouble;
00364   int                   _dataAlignPtr;
00365 
00366   // stack management information
00367   int                   _stackFrameMinSize;
00368   int                   _stackExtraTop;
00369   int                   _stackExtraBottom;
00370   int                   _stackAlign;
00371   int                   _stackFormalsOffset;
00372 
00373   // emulation mode
00374   bool                  _emulate3Address;
00375 
00376   // the set of Lir2Asm records for this arch
00377   // NOTE: you should NOT change the order of the records of this array
00378   //    under any circumstances.  if you do, you will mess up the 
00379   //    mnemonic->Lir2Asm map below.
00380   Lir2Asm_list  _Lir2Asm_records;
00381 
00382   // a map from instruction mnemonic to a set of array indices of Lir2Asm
00383   //    records that might be able to handle that instruction.
00384   typedef map<mnemonic, vector<int> > map_menmonic_to_record_set;
00385   map_menmonic_to_record_set _Lir2Asm_mnemonicLookup;
00386 
00387   // some temporaries used when parsing Lir2Asm records
00388   // NOTE: see parse_Lir2Asm_item() for usage of this
00389   string                                _tempParseString;
00390   register_info_list    _tempRegList;
00391   bool                          _tempBool;
00392 }; // end class arch_info
00393 
00394 #endif
00395 

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