mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 12:00:11 -05:00
408 lines
10 KiB
Modula-2
408 lines
10 KiB
Modula-2
(* M2BasicBlock.mod converts a scope block into a list of basic blocks.
|
|
|
|
Copyright (C) 2001-2026 Free Software Foundation, Inc.
|
|
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
|
|
|
|
This file is part of GNU Modula-2.
|
|
|
|
GNU Modula-2 is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
any later version.
|
|
|
|
GNU Modula-2 is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GNU Modula-2; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. *)
|
|
|
|
IMPLEMENTATION MODULE M2BasicBlock ;
|
|
|
|
|
|
FROM Storage IMPORT ALLOCATE, DEALLOCATE ;
|
|
FROM StrIO IMPORT WriteString, WriteLn ;
|
|
FROM NumberIO IMPORT WriteCard ;
|
|
FROM M2Debug IMPORT Assert ;
|
|
FROM M2Options IMPORT OptimizeBasicBlock ;
|
|
|
|
FROM M2Quads IMPORT IsReferenced, IsConditional, IsUnConditional, IsCall,
|
|
IsReturn, IsNewLocalVar, IsKillLocalVar,
|
|
IsCatchBegin, IsCatchEnd,
|
|
IsInitStart, IsInitEnd, IsFinallyStart, IsFinallyEnd,
|
|
IsInitialisingConst, IsConditionalBooleanQuad,
|
|
IsPseudoQuad, IsDefOrModFile,
|
|
GetNextQuad, GetQuad, QuadOperator,
|
|
SubQuad, DisplayQuadRange ;
|
|
|
|
FROM M2Scope IMPORT ScopeBlock, ForeachScopeBlockDo3 ;
|
|
|
|
|
|
CONST
|
|
Debugging = FALSE ;
|
|
|
|
TYPE
|
|
BasicBlock = POINTER TO RECORD
|
|
Scope : CARDINAL ; (* Scope associated with the block. *)
|
|
StartQuad : CARDINAL ; (* First Quad in Basic Block. *)
|
|
EndQuad : CARDINAL ; (* End Quad in Basic Block. *)
|
|
First : BOOLEAN ; (* The first block? *)
|
|
Right : BasicBlock ;
|
|
Left : BasicBlock ;
|
|
END ;
|
|
|
|
VAR
|
|
FreeList : BasicBlock ; (* Free list of Basic Blocks *)
|
|
HeadOfBasicBlock: BasicBlock ;
|
|
|
|
|
|
PROCEDURE stop ;
|
|
END stop ;
|
|
|
|
|
|
(*
|
|
InitBasicBlocks - converts a list of quadruples as defined by
|
|
scope blocks into a set of basic blocks.
|
|
All quadruples within this list which are not
|
|
reachable are removed.
|
|
*)
|
|
|
|
PROCEDURE InitBasicBlocks (sb: ScopeBlock) : BasicBlock ;
|
|
BEGIN
|
|
HeadOfBasicBlock := NIL ;
|
|
ForeachScopeBlockDo3 (sb, ConvertQuads2BasicBlock) ;
|
|
RETURN HeadOfBasicBlock
|
|
END InitBasicBlocks ;
|
|
|
|
|
|
(*
|
|
InitBasicBlocksFromRange - converts a list of quadruples as defined by
|
|
start..end.
|
|
All quadruples within this list which are not
|
|
reachable are removed.
|
|
*)
|
|
|
|
PROCEDURE InitBasicBlocksFromRange (ScopeSym: CARDINAL;
|
|
start, end: CARDINAL) : BasicBlock ;
|
|
BEGIN
|
|
HeadOfBasicBlock := NIL ;
|
|
ConvertQuads2BasicBlock (ScopeSym, start, end) ;
|
|
IF Debugging
|
|
THEN
|
|
DisplayBasicBlocks (HeadOfBasicBlock)
|
|
END ;
|
|
RETURN( HeadOfBasicBlock )
|
|
END InitBasicBlocksFromRange ;
|
|
|
|
|
|
(*
|
|
KillBasicBlocks - destroys the list of Basic Blocks.
|
|
*)
|
|
|
|
PROCEDURE KillBasicBlocks (VAR bb: BasicBlock) ;
|
|
BEGIN
|
|
FreeBasicBlocks (bb) ;
|
|
bb := NIL
|
|
END KillBasicBlocks ;
|
|
|
|
|
|
(*
|
|
FreeBasicBlocks - destroys the list of Basic Blocks.
|
|
*)
|
|
|
|
PROCEDURE FreeBasicBlocks (bb: BasicBlock) ;
|
|
VAR
|
|
b, c: BasicBlock ;
|
|
BEGIN
|
|
IF bb#NIL
|
|
THEN
|
|
b := bb ;
|
|
REPEAT
|
|
c := bb^.Right ;
|
|
bb^.Right := FreeList ;
|
|
FreeList := bb ;
|
|
bb := c
|
|
UNTIL bb=b
|
|
END
|
|
END FreeBasicBlocks ;
|
|
|
|
|
|
(*
|
|
New - returns a basic block.
|
|
*)
|
|
|
|
PROCEDURE New (Scope: CARDINAL; First: BOOLEAN) : BasicBlock ;
|
|
VAR
|
|
b: BasicBlock ;
|
|
BEGIN
|
|
IF FreeList=NIL
|
|
THEN
|
|
NEW (b)
|
|
ELSE
|
|
b := FreeList ;
|
|
FreeList := FreeList^.Right
|
|
END ;
|
|
Assert (b#NIL) ;
|
|
b^.Scope := Scope ;
|
|
b^.First := First ;
|
|
RETURN b
|
|
END New ;
|
|
|
|
|
|
(*
|
|
ConvertQuads2BasicBlock - converts a list of quadruples to a list of
|
|
Basic Blocks.
|
|
A Basic Block is defined as a list of quadruples
|
|
which has only has one entry and exit point.
|
|
*)
|
|
|
|
PROCEDURE ConvertQuads2BasicBlock (ScopeSym: CARDINAL; Start, End: CARDINAL) ;
|
|
VAR
|
|
First,
|
|
LastQuadDefMod,
|
|
LastQuadConditional,
|
|
LastQuadCall,
|
|
LastQuadReturn : BOOLEAN ;
|
|
Quad : CARDINAL ;
|
|
CurrentBB : BasicBlock ;
|
|
LastBB : BasicBlock ;
|
|
BEGIN
|
|
IF Debugging
|
|
THEN
|
|
WriteString ("Enter ConvertQuads2BasicBlock") ; WriteLn ;
|
|
DisplayQuadRange (ScopeSym, Start, End)
|
|
END ;
|
|
(*
|
|
Algorithm to perform Basic Block:
|
|
|
|
For every quadruple establish a set of leaders.
|
|
A leader is defined as a quadruple which is
|
|
either:
|
|
|
|
(i) The first quadruple.
|
|
(ii) Any quadruple which is the target of a jump or unconditional jump.
|
|
(iii) Any statement which follows a conditional jump
|
|
|
|
For each leader construct a basic block.
|
|
A Basic Block starts with a leader quadruple and ends with either:
|
|
|
|
(i) Another leader
|
|
(ii) An unconditional Jump.
|
|
|
|
Any quadruples that do not fall into a Basic Block can be thrown away
|
|
since they will never be executed.
|
|
*)
|
|
LastBB := NIL ;
|
|
CurrentBB := NIL ;
|
|
Quad := Start ;
|
|
LastQuadConditional := TRUE ; (* Force Rule (i). *)
|
|
LastQuadCall := FALSE ;
|
|
LastQuadReturn := FALSE ;
|
|
LastQuadDefMod := FALSE ;
|
|
First := TRUE ;
|
|
(* Scan all quadruples. *)
|
|
WHILE (Quad<=End) AND (Quad#0) DO
|
|
IF Quad = 200
|
|
THEN
|
|
stop
|
|
END ;
|
|
IF LastQuadConditional OR LastQuadCall OR LastQuadReturn OR
|
|
LastQuadDefMod OR IsReferenced(Quad)
|
|
THEN
|
|
(* Rule (ii) *)
|
|
CurrentBB := New (ScopeSym, First) ; (* Get a new Basic Block. *)
|
|
(* At least one quad in this Basic Block. *)
|
|
StartBB(CurrentBB, Quad) ;
|
|
EndBB(CurrentBB, Quad) ;
|
|
First := FALSE
|
|
ELSIF CurrentBB#NIL
|
|
THEN
|
|
(* We have a Basic Block - therefore add quad to this Block *)
|
|
EndBB(CurrentBB, Quad)
|
|
ELSIF IsPseudoQuad(Quad)
|
|
THEN
|
|
(* Add Quad to the Last BB since Pseudo Quads - compiler directives *)
|
|
(* must not be thrown away. *)
|
|
EndBB(LastBB, Quad)
|
|
ELSIF IsReturn(Quad) OR IsKillLocalVar(Quad) OR
|
|
IsCatchEnd(Quad) OR IsCatchBegin(Quad) OR
|
|
IsInitStart(Quad) OR IsInitEnd(Quad) OR
|
|
IsFinallyStart(Quad) OR IsFinallyEnd(Quad)
|
|
THEN
|
|
(* We must leave these quads alone. *)
|
|
EndBB(LastBB, Quad)
|
|
ELSIF IsConditionalBooleanQuad (Quad)
|
|
THEN
|
|
(* We can remove unreachable const quads. *)
|
|
SubQuad (Quad)
|
|
(*
|
|
ELSIF IsInitialisingConst(Quad)
|
|
THEN
|
|
(* But we leave remaining constant quads alone. *)
|
|
EndBB(LastBB, Quad)
|
|
*)
|
|
ELSE
|
|
(* Remove this Quad since it will never be reached. *)
|
|
SubQuad(Quad)
|
|
END ;
|
|
LastQuadConditional := IsConditional(Quad) ;
|
|
LastQuadCall := IsCall(Quad) ;
|
|
LastQuadReturn := IsReturn(Quad) ;
|
|
LastQuadDefMod := IsDefOrModFile(Quad) ;
|
|
IF IsUnConditional(Quad)
|
|
THEN
|
|
LastBB := CurrentBB ;
|
|
CurrentBB := NIL
|
|
END ;
|
|
Quad := GetNextQuad(Quad)
|
|
END ;
|
|
IF Debugging
|
|
THEN
|
|
WriteString ("Exit ConvertQuads2BasicBlock") ; WriteLn ;
|
|
DisplayQuadRange (ScopeSym, Start, End)
|
|
END
|
|
END ConvertQuads2BasicBlock ;
|
|
|
|
|
|
(*
|
|
ForeachBasicBlockDo - for each basic block call procedure p.
|
|
*)
|
|
|
|
PROCEDURE ForeachBasicBlockDo (bb: BasicBlock; p: BasicBlockProc) ;
|
|
VAR
|
|
b: BasicBlock ;
|
|
BEGIN
|
|
IF bb#NIL
|
|
THEN
|
|
b := bb ;
|
|
REPEAT
|
|
WITH b^ DO
|
|
p (b)
|
|
END ;
|
|
b := b^.Right
|
|
UNTIL b=bb
|
|
END
|
|
END ForeachBasicBlockDo ;
|
|
|
|
|
|
(*
|
|
StartBB - Initially fills a Basic Block, b, with a start quad Quad.
|
|
The Basic Block is then added to the end of Basic Block list.
|
|
*)
|
|
|
|
PROCEDURE StartBB (b: BasicBlock; Quad: CARDINAL) ;
|
|
BEGIN
|
|
WITH b^ DO
|
|
StartQuad := Quad ;
|
|
EndQuad := Quad
|
|
END ;
|
|
Add(HeadOfBasicBlock, b) (* Add b to the end of the Basic Block list *)
|
|
END StartBB ;
|
|
|
|
|
|
(*
|
|
EndBB - Fills a Basic Block, b, with an end quad Quad.
|
|
*)
|
|
|
|
PROCEDURE EndBB (b: BasicBlock; Quad: CARDINAL) ;
|
|
BEGIN
|
|
b^.EndQuad := Quad
|
|
END EndBB ;
|
|
|
|
|
|
(*
|
|
Add adds a specified element to the end of a queue.
|
|
*)
|
|
|
|
PROCEDURE Add (VAR Head: BasicBlock;
|
|
b : BasicBlock) ;
|
|
BEGIN
|
|
IF Head=NIL
|
|
THEN
|
|
Head := b ;
|
|
b^.Left := b ;
|
|
b^.Right := b
|
|
ELSE
|
|
b^.Right := Head ;
|
|
b^.Left := Head^.Left ;
|
|
Head^.Left^.Right := b ;
|
|
Head^.Left := b
|
|
END
|
|
END Add ;
|
|
|
|
|
|
(*
|
|
DisplayBasicBlocks - displays the basic block data structure.
|
|
*)
|
|
|
|
PROCEDURE DisplayBasicBlocks (bb: BasicBlock) ;
|
|
VAR
|
|
b: BasicBlock ;
|
|
BEGIN
|
|
b := bb ;
|
|
WriteString('quadruples') ; WriteLn ;
|
|
IF b#NIL
|
|
THEN
|
|
REPEAT
|
|
DisplayBlock(b) ;
|
|
b := b^.Right
|
|
UNTIL b=bb
|
|
END
|
|
END DisplayBasicBlocks ;
|
|
|
|
|
|
PROCEDURE DisplayBlock (b: BasicBlock) ;
|
|
BEGIN
|
|
WITH b^ DO
|
|
WriteString(' start ') ; WriteCard(StartQuad, 6) ;
|
|
WriteString(' end ') ; WriteCard(EndQuad, 6) ;
|
|
END
|
|
END DisplayBlock ;
|
|
|
|
|
|
(*
|
|
GetBasicBlockScope - return the scope associated with the basic block.
|
|
*)
|
|
|
|
PROCEDURE GetBasicBlockScope (bb: BasicBlock) : CARDINAL ;
|
|
BEGIN
|
|
RETURN bb^.Scope
|
|
END GetBasicBlockScope ;
|
|
|
|
|
|
(*
|
|
GetBasicBlockStart - return the quad associated with the start of the basic block.
|
|
*)
|
|
|
|
PROCEDURE GetBasicBlockStart (bb: BasicBlock) : CARDINAL ;
|
|
BEGIN
|
|
RETURN bb^.StartQuad
|
|
END GetBasicBlockStart ;
|
|
|
|
|
|
(*
|
|
GetBasicBlockEnd - return the quad associated with the end of the basic block.
|
|
*)
|
|
|
|
PROCEDURE GetBasicBlockEnd (bb: BasicBlock) : CARDINAL ;
|
|
BEGIN
|
|
RETURN bb^.EndQuad
|
|
END GetBasicBlockEnd ;
|
|
|
|
|
|
(*
|
|
IsBasicBlockFirst - return TRUE if this basic block is the first in the sequence.
|
|
*)
|
|
|
|
PROCEDURE IsBasicBlockFirst (bb: BasicBlock) : BOOLEAN ;
|
|
BEGIN
|
|
RETURN bb^.First
|
|
END IsBasicBlockFirst ;
|
|
|
|
|
|
BEGIN
|
|
FreeList := NIL
|
|
END M2BasicBlock.
|