FreeBASIC  0.91.0
reg.bas
Go to the documentation of this file.
1 '' local register allocation, based on the bottom-up algorithm (both
2 '' for stacked and normal sets)
3 ''
4 '' obs: only works locally, can't be used between blocks
5 ''
6 '' chng: sep/2004 written [v1ctor]
7 '' jan/2005 much more modular using fake classes [v1ctor]
8 
9 
10 #include once "fb.bi"
11 #include once "fbint.bi"
12 #include once "ir.bi"
13 #include once "reg.bi"
14 
15 '' internals
16 
17 declare sub regInitClass _
18  ( _
19  byval this_ as REGCLASS ptr, _
20  sizeTb() as REG_SIZEMASK _
21  )
22 
23 declare sub sregInitClass _
24  ( _
25  byval this_ as REGCLASS ptr, _
26  sizeTb() as REG_SIZEMASK _
27  )
28 
29 '':::::
30 function regNewClass _
31  ( _
32  byval class_ as integer, _
33  byval regs as integer, _
34  sizeTb() as REG_SIZEMASK, _
35  byval isstack as integer _
36  ) as REGCLASS ptr
37 
38  dim as REGCLASS ptr this_
39 
40  this_ = xcallocate( len( REGCLASS ) )
41 
42  this_->class = class_
43  this_->regs = regs
44  this_->isstack = isstack
45 
46  if( this_->isstack = FALSE ) then
47  regInitClass( this_, sizeTb() )
48  else
49  sregInitClass( this_, sizeTb() )
50  end if
51 
52  function = this_
53 
54 end function
55 
56 '':::::
57 function regDelClass _
58  ( _
59  byval this_ as REGCLASS ptr _
60  ) as integer
61 
62  function = FALSE
63 
64  if( this_ = NULL ) then
65  exit function
66  end if
67 
68  deallocate( this_ )
69 
70  function = TRUE
71 
72 end function
73 
74 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
75 '' non-stack registers allocator
76 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
77 
78 '':::::
79 sub regPush _
80  ( _
81  byval this_ as REGCLASS ptr, _
82  byval n as integer _
83  ) static
84 
85  dim as REG_REG ptr r
86 
87  '' take from used list
88  r = this_->regctx.usedtail
89 
90  this_->regctx.usedtail = r->prev
91 
92  '' add to free list
93  r->prev = this_->regctx.freetail
94  this_->regctx.freetail = r
95 
96  r->num = n
97 
98 end sub
99 
100 '':::::
101 function regPop _
102  ( _
103  byval this_ as REGCLASS ptr, _
104  byval size as integer _ '' in bytes
105  ) as integer static
106 
107  dim as REG_REG ptr r, last
108 
109  r = this_->regctx.freetail
110  do while( r <> NULL )
111  '' same size?
112  if( (this_->regctx.sizeTB(r->num) and size) <> 0 ) then
113  '' remove from free list
114  if( this_->regctx.freetail = r ) then
115  this_->regctx.freetail = r->prev
116  else
117  last->prev = r->prev
118  end if
119 
120  '' add to used list
121  r->prev = this_->regctx.usedtail
122  this_->regctx.usedtail = r
123 
124  return r->num
125  end if
126 
127  last = r
128  r = r->prev
129  loop
130 
131  function = INVALID
132 
133 end function
134 
135 '':::::
136 sub regPopReg _
137  ( _
138  byval this_ as REGCLASS ptr, _
139  byval n as integer _
140  ) static
141 
142  dim as REG_REG ptr r, last
143 
144  r = this_->regctx.freetail
145  do while( r <> NULL )
146  '' same?
147  if( r->num = n ) then
148  '' remove from free list
149  if( this_->regctx.freetail = r ) then
150  this_->regctx.freetail = r->prev
151  else
152  last->prev = r->prev
153  end if
154 
155  '' add to used list
156  r->prev = this_->regctx.usedtail
157  this_->regctx.usedtail = r
158 
159  exit sub
160  end if
161 
162  last = r
163  r = r->prev
164  loop
165 
166  '' loop shouldn't fail
167  errReportEx( FB_ERRMSG_INTERNAL, __FUNCTION__ )
168 
169 end sub
170 
171 '':::::
172 sub regClear _
173  ( _
174  byval this_ as REGCLASS ptr _
175  ) static
176 
177  dim as REG_REG ptr r
178  dim as integer n
179 
180  this_->regctx.freeTB = -1
181  this_->regctx.freetail = NULL
182  this_->regctx.usedtail = NULL
183 
184  for n = 0 to this_->regs - 1
185  this_->vregTB(n) = NULL
186  this_->vauxparent(n) = NULL
187  this_->regctx.nextTB(n) = 0
188 
189  r = @this_->regctx.regTB(n)
190 
191  '' add to free list
192  r->prev = this_->regctx.freetail
193  this_->regctx.freetail = r
194 
195  r->num = n
196  next
197 
198 end sub
199 
200 '':::::
201 function regFindFarest _
202  ( _
203  byval this_ as REGCLASS ptr, _
204  byval size as integer _ '' in bytes
205  ) as integer static
206 
207  dim as integer n, r
208  dim as uinteger maxdist
209 
210  '' all regs must be used atm
211 
212  maxdist = 0
213  r = INVALID
214  for n = 0 to this_->regs - 1
215  '' valid bits?
216  if( (this_->regctx.sizeTB(n) and size) <> 0 ) then
217  ''
218  if( this_->regctx.nextTB(n) > maxdist ) then
219  maxdist = this_->regctx.nextTB(n)
220  r = n
221  end if
222  end if
223  next
224 
225  function = r
226 
227 end function
228 
229 '':::::
230 function regAllocate _
231  ( _
232  byval this_ as REGCLASS ptr, _
233  byval vreg as IRVREG ptr, _
234  byval vauxparent as IRVREG ptr, _
235  byval size as uinteger _ '' in bytes
236  ) as integer
237 
238  dim as integer r = any
239 
240  r = regPop( this_, size )
241  if( r = INVALID ) then
242  r = regFindFarest( this_, size )
243 
244  '' This will regFree() the register
245  irStoreVR( this_->vregTB(r), this_->vauxparent(r) )
246 
247  '' So remove it from the free list
248  regPopReg( this_, r )
249  end if
250 
251  REG_SETUSED( this_->regctx.freeTB, r )
252  this_->vregTB(r) = vreg
253  this_->vauxparent(r) = vauxparent
254  this_->regctx.nextTB(r) = irGetDistance( vreg )
255 
256  function = r
257 
258 end function
259 
260 '':::::
261 function regAllocateReg _
262  ( _
263  byval this_ as REGCLASS ptr, _
264  byval r as integer, _
265  byval vreg as IRVREG ptr, _
266  byval vauxparent as IRVREG ptr _
267  ) as integer
268 
269  if( REG_ISFREE( this_->regctx.freeTB, r ) ) then
270  regPopReg( this_, r )
271  REG_SETUSED( this_->regctx.freeTB, r )
272  end if
273 
274  this_->vregTB(r) = vreg
275  this_->vauxparent(r) = vauxparent
276  this_->regctx.nextTB(r) = irGetDistance( vreg )
277 
278  function = r
279 
280 end function
281 
282 '':::::
283 function regEnsure _
284  ( _
285  byval this_ as REGCLASS ptr, _
286  byval vreg as IRVREG ptr, _
287  byval vauxparent as IRVREG ptr, _
288  byval size as uinteger _
289  ) as integer
290 
291  dim as integer r = any
292 
293  r = vreg->reg
294  if( r = INVALID ) then
295  r = regAllocate( this_, vreg, vauxparent, size )
296  irLoadVR( r, vreg, vauxparent )
297  end if
298 
299  function = r
300 
301 end function
302 
303 '':::::
304 sub regSetOwner _
305  ( _
306  byval this_ as REGCLASS ptr, _
307  byval r as integer, _
308  byval vreg as IRVREG ptr, _
309  byval vauxparent as IRVREG ptr _
310  )
311 
312  REG_SETUSED( this_->regctx.freeTB, r )
313  this_->vregTB(r) = vreg
314  this_->vauxparent(r) = vauxparent
315  this_->regctx.nextTB(r) = irGetDistance( vreg )
316 
317 end sub
318 
319 '':::::
320 sub regFree _
321  ( _
322  byval this_ as REGCLASS ptr, _
323  byval r as integer _
324  ) static
325 
326  if( REG_ISUSED( this_->regctx.freeTB, r ) ) then
327  REG_SETFREE( this_->regctx.freeTB, r )
328  this_->vregTB(r) = NULL
329  this_->vauxparent(r) = NULL
330  this_->regctx.nextTB(r) = 0
331  regPush( this_, r )
332  end if
333 
334 end sub
335 
336 '':::::
337 function regIsFree _
338  ( _
339  byval this_ as REGCLASS ptr, _
340  byval r as integer _
341  ) as integer static
342 
343  function = REG_ISFREE( this_->regctx.freeTB, r )
344 
345 end function
346 
347 '':::::
348 function regGetMaxRegs _
349  ( _
350  byval this_ as REGCLASS ptr _
351  ) as integer static
352 
353  function = this_->regs
354 
355 end function
356 
357 '':::::
358 function regGetFirst _
359  ( _
360  byval this_ as REGCLASS ptr _
361  ) as integer static
362 
363  function = 0
364 
365 end function
366 
367 '':::::
368 function regGetNext _
369  ( _
370  byval this_ as REGCLASS ptr, _
371  byval r as integer _
372  ) as integer static
373 
374  function = INVALID
375 
376  if( r >= 0 ) then
377  r += 1
378  if( r < this_->regs ) then
379  function = r
380  end if
381  end if
382 
383 end function
384 
385 '':::::
386 function regGetVreg _
387  ( _
388  byval this_ as REGCLASS ptr, _
389  byval r as integer, _
390  byref vauxparent as IRVREG ptr _
391  ) as IRVREG ptr static
392 
393  function = this_->vregTB(r)
394  vauxparent = this_->vauxparent(r)
395 
396 end function
397 
398 '':::::
399 function regGetRealReg _
400  ( _
401  byval this_ as REGCLASS ptr, _
402  byval r as integer _
403  ) as integer static
404 
405  function = r
406 
407 end function
408 
409 '':::::
410 sub regDump _
411  ( _
412  byval this_ as REGCLASS ptr _
413  )
414 #if 0
415  dim as integer i, cnt
416 
417  cnt = 0
418  for i = 0 to this_->regs - 1
419  if( REG_ISUSED( this_->regctx.freeTB, i ) ) then
420  print i;
421  cnt += 1
422  end If
423  next
424 
425  if( cnt > 0 ) then print
426 #endif
427 end sub
428 
429 '':::::
430 sub regInitClass _
431  ( _
432  byval this_ as REGCLASS ptr, _
433  sizeTb() as REG_SIZEMASK _
434  ) static
435 
436  dim as integer i
437 
438  regClear( this_ )
439 
440  for i = 0 to this_->regs - 1
441  this_->regctx.sizeTb(i) = sizeTb(i)
442  next
443 
444  this_->ensure = @regEnsure
445  this_->_allocate = @regAllocate
446  this_->allocateReg = @regAllocateReg
447  this_->free = @regFree
448  this_->isFree = @regIsFree
449  this_->setOwner = @regSetOwner
450  this_->getMaxRegs = @regGetMaxRegs
451  this_->getFirst = @regGetFirst
452  this_->getNext = @regGetNext
453  this_->getVreg = @regGetVreg
454  this_->getRealReg = @regGetRealReg
455  this_->clear = @regClear
456  this_->dump = @regDump
457 
458 end sub
459 
460 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
461 '' stack registers allocator
462 ''::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
463 
464 '':::::
465 function sregFindReg _
466  ( _
467  byval this_ as REGCLASS ptr, _
468  byval vreg as IRVREG ptr _
469  ) as integer static
470 
471  dim as integer r
472 
473  function = INVALID
474 
475  if( this_->stkctx.fregs = this_->regs ) then
476  exit function
477  end if
478 
479  for r = 0 to this_->regs - 1
480  if( this_->stkctx.regTB(r) <> INVALID ) then
481  if( this_->vregTB(r) = vreg ) then
482  return r
483  end If
484  end if
485  next
486 
487 end function
488 
489 '':::::
490 sub sregXchg _
491  ( _
492  byval this_ as REGCLASS ptr, _
493  byval r1 as integer _
494  ) Static
495 
496  dim as integer i, r2
497 
498  irXchgTOS( r1 )
499 
500  r2 = INVALID
501 
502  for i = 0 to this_->regs - 1
503  if( this_->stkctx.regTB(i) = 0 ) then
504  r2 = i
505  exit for
506  end if
507  next
508 
509  swap this_->stkctx.regTB(r1), this_->stkctx.regTB(r2)
510 
511 end sub
512 
513 '':::::
514 function sregFindFreeReg _
515  ( _
516  byval this_ as REGCLASS ptr _
517  ) as integer Static
518 
519  dim as integer r
520 
521  function = INVALID
522 
523  if( this_->stkctx.fregs = 0 ) then
524  exit function
525  end if
526 
527  for r = 0 to this_->regs - 1
528  if( this_->stkctx.regTB(r) = INVALID ) then
529  return r
530  end If
531  next
532 
533 end function
534 
535 '':::::
536 function sregFindLowestReg _
537  ( _
538  byval this_ as REGCLASS ptr _
539  ) as integer Static
540 
541  dim as integer r, i, lowest
542 
543  i = INVALID
544  lowest = -32768
545 
546  for r = 0 to this_->regs - 1
547  if( this_->stkctx.regTB(r) <> INVALID ) then
548  if( this_->stkctx.regTB(r) > lowest ) then
549  lowest = this_->stkctx.regTB(r)
550  i = r
551  end if
552  end If
553  next
554 
555  function = i
556 
557 end function
558 
559 '':::::
560 function sregFindTOSReg _
561  ( _
562  byval this_ as REGCLASS ptr _
563  ) as integer Static
564 
565  dim as integer r
566 
567  for r = 0 to this_->regs - 1
568  if( this_->stkctx.regTB(r) = 0 ) then
569  return r
570  end If
571  next
572 
573  function = INVALID
574 
575 end function
576 
577 function sregAllocate _
578  ( _
579  byval this_ as REGCLASS ptr, _
580  byval vreg as IRVREG ptr, _
581  byval vauxparent as IRVREG ptr, _
582  byval size as uinteger _ '' unused
583  ) as integer
584 
585  dim as integer r = any
586 
587  r = sregFindFreeReg( this_ )
588  if( r = INVALID ) then
589  r = sregFindTOSReg( this_ )
590  '' This will sregFree() the register
591  irStoreVR( this_->vregTB(r), this_->vauxparent(r) )
592  else
593  this_->stkctx.fregs -= 1
594 
595  for i as integer = 0 to this_->regs - 1
596  if( this_->stkctx.regTB(i) <> INVALID ) then
597  this_->stkctx.regTB(i) += 1
598  end If
599  next
600  end If
601 
602  this_->vregTB(r) = vreg
603  this_->vauxparent(r) = vauxparent
604  this_->stkctx.regTB(r) = 0
605 
606  function = r
607 end function
608 
609 function sregAllocateReg _
610  ( _
611  byval this_ as REGCLASS ptr, _
612  byval r as integer, _
613  byval vreg as IRVREG ptr, _
614  byval vauxparent as IRVREG ptr _
615  ) as integer
616 
617  '' assuming r will be always 0 (result, TOS)
618  function = sregAllocate( this_, vreg, vauxparent, REG_SIZEMASK_64 )
619 
620 end function
621 
622 function sregEnsure _
623  ( _
624  byval this_ as REGCLASS ptr, _
625  byval vreg as IRVREG ptr, _
626  byval vauxparent as IRVREG ptr, _
627  byval size as uinteger _ '' unused
628  ) as integer
629 
630  dim as integer r = any
631 
632  r = sregFindReg( this_, vreg )
633  if( r = INVALID ) then
634  r = sregAllocate( this_, vreg, vauxparent, REG_SIZEMASK_64 )
635  irLoadVR( r, vreg, vauxparent )
636  else
637  assert( vreg->reg = r )
638  if( this_->stkctx.regTB(r) <> 0 ) then
639  sregXchg( this_, r )
640  end if
641  end if
642 
643  function = r
644 end function
645 
646 sub sregFree _
647  ( _
648  byval this_ as REGCLASS ptr, _
649  byval r as integer _
650  )
651 
652  dim as integer i, realreg
653 
654  if( this_->stkctx.regTB(r) = INVALID ) then
655  exit sub
656  end if
657 
658  realreg = this_->stkctx.regTB(r)
659  this_->stkctx.regTB(r) = INVALID
660  this_->vregTB(r) = NULL
661  this_->vauxparent(r) = NULL
662 
663  for i = 0 to this_->regs - 1
664  if( this_->stkctx.regTB(i) <> INVALID ) then
665  if( this_->stkctx.regTB(i) > realreg ) then
666  this_->stkctx.regTB(i) -= 1
667  end if
668  end If
669  next
670 
671  this_->stkctx.fregs += 1
672 
673 end sub
674 
675 '':::::
676 function sregIsFree _
677  ( _
678  byval this_ as REGCLASS ptr, _
679  byval r as integer _
680  ) as integer static
681 
682  function = this_->stkctx.regTB(r) = INVALID
683 
684 end function
685 
686 '':::::
687 sub sregSetOwner _
688  ( _
689  byval this_ as REGCLASS ptr, _
690  byval r as integer, _
691  byval vreg as IRVREG ptr, _
692  byval vauxparent as IRVREG ptr _
693  )
694 
695  this_->vregTB(r) = vreg
696  this_->vauxparent(r) = vauxparent
697 
698 end sub
699 
700 '':::::
701 function sregGetRealReg _
702  ( _
703  byval this_ as REGCLASS ptr, _
704  byval r as integer _
705  ) as integer static
706 
707  function = this_->stkctx.regTB(r)
708 
709 end function
710 
711 '':::::
712 function sregGetMaxRegs _
713  ( _
714  byval this_ as REGCLASS ptr _
715  ) as integer static
716 
717  function = this_->regs
718 
719 end function
720 
721 '':::::
722 function sregGetFirst _
723  ( _
724  byval this_ as REGCLASS ptr _
725  ) as integer static
726 
727  function = sregFindTOSReg( this_ )
728 
729 end function
730 
731 '':::::
732 function sregGetNext _
733  ( _
734  byval this_ as REGCLASS ptr, _
735  byval r as integer _
736  ) as integer static
737 
738  if( (r < 0) or (r >= this_->regs) ) then
739  function = INVALID
740  else
741  function = sregFindTOSReg( this_ )
742  end if
743 
744 end function
745 
746 '':::::
747 function sregGetVreg _
748  ( _
749  byval this_ as REGCLASS ptr, _
750  byval r as integer, _
751  byref vauxparent as IRVREG ptr _
752  ) as IRVREG ptr
753 
754  function = this_->vregTB(r)
755  vauxparent = this_->vauxparent(r)
756 
757 end function
758 
759 '':::::
760 sub sregDump _
761  ( _
762  byval this_ as REGCLASS ptr _
763  )
764 #if 0
765  dim as integer i, cnt
766 
767  cnt = 0
768  for i = 0 to this_->regs - 1
769  if( this_->stkctx.regTB(i) <> INVALID ) then
770  print i;
771  cnt += 1
772  end If
773  next
774 
775  if( cnt > 0 ) then print
776 #endif
777 end sub
778 
779 '':::::
780 sub sregClear _
781  ( _
782  byval reg as REGCLASS ptr _
783  )
784 
785  dim as integer r = any
786 
787  reg->stkctx.fregs = reg->regs
788 
789  for r = 0 to reg->regs - 1
790  reg->stkctx.regTB(r) = INVALID
791  reg->vregTB(r) = NULL
792  reg->vauxparent(r) = NULL
793  next
794 
795 end sub
796 
797 '':::::
798 sub sregInitClass _
799  ( _
800  byval this_ as REGCLASS ptr, _
801  sizeTb() as REG_SIZEMASK _
802  )
803 
804  '' sizeTb() is unused (x86 assumption)
805 
806  sregClear( this_ )
807 
808  this_->ensure = @sregEnsure
809  this_->_allocate = @sregAllocate
810  this_->allocateReg = @sregAllocateReg
811  this_->free = @sregFree
812  this_->isFree = @sregIsFree
813  this_->setOwner = @sregSetOwner
814  this_->getMaxRegs = @sregGetMaxRegs
815  this_->getFirst = @sregGetFirst
816  this_->getNext = @sregGetNext
817  this_->getVreg = @sregGetVreg
818  this_->getRealReg = @sregGetRealReg
819  this_->clear = @sregClear
820  this_->dump = @sregDump
821 
822 end sub
823