Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* -*-Mode: c++;-*- (Tell emacs to use c++ mode) */ 00037 00038 #ifndef segmented_array_INCLUDED 00039 #define segmented_array_INCLUDED 00040 00041 #ifndef __SGI_STL_VECTOR_H 00042 00043 # if defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES) 00044 # undef short // get around bogus type defs. 00045 # undef int 00046 # undef long 00047 # endif // defined(defs_INCLUDED) && !defined(USE_STANDARD_TYPES) 00048 00049 using namespace std; 00050 #include <vector> 00051 00052 #endif // __SGI_STL_VECTOR_H 00053 00054 #include "errors.h" 00055 #include "mempool.h" 00056 #include "mempool_allocator.h" 00057 00058 00059 // SA_Ptr is pointer to SEG_ARRAY, 00060 // SA_vt_Ptr is pointer to SEG_ARRAY::value_type, 00061 // SA_vt_Ref is reference to SEG_ARRAY::value_type. 00062 // 00063 // These are template parameters because we need both constant and 00064 // mutable iterators. For a constant iterator they will be, 00065 // respectively, const SEG_ARRAY*, const SEG_ARRAY::value_type*, and 00066 // const SEG_ARRAY::value_type&. For a mutable iterator they will be 00067 // SEG_ARRAY*, SEG_ARRAY::value_type*, and SEG_ARRAY::value_type&. 00068 00069 // TO DO: add a conversion from the mutable version to the constant 00070 // version. 00071 00072 template <class SA_Ptr, class T, class SA_vt_Ptr, class SA_vt_Ref> 00073 class SEGMENTED_ARRAY_ITERATOR 00074 { 00075 public: 00076 typedef T value_type; 00077 typedef UINT difference_type; 00078 typedef std::forward_iterator_tag iterator_category; 00079 typedef SA_vt_Ptr pointer; 00080 typedef SA_vt_Ref reference; 00081 00082 private: 00083 00084 SA_Ptr segmented_array; 00085 SA_vt_Ptr ptr; // pointer to the current element 00086 SA_vt_Ptr segment_last; // ptr after the current segment 00087 UINT map_idx; // index to the map array 00088 00089 private: 00090 00091 typedef SEGMENTED_ARRAY_ITERATOR self; 00092 00093 public: 00094 00095 SEGMENTED_ARRAY_ITERATOR (SA_Ptr sa, T* p, T* last, UINT idx) 00096 : segmented_array (sa), ptr (p), segment_last (last) { 00097 map_idx = sa->Block_index(idx); 00098 } 00099 00100 SEGMENTED_ARRAY_ITERATOR (SA_Ptr sa, UINT idx) 00101 : segmented_array (sa) { 00102 map_idx = sa->Block_index(idx); 00103 ptr = &(sa->Entry(idx)); 00104 segment_last = sa->Block_end(map_idx); 00105 } 00106 00107 SEGMENTED_ARRAY_ITERATOR () {} 00108 00109 SA_vt_Ref operator* () const { return *ptr; } 00110 SA_vt_Ptr Ptr () const { return ptr; } 00111 SA_vt_Ptr operator->() const { return ptr; } 00112 UINT Index () const { 00113 return map_idx * segmented_array->Block_size() + 00114 (ptr - segmented_array->Block_begin(map_idx)); 00115 } 00116 00117 self& operator ++ () { 00118 ++ptr; 00119 if (ptr == segment_last) { 00120 UINT map_entries = 00121 (segment_last - segmented_array->Block_begin(map_idx)) / 00122 segmented_array->Block_size (); 00123 if (map_idx + map_entries < segmented_array->Block_index_end()) { 00124 map_idx += map_entries; 00125 ptr = segmented_array->Block_begin(map_idx); 00126 segment_last = segmented_array->Block_end(map_idx); 00127 } 00128 } 00129 return *this; 00130 } 00131 00132 self operator ++ (int) { 00133 self tmp = *this; 00134 ++(*this); 00135 return tmp; 00136 } 00137 00138 BOOL operator == (const self& x) const { return ptr == x.ptr; } 00139 BOOL operator != (const self& x) const { return !(*this == x); } 00140 00141 }; // SEGMENTED_ARRAY_ITERATOR 00142 00143 00144 template <class T, UINT block_size = 128> 00145 class SEGMENTED_ARRAY 00146 { 00147 private: 00148 00149 std::vector<std::pair<T *, BOOL>, mempool_allocator<std::pair<T *,BOOL> > > map; 00150 00151 MEM_POOL *pool; 00152 UINT size_; // total number of elements inserted 00153 UINT max_size_; // total # of elements allocated 00154 INT block_base; // idx of the beginning of 00155 // block (signed so we can set 00156 // to -1, meaning no block allocated) 00157 UINT next_block_size; // size of block to be allocated 00158 T *block; // points to the last block 00159 00160 typedef SEGMENTED_ARRAY<T, block_size> self; 00161 00162 public: 00163 typedef T base_type; 00164 00165 typedef T value_type; 00166 typedef value_type* pointer; 00167 typedef const value_type* const_pointer; 00168 typedef value_type& reference; 00169 typedef const value_type& const_reference; 00170 typedef UINT size_type; 00171 typedef INT difference_type; 00172 00173 typedef SEGMENTED_ARRAY_ITERATOR<self*, T, pointer, reference> 00174 iterator; 00175 typedef SEGMENTED_ARRAY_ITERATOR<const self*, T, 00176 const_pointer, const_reference> 00177 const_iterator; 00178 00179 private: 00180 00181 // private operations 00182 00183 UINT Round_up (UINT s) { 00184 UINT mask = block_size - 1; 00185 return (s + mask) & ~mask; 00186 } 00187 00188 void Update_Map (T *marker, UINT new_size, BOOL own_memory); 00189 00190 void Pop_Map (); 00191 00192 // allocate a block, assume the array is completely filled 00193 void Allocate (); 00194 00195 T& New_entry () { 00196 if (size_ == max_size_) Allocate (); 00197 return block[size_++ - block_base]; 00198 } 00199 00200 // copy n elements to current buffer, assume no overflow 00201 void Copy (const T* x, UINT n) { 00202 std::copy(x, x + n, block + (size_ - block_base)); 00203 size_ += n; 00204 } 00205 00206 // block_idx is an index into the map. This function returns 00207 // the first map index that points to a different block. 00208 UINT next_block_idx(UINT block_idx) const { 00209 for ( ; block_idx + 1 < map.size() && 00210 map[block_idx].first + block_size == map[block_idx + 1].first ; 00211 ++block_idx) 00212 {} 00213 return block_idx + 1; 00214 } 00215 00216 public: 00217 00218 SEGMENTED_ARRAY(MEM_POOL *m = Malloc_Mem_Pool) : map (m), pool (m) { 00219 size_ = max_size_ = next_block_size = 0; 00220 block_base = -1; 00221 block = 0; 00222 } 00223 00224 ~SEGMENTED_ARRAY() { 00225 typedef typename vector<pair<T *, BOOL>, mempool_allocator<pair<T *, BOOL> > >::iterator TempIteratorType; 00226 // Free memory from blocks. Map memory gets freed when the map 00227 // vector is destructed. 00228 for ( TempIteratorType entry = map.begin(); entry != map.end(); ++entry ) { 00229 // entry->second <==> this map entry owns the block's memory. 00230 if (entry->second) { 00231 MEM_POOL_FREE(pool, entry->first); 00232 } 00233 } 00234 } 00235 00236 UINT Block_size () const { return block_size; } 00237 00238 UINT Size () const { return size_; } 00239 UINT size () const { return size_; } 00240 00241 T& Entry (UINT idx) { 00242 Is_True (idx < size_, ("Array subscript out of bound")); 00243 return map[idx / block_size].first[idx % block_size]; 00244 } 00245 00246 const T& Entry (UINT idx) const { 00247 Is_True (idx < size_, ("Array subscript out of bound")); 00248 return map[idx / block_size].first[idx % block_size]; 00249 } 00250 T& operator[] (UINT idx) { return Entry(idx); } 00251 const T& operator[] (UINT idx) const { return Entry(idx); } 00252 00253 iterator begin () { 00254 return iterator (this, map[0].first, Block_end (0), 0); 00255 } 00256 00257 iterator end () { 00258 return iterator (this, block + (size_ - block_base), 00259 block + (max_size_ - block_base), size_); 00260 } 00261 00262 const_iterator begin () const { 00263 return const_iterator (this, map[0].first, Block_end (0), 0); 00264 } 00265 00266 const_iterator end () const { 00267 return const_iterator (this, block + (size_ - block_base), 00268 block + (max_size_ - block_base), size_); 00269 } 00270 00271 00272 T& New_entry (UINT& idx) { idx = size_; return New_entry (); } 00273 00274 UINT Insert (const T& x); 00275 00276 void Delete_last () { 00277 --size_; 00278 if (size_ == block_base) 00279 Pop_Map (); 00280 } 00281 00282 00283 void Delete_last (UINT n); 00284 00285 void Delete_down_to (UINT idx) { 00286 if (size_ > idx) 00287 Delete_last (size_ - idx); 00288 } 00289 00290 // insert multiple elements, always copy to new buffer. 00291 UINT Insert (const T* x, UINT n_elemt); 00292 00293 // similar to insert, except reuse the given buffer if possible 00294 UINT Transfer (T* x, UINT n_elemt); 00295 00296 // Reserve extra storage. Actual allocation will be done when the 00297 // already allocated storage is filled. 00298 void Reserve (UINT n_elemt) { 00299 if (max_size_ - size_ + next_block_size < n_elemt) 00300 next_block_size = n_elemt - (max_size_ - size_); 00301 } 00302 00303 // return the number of element till the end of the block 00304 UINT Get_block_size (UINT idx) const { 00305 UINT block_idx = idx / block_size; 00306 return std::min(next_block_idx(block_idx) * block_size, size_) - idx; 00307 } 00308 00309 UINT Block_index (UINT idx) const { return idx / block_size; } 00310 00311 // A valid block index n is in the range 0 <= n < Block_index_end(). 00312 UINT Block_index_end () const { return map.size(); } 00313 00314 T* Block_begin (UINT block_idx) { return map[block_idx].first; } 00315 const T* Block_begin (UINT block_idx) const { return map[block_idx].first; } 00316 00317 T* Block_end(UINT block_idx) { 00318 return Block_begin(block_idx) + 00319 (next_block_idx(block_idx) - block_idx) * block_size; 00320 } 00321 00322 const T* Block_end(UINT block_idx) const { 00323 return Block_begin(block_idx) + 00324 (next_block_idx(block_idx) - block_idx) * block_size; 00325 } 00326 00327 }; // SEGMENTED_ARRAY 00328 00329 00330 template <class T, UINT block_size> 00331 inline void 00332 SEGMENTED_ARRAY<T,block_size>::Update_Map(T *marker, 00333 UINT new_size, 00334 BOOL own_memory) 00335 { 00336 do { 00337 map.push_back(std::pair<T*, BOOL>(marker, own_memory)); 00338 // own_memory = FALSE; 00339 new_size -= block_size; 00340 marker += block_size; 00341 } while (new_size); 00342 } // SEGMENTED_ARRAY<T,block_size>::Update_Map 00343 00344 00345 // deallocate a block and re-adjust the map and other variables 00346 template <class T, UINT block_size> 00347 void 00348 SEGMENTED_ARRAY<T,block_size>::Pop_Map () 00349 { 00350 next_block_size += max_size_ - block_base; 00351 MEM_POOL_FREE (pool, block); 00352 00353 T *last_map_entry; 00354 do { 00355 last_map_entry = (map.end() - 1)->first; 00356 map.pop_back (); 00357 } while (last_map_entry != block); 00358 00359 max_size_ = size_; 00360 if (size_ > 0) { 00361 Is_True(size_ >= block_size, 00362 ("SEGMENTED_ARRAY: size in limbo")); 00363 block_base = size_ - block_size; 00364 UINT idx = block_base / block_size; 00365 block = map[idx].first; 00366 while (idx > 0 && map[idx - 1].first + block_size == block) { 00367 block = map[--idx].first; 00368 block_base -= block_size; 00369 } 00370 } 00371 else { 00372 Is_True(map.begin() == map.end(), 00373 ("SEGMENTED_ARRAY::Pop_Map: Map should be empty")); 00374 block_base = -1; 00375 block = NULL; 00376 } 00377 } // SEGMENTED_ARRAY<T,block_size>::Pop_Map 00378 00379 00380 template <class T, UINT block_size> 00381 void 00382 SEGMENTED_ARRAY<T,block_size>::Allocate () 00383 { 00384 Is_True (size_ == max_size_, ("Invalid internal state in segmented array")); 00385 00386 UINT new_size; 00387 00388 if (next_block_size == 0) 00389 new_size = block_size; 00390 else { 00391 new_size = Round_up (next_block_size); 00392 next_block_size = 0; 00393 } 00394 00395 block = (T *) MEM_POOL_Alloc (pool, new_size * sizeof(T)); 00396 max_size_ += new_size; 00397 block_base = size_; 00398 00399 Update_Map (block, new_size, TRUE); 00400 00401 } // SEGMENTED_ARRAY::Allocate 00402 00403 00404 template <class T, UINT block_size> 00405 void 00406 SEGMENTED_ARRAY<T,block_size>::Delete_last (UINT n) 00407 { 00408 while (n >= size_ - block_base) { 00409 n -= size_ - block_base; 00410 size_ = block_base; 00411 Pop_Map (); 00412 } 00413 00414 size_ -= n; 00415 } // Delete_last 00416 00417 00418 template <class T, UINT block_size> 00419 inline UINT 00420 SEGMENTED_ARRAY<T,block_size>::Insert (const T& x) 00421 { 00422 UINT idx = size_; 00423 T &entry = New_entry (); 00424 00425 entry = x; 00426 return idx; 00427 } // SEGMENTED_ARRAY::Insert 00428 00429 00430 template <class T, UINT block_size> 00431 UINT 00432 SEGMENTED_ARRAY<T,block_size>::Insert (const T* x, UINT n_elemt) 00433 { 00434 UINT result = size_; 00435 if (size_ + n_elemt <= max_size_) { 00436 Copy (x, n_elemt); 00437 return result; 00438 } 00439 00440 UINT space_left = max_size_ - size_; 00441 Copy (x, space_left); 00442 n_elemt -= space_left; 00443 00444 Reserve (n_elemt); 00445 Allocate (); 00446 Copy (x + space_left, n_elemt); 00447 00448 return result; 00449 } // SEGMENTED_ARRAY::Insert 00450 00451 00452 template <class T, UINT block_size> 00453 UINT 00454 SEGMENTED_ARRAY<T,block_size>::Transfer (T* x, UINT n_elemt) 00455 { 00456 UINT result = size_; 00457 00458 if (size_ + n_elemt <= max_size_) { 00459 Copy (x, n_elemt); 00460 return result; 00461 } 00462 00463 UINT space_left = max_size_ - size_; 00464 if (space_left > 0) { 00465 Copy (x, space_left); 00466 n_elemt -= space_left; 00467 x += space_left; 00468 } 00469 00470 if (n_elemt >= block_size) { 00471 UINT reused_size = n_elemt & ~(block_size - 1); 00472 block = x; 00473 Update_Map (block, reused_size, FALSE); 00474 block_base = size_; 00475 size_ += reused_size; 00476 max_size_ += reused_size; 00477 n_elemt -= reused_size; 00478 x += reused_size; 00479 if (next_block_size > reused_size) 00480 next_block_size -= reused_size; 00481 else 00482 next_block_size = 0; 00483 } 00484 00485 if (n_elemt > 0) { 00486 Allocate (); 00487 Copy (x, n_elemt); 00488 } 00489 00490 return result; 00491 00492 } // SEGMENTED_ARRAY::Transfer 00493 00494 00495 template <class T, UINT block_size, class OP> 00496 inline void 00497 For_all_entries (SEGMENTED_ARRAY<T, block_size>& array, const OP &op, 00498 UINT32 first = 0) 00499 { 00500 UINT last = array.size (); 00501 00502 while (first < last) { 00503 T *block = &array[first]; 00504 UINT size = array.Get_block_size (first); 00505 for (UINT j = 0; j < size; ++j, ++block) 00506 op (first + j, block); 00507 first += size; 00508 } 00509 } 00510 00511 // The following function is ifdefed out because, until we have 00512 // partial ordering of function templates, the compiler will flag it 00513 // as ambiguous. 00514 #if 0 00515 00516 template <class T, UINT block_size, class OP> 00517 inline void 00518 For_all_entries (const SEGMENTED_ARRAY<T, block_size>& array, const OP &op, 00519 UINT32 first = 0) 00520 { 00521 UINT last = array.size (); 00522 00523 while (first < last) { 00524 const T *block = &array[first]; 00525 UINT size = array.Get_block_size (first); 00526 for (UINT j = 0; j < size; ++j, ++block) 00527 op (first + j, block); 00528 first += size; 00529 } 00530 } 00531 00532 #endif 00533 00534 template <class T, UINT block_size, class OP> 00535 inline void 00536 For_all_blocks (SEGMENTED_ARRAY<T, block_size>& array, const OP &op) 00537 { 00538 UINT max_size = array.size (); 00539 UINT i = 0; 00540 00541 while (i < max_size) { 00542 T *block = &array[i]; 00543 UINT size = array.Get_block_size (i); 00544 op (i, block, size); 00545 i += size; 00546 } 00547 } 00548 00549 00550 #define NOT_FOUND ((UINT) -1) 00551 00552 template <class T, UINT block_size, class PREDICATE> 00553 inline UINT 00554 Find_entry_if (const SEGMENTED_ARRAY<T, block_size>& array, 00555 const PREDICATE& pred, UINT i = 0) 00556 { 00557 UINT max_size = array.size (); 00558 00559 while (i < max_size) { 00560 const T *block = &array[i]; 00561 UINT size = array.Get_block_size (i); 00562 for (UINT j = 0; j < size; ++j, ++block) 00563 if (pred (i+j, block)) 00564 return i + j; 00565 i += size; 00566 } 00567 00568 return (UINT) NOT_FOUND; 00569 } 00570 00571 00572 // copy the content of one segmented array to another, optionally specified 00573 // the range [first_idx, last_idx) to be copied. 00574 // returns the number of entries copied. 00575 template <class T, UINT block_size> 00576 UINT32 00577 Copy_array_range (const SEGMENTED_ARRAY<T, block_size>& from_array, 00578 SEGMENTED_ARRAY<T, block_size>& to_array, 00579 UINT32 first_idx = 0, UINT32 last_idx = (UINT32) -1) 00580 { 00581 if (last_idx > from_array.size ()) 00582 last_idx = from_array.size (); 00583 00584 Is_True (last_idx >= first_idx, ("Invalid copy range")); 00585 00586 UINT32 entries = last_idx - first_idx; 00587 00588 to_array.Reserve (entries); 00589 00590 while (first_idx < last_idx) { 00591 const T* block = &from_array[first_idx]; 00592 UINT32 size = from_array.Get_block_size (first_idx); 00593 if (size > last_idx - first_idx) 00594 size = last_idx - first_idx; 00595 00596 to_array.Insert (block, size); 00597 first_idx += size; 00598 } 00599 00600 return entries; 00601 } // Copy_array_range 00602 00603 #endif /* segmented_array_INCLUDED */