memory_allocators.cc

Go to the documentation of this file.
00001 /*!
00002         \file
00003         \brief Implementation of memory allocators for i686 architecture.
00004         \author jaz
00005 */
00006 
00007 #include <lestes/std/set.hh>
00008 #include <lestes/md/common.hh>
00009 #include <lestes/md/types/tm_data_type_base.g.hh>
00010 #include <lestes/md/registers/tm_register_base.g.hh>
00011 #include <lestes/md/tasm/tm_asm.mdg.hh>
00012 #include <lestes/md/symbols/symbol_register.g.hh>
00013 #include <lestes/md/symbols/name_mangler.g.hh>
00014 #include <lestes/md/literals/literal_info_base.g.hh>
00015 #include <lestes/md/types/ss_type2tm_type.g.hh>
00016 #include <lestes/backend_v2/structs/pi_operands.g.hh>
00017 #include <lestes/backend_v2/intercode/pi_mem_factory.g.hh>
00018 #include <lestes/backend_v2/intercode/pi.g.hh>
00019 #include <lestes/backend_v2/intercode/visitor_pi_pi2id.g.hh>
00020 #include <lestes/backend_v2/intercode/visitor_pi_pi2pi_operands.g.hh>
00021 #include <lestes/lang/cplus/sem/ss_declaration.g.hh>
00022 #include <lestes/lang/cplus/sem/ss_type.g.hh>
00023 #include <lestes/md/mem/memory_allocators.g.hh>
00024 
00025 package(lestes);
00026 package(md);
00027 package(mem)
00028 
00029 using namespace ::lestes::backend_v2::intercode;
00030 using namespace ::lestes::backend_v2::structs;
00031 using namespace ::lestes::md::types;
00032 using namespace ::lestes::lang::cplus::sem;
00033 
00034 using ::lestes::md::symbols::name_mangler;
00035 using ::lestes::md::symbols::symbol_register;
00036 using ::lestes::md::types::ss_type2tm_type;
00037 using ::lestes::md::literals::literal_info_base;
00038 using ::lestes::md::tasm::tm_asm;
00039 
00040 typedef list< srp< pi_mf_stack > >                      pi_mf_stack_list_type;
00041 typedef set< srp< pi_mf_stack > >                       pi_mf_stack_set_type;
00042 typedef list< srp< pi_pi > >                            pi_pi_list_type;
00043 typedef list< srp< pi_operand > >                       pi_operand_list_type;
00044 typedef map< srp< ss_object_declaration >, srp< pi_mf_decl > > decl2mf_decl_map_type;
00045 typedef map< srp< ss_object_declaration >, srp< pi_mf_stack > > decl2mf_stack_map_type;
00046 typedef map< srp< pi_mem_factory >, srp< literal_info_base > > mf2pi_li_map_type;
00047 typedef list< srp< pi_mem > >                           pi_mem_list_type;
00048 
00049 
00050 declare_logger(log);
00051 initialize_logger( log, "memory_allocators", md_logger );
00052 
00053 #define STACK_ALIGNMENT 32
00054 
00055 
00056 /***************************** GLOBAL_VARIABLE_ALLOCATOR *******************************************/
00057 
00058 /*!
00059         \brief Calculates placement of allocated variables in memory.
00060 */
00061 void global_variable_allocator::calculate_placement() {
00062         //TODO
00063 }
00064 
00065 /*!
00066         \brief Generates asm declarations for initialized global variables.
00067         
00068         \param output Output stream.
00069 */
00070 void global_variable_allocator::emit_asm_declarations_for_initialized(::std::ostream& output) {
00071         lassert(output);
00072         
00073         decl2mf_decl_map_type::iterator it;
00074         for(it=variables_get()->begin(); it!=variables_get()->end(); it++) {
00075         
00076                 mf2pi_li_map_type::iterator it2 = values_get()->find(it->second);
00077                 
00078                 if ( it2==values_get()->end() ) {
00079                         /*
00080                                 Variable is unitialized. 
00081                                 It is emited by emit_asm_declarations_for_uninitialized call.
00082                         */
00083                         continue;
00084                 }
00085                 
00086                 lstring code = tm_asm::ent_global_simple_decl_get();
00087                 
00088                 lstring id = name_mangler::instance()->mangle(it->first);
00089                 lstring type = it2->second->get_asm_definition_type();
00090                 lstring value = it2->second->get_asm_definition_val();
00091                 
00092                 code = string_replace(code,"$id",id);
00093                 code = string_replace(code,"$type",type);
00094                 code = string_replace(code, "$value", value);
00095                 output << code;
00096         }
00097 }
00098 
00099 /*!
00100         \brief Generates asm declarations for uninitialized global variables.
00101         
00102         \param output Output stream.
00103 */
00104 void global_variable_allocator::emit_asm_declarations_for_uninitialized(::std::ostream& output) {
00105         lassert(output);
00106         
00107         decl2mf_decl_map_type::iterator it1;
00108         for(it1=variables_get()->begin(); it1!=variables_get()->end(); it1++) {
00109         
00110                 mf2pi_li_map_type::iterator it2 = values_get()->find(it1->second);
00111                 
00112                 if ( it2!=values_get()->end() ) {
00113                         /*
00114                                 Variable is itialized.
00115                                 It is emited by emit_asm_declarations_for_initialized call.
00116                         */
00117                         continue;
00118                 }
00119                 
00120                 lstring code = tm_asm::ent_global_simple_decl_get();
00121                 
00122                 lstring id = name_mangler::instance()->mangle(it1->first);
00123                 
00124                 ptr<tm_data_type_base> dt = it1->second->type_get();
00125                 lstring type;
00126                 
00127                 ::std::ostringstream oss;
00128                 oss << "resb " << dt->bitwidth_get()/8; 
00129                 type = oss.str();
00130                 
00131                 code = string_replace(code,"$id",id);
00132                 code = string_replace(code,"$type",type);
00133                 code = string_replace(code, "$value", "");
00134                 output << code;
00135         }
00136 }
00137 
00138 /*!
00139         \brief Deallocates space for variable.
00140         
00141         The right moment for dealocation is given by two sequencepoints. Dealocation is performed between them.
00142         
00143         \param mem The space to be dealocated.
00144         \param psp The first bound sequencepoint.
00145         \param nsp The second bound sequencepoint.
00146 */
00147 void global_variable_allocator::deallocate(ptr<pi_mem_factory>, ptr<pi_sp>, ptr<pi_sp>) {
00148 }
00149 
00150 /*!
00151         \brief Allocates space for variable in global data storage.
00152         
00153         \param decl Declaration of the variable.
00154         \return The memory space for variable.
00155 */
00156 ptr< pi_mem_factory > global_variable_allocator::allocate(ptr< ss_object_declaration > decl) {
00157         lassert(decl);
00158         
00159         //Check whether variable for the declaration has been already allocated.
00160         decl2mf_decl_map_type::iterator it = variables_get()->find(decl);
00161         if ( it!=variables_get()->end()) {
00162                 //Variable has been already allocated!
00163                 return it->second;
00164         }
00165         
00166         //Allocate new global variable.
00167         ptr<pi_mf_decl> new_var = pi_mf_decl::create(this, decl->type_get()->accept_ss_type2tm_type_gen_base(ss_type2tm_type::instance()), decl);
00168         
00169         //Add it to the global variable map.
00170         (*variables_get())[decl] = new_var;
00171 
00172         //Register new symbol in symbol register
00173         symbol_register::instance()->register_symbol(decl);
00174                 
00175         log << "Global variable(" << new_var->uid_get() << ") has been declared for ss_object_declaration(" << decl->uid_get() << ")\n";
00176         
00177         return  new_var;
00178 }
00179 
00180 /*!
00181         \brief Initialiaze memory space in global data storage with given value.
00182         
00183         \param mem The memory space.
00184         \param value The value.
00185 */
00186 void global_variable_allocator::init_variable(ptr<pi_mem_factory> mem, ptr<literal_info_base> value) {
00187         lassert(mem);
00188         lassert(value);
00189         
00190         //Check  that variable has been regularly allocated by this allocator.
00191         decl2mf_decl_map_type::iterator it = variables_get()->find(mem.dncast<pi_mf_decl>()->decl_get());
00192         lassert(it!=variables_get()->end());
00193         
00194         //Assign value to variable that occupies space mem.
00195         (*values_get())[mem] = value;
00196         
00197         log << "Global variable(" << mem->uid_get() << ") has been initialized with value " <<  value->get_asm_definition_val()<< "\n";
00198 }
00199 
00200 
00201 /************************* LOCAL_VARIABLE_ALLOCATOR **********************************************/
00202 /*!
00203         \brief Deallocates space for variable on the local stack.
00204         
00205         The right moment for dealocation is given by two sequencepoints. Dealocation is performed between them.
00206         
00207         \param mem The space to be dealocated.
00208         \param psp The first bound sequencepoint.
00209         \param nsp The second bound sequencepoint.
00210 */
00211 void local_variable_allocator::deallocate(ptr<pi_mem_factory>, ptr<pi_sp>, ptr<pi_sp>) {
00212 }
00213 
00214 /*!
00215         \brief Allocates space for temporal variable on the local stack.
00216         
00217         \param type Type of variable.
00218         \return The memory space for variable.
00219 */
00220 ptr< pi_mem_factory > local_variable_allocator::allocate_tmp(ptr< tm_data_type_base > type) {
00221         lassert(type);
00222         
00223         //Create new pi_mem.
00224         ptr<pi_mf_stack> new_var = pi_mf_stack::create(this,type,0);
00225         
00226         //Add it to the local variable list for the function.
00227         tmps->push_back(new_var);       
00228         
00229         return  new_var;
00230 }
00231 
00232 
00233 /*!
00234         \brief Allocates space for regular variable on the local stack.
00235         
00236         \param decl Declaration of the variable.
00237         \return The memory space for variable.
00238 */
00239 
00240 ptr< pi_mem_factory > local_variable_allocator::allocate(ptr< ss_object_declaration > decl) {
00241         lassert(decl);
00242 
00243         //Check whether variable for the declaration has been already allocated.
00244         decl2mf_stack_map_type::iterator it = variables_get()->find(decl);
00245         if ( it!=variables_get()->end()) {
00246                 //Variable has been already allocated.
00247                 return it->second;
00248         }
00249         
00250         //Allocate new local variable.
00251         ptr<pi_mf_stack> new_var = pi_mf_stack::create(this, decl->type_get()->accept_ss_type2tm_type_gen_base(ss_type2tm_type::instance()), 0);
00252         
00253         //Add it to the local variable map.
00254         (*variables_get())[decl] = new_var;
00255         
00256         return  new_var;
00257 }
00258 
00259 
00260 /*
00261         \brief Calculates placement of local variables and parameters in memory.
00262         
00263         Note:
00264         Stack arrangement before function call
00265          ------------------ EBP
00266                 local vars
00267         ------------------- EBP+tmps_space_start_offset
00268                 tmp local vars
00269         -------------------     EBP+pars_space_start_offset-preserved_space_size
00270                 EDI, ESI, EBX
00271         ------------------- EBP+pars_space_start_offset
00272                 parameters
00273         ------------------- ESP 
00274         
00275         \param pi_list Function's body.
00276 */
00277 void local_variable_allocator::calculate_placement() {
00278         if ( placement_calculated_get() ) {
00279                 lassert(false);
00280                 return;
00281         }
00282 
00283         preserved_space_size_set(0);
00284         calculate_vars_placement();
00285         calculate_tmps_placement();
00286         placement_calculated_set(true);
00287 }
00288 
00289 
00290 /*!
00291         \brief Calculates placement of regular local variables in memory.
00292 */
00293 void local_variable_allocator::calculate_vars_placement() {     
00294         
00295         vars_space_start_offset_set(-preserved_space_size_get());
00296         
00297         t_ssize offset = vars_space_start_offset_get();
00298         
00299         decl2mf_stack_map_type::iterator it;    
00300         for(it=variables->begin(); it!=variables->end(); it++) {
00301                 ptr<pi_mf_stack> mem = it->second;
00302                 
00303                 ulint item_size = mem->type_get()->bitwidth_get();
00304                 
00305                 if ( item_size % STACK_ALIGNMENT != 0 ){
00306                         item_size = (item_size/STACK_ALIGNMENT + 1)*STACK_ALIGNMENT;
00307                 }
00308                                 
00309                 offset -= item_size;
00310                 
00311                 mem->offset_set(offset);
00312         }
00313         
00314         tmps_space_start_offset_set(offset);
00315 }
00316 
00317 /*!
00318         \brief Calculates placement of temporal local variables in memory.
00319 */
00320 void local_variable_allocator::calculate_tmps_placement() {     
00321         
00322         t_ssize offset = tmps_space_start_offset_get();
00323         
00324         pi_mf_stack_list_type::iterator it;     
00325         for(it=tmps->begin(); it!=tmps->end(); it++) {
00326                 ptr<pi_mf_stack> mem = *it;
00327                 
00328                 ulint item_size = mem->type_get()->bitwidth_get();
00329                 
00330                 if ( item_size % STACK_ALIGNMENT != 0 ){
00331                         item_size = (item_size/STACK_ALIGNMENT + 1)*STACK_ALIGNMENT;
00332                 }
00333                 offset -= item_size;
00334                 
00335                 mem->offset_set(offset);
00336         }
00337         
00338         local_end_offset_set(offset);
00339 }
00340 
00341 end_package(mem)
00342 end_package(md);
00343 end_package(lestes);
00344 

Generated on Mon Feb 12 18:22:41 2007 for lestes by doxygen 1.5.1-20070107