|
@@ -239,225 +239,6 @@ TYPE
|
|
|
END QuickSort;
|
|
|
END List;
|
|
|
|
|
|
- IntegerList* = OBJECT
|
|
|
- VAR list: IntegerArray;
|
|
|
- count-: LONGINT;
|
|
|
-
|
|
|
- PROCEDURE & InitList*(initialSize: LONGINT) ;
|
|
|
- BEGIN
|
|
|
- INC( lists ); NEW( list, initialSize ); count := 0;
|
|
|
- END InitList;
|
|
|
-
|
|
|
- PROCEDURE Length*( ): LONGINT;
|
|
|
- BEGIN RETURN count END Length;
|
|
|
-
|
|
|
- PROCEDURE Grow;
|
|
|
- VAR old: IntegerArray; i: LONGINT;
|
|
|
- BEGIN
|
|
|
- INC( enlarged ); old := list; NEW( list, LEN( list ) * 4 );
|
|
|
- FOR i := 0 TO count - 1 DO list[i] := old[i] END
|
|
|
- END Grow;
|
|
|
-
|
|
|
- PROCEDURE Get*( i: LONGINT ): LONGINT;
|
|
|
- BEGIN
|
|
|
- IF (i < 0) OR (i >= count) THEN HALT( 101 ) END;
|
|
|
- RETURN list[i]
|
|
|
- END Get;
|
|
|
-
|
|
|
- PROCEDURE Set*(i: LONGINT; x: LONGINT);
|
|
|
- BEGIN
|
|
|
- IF (i < 0) OR (i >= count) THEN HALT( 101 ) END;
|
|
|
- list[i] := x;
|
|
|
- END Set;
|
|
|
-
|
|
|
- PROCEDURE Add*( x: LONGINT );
|
|
|
- BEGIN
|
|
|
- IF count = LEN( list ) THEN Grow END;
|
|
|
- list[count] := x; INC( count )
|
|
|
- END Add;
|
|
|
-
|
|
|
- PROCEDURE Prepend*(x: LONGINT);
|
|
|
- VAR i: LONGINT;
|
|
|
- BEGIN
|
|
|
- IF count = LEN( list ) THEN Grow END;
|
|
|
-
|
|
|
- FOR i := count-1 TO 0 BY - 1 DO
|
|
|
- list[i+1] := list[i];
|
|
|
- END;
|
|
|
- list[0] := x; INC(count);
|
|
|
- END Prepend;
|
|
|
-
|
|
|
- PROCEDURE Append*(x: IntegerList);
|
|
|
- VAR i: LONGINT;
|
|
|
- BEGIN
|
|
|
- FOR i := 0 TO x.Length() - 1 DO
|
|
|
- Add(x.Get(i));
|
|
|
- END;
|
|
|
- END Append;
|
|
|
-
|
|
|
- PROCEDURE Remove*( x: LONGINT );
|
|
|
- VAR i: LONGINT;
|
|
|
- BEGIN
|
|
|
- i := 0;
|
|
|
- WHILE (i < count) & (list[i] # x) DO INC( i ) END;
|
|
|
- IF i < count THEN
|
|
|
- WHILE (i < count - 1) DO list[i] := list[i + 1]; INC( i ) END;
|
|
|
- DEC( count );
|
|
|
- END
|
|
|
- END Remove;
|
|
|
-
|
|
|
- PROCEDURE RemoveByIndex*( i: LONGINT );
|
|
|
- BEGIN
|
|
|
- IF i < count THEN
|
|
|
- WHILE (i < count - 1) DO list[i] := list[i + 1]; INC( i ) END;
|
|
|
- DEC( count );
|
|
|
- END
|
|
|
- END RemoveByIndex;
|
|
|
-
|
|
|
- PROCEDURE Insert*( i,x: LONGINT);
|
|
|
- VAR j: LONGINT;
|
|
|
- BEGIN
|
|
|
- ASSERT((i >= 0) & (i < count));
|
|
|
-
|
|
|
- IF count = LEN( list ) THEN Grow END; INC( count );
|
|
|
-
|
|
|
- j := count - 2;
|
|
|
- WHILE (j >= i) DO list[j+1] := list[j]; DEC( j ) END;
|
|
|
- list[i] := x;
|
|
|
- END Insert;
|
|
|
-
|
|
|
- PROCEDURE Replace*( x, y: LONGINT );
|
|
|
- VAR i: LONGINT;
|
|
|
- BEGIN
|
|
|
- i := IndexOf( x );
|
|
|
- IF i >= 0 THEN list[i] := y END
|
|
|
- END Replace;
|
|
|
-
|
|
|
- PROCEDURE IndexOf*( x: LONGINT ): LONGINT;
|
|
|
- VAR i: LONGINT;
|
|
|
- BEGIN
|
|
|
- i := 0;
|
|
|
- WHILE i < count DO
|
|
|
- IF list[i] = x THEN RETURN i END;
|
|
|
- INC( i )
|
|
|
- END;
|
|
|
- RETURN -1
|
|
|
- END IndexOf;
|
|
|
-
|
|
|
- PROCEDURE Contains*( x: LONGINT ): BOOLEAN;
|
|
|
- BEGIN RETURN IndexOf( x ) # -1; END Contains;
|
|
|
-
|
|
|
- PROCEDURE Clear*;
|
|
|
- BEGIN count := 0 END Clear;
|
|
|
-
|
|
|
- END IntegerList;
|
|
|
-
|
|
|
- (* Supports get, add, contain, append in O(1) *)
|
|
|
- Bag* = OBJECT
|
|
|
- VAR
|
|
|
- count-: LONGINT;
|
|
|
- list: List;
|
|
|
-
|
|
|
- PROCEDURE & InitBag* ;
|
|
|
- BEGIN
|
|
|
- Clear();
|
|
|
- END InitBag;
|
|
|
-
|
|
|
- PROCEDURE Length*( ): LONGINT;
|
|
|
- BEGIN
|
|
|
- RETURN list.Length();
|
|
|
- END Length;
|
|
|
-
|
|
|
- PROCEDURE Get*( i: LONGINT ): ANY;
|
|
|
- BEGIN RETURN list.Get(i); END Get;
|
|
|
-
|
|
|
- PROCEDURE Add*( x: ANY );
|
|
|
- BEGIN
|
|
|
- ASSERT( x # NIL );
|
|
|
- IF ~Contains(x) THEN
|
|
|
- list.Add(x);
|
|
|
- END;
|
|
|
- END Add;
|
|
|
-
|
|
|
- PROCEDURE Append*(x: Bag);
|
|
|
- VAR i: LONGINT;
|
|
|
- BEGIN
|
|
|
- FOR i := 0 TO x.Length() - 1 DO
|
|
|
- IF ~Contains(x.Get(i)) THEN
|
|
|
- Add(x.Get(i));
|
|
|
- END;
|
|
|
- END;
|
|
|
- END Append;
|
|
|
-
|
|
|
- PROCEDURE Remove*( x: ANY );
|
|
|
- BEGIN
|
|
|
- list.Remove(x);
|
|
|
- END Remove;
|
|
|
-
|
|
|
- PROCEDURE Contains*( x: ANY ): BOOLEAN;
|
|
|
- BEGIN RETURN list.Contains(x); END Contains;
|
|
|
-
|
|
|
- PROCEDURE Clear*;
|
|
|
- BEGIN
|
|
|
- count := 0;
|
|
|
- NEW(list,InitListSize);
|
|
|
- list.multipleAllowed := TRUE; list.nilAllowed := TRUE;
|
|
|
- END Clear;
|
|
|
-
|
|
|
- END Bag;
|
|
|
-
|
|
|
- (* Supports get, add, contain, append in O(1) *)
|
|
|
- IntegerBag* = OBJECT
|
|
|
- VAR
|
|
|
- count-: LONGINT;
|
|
|
- list: IntegerList;
|
|
|
-
|
|
|
- PROCEDURE & InitBag* ;
|
|
|
- BEGIN
|
|
|
- Clear();
|
|
|
- END InitBag;
|
|
|
-
|
|
|
- PROCEDURE Length*( ): LONGINT;
|
|
|
- BEGIN
|
|
|
- RETURN list.Length();
|
|
|
- END Length;
|
|
|
-
|
|
|
- PROCEDURE Get*( i: LONGINT ):LONGINT;
|
|
|
- BEGIN RETURN list.Get(i); END Get;
|
|
|
-
|
|
|
- PROCEDURE Add*( x: LONGINT );
|
|
|
- BEGIN
|
|
|
- IF ~Contains(x) THEN
|
|
|
- list.Add(x);
|
|
|
- END;
|
|
|
- END Add;
|
|
|
-
|
|
|
- PROCEDURE Append*(x: IntegerBag);
|
|
|
- VAR i: LONGINT;
|
|
|
- BEGIN
|
|
|
- FOR i := 0 TO x.Length() - 1 DO
|
|
|
- IF ~Contains(x.Get(i)) THEN
|
|
|
- Add(x.Get(i));
|
|
|
- END;
|
|
|
- END;
|
|
|
- END Append;
|
|
|
-
|
|
|
- PROCEDURE Remove*(x: LONGINT );
|
|
|
- BEGIN
|
|
|
- list.Remove(x);
|
|
|
- END Remove;
|
|
|
-
|
|
|
- PROCEDURE Contains*( x: LONGINT ): BOOLEAN;
|
|
|
- BEGIN RETURN list.Contains(x); END Contains;
|
|
|
-
|
|
|
- PROCEDURE Clear*;
|
|
|
- BEGIN
|
|
|
- count := 0;
|
|
|
- NEW(list,InitListSize);
|
|
|
- END Clear;
|
|
|
-
|
|
|
- END IntegerBag;
|
|
|
-
|
|
|
HashEntryAny = RECORD
|
|
|
key, value: ANY;
|
|
|
valueInt: LONGINT;
|
|
@@ -816,609 +597,6 @@ TYPE
|
|
|
|
|
|
END HashTableSegmentedName;
|
|
|
|
|
|
- (* Hash table supporting 2 keys *)
|
|
|
- HashTable2D* = OBJECT(HashTable);
|
|
|
- VAR
|
|
|
- initialSize: LONGINT;
|
|
|
-
|
|
|
- (* Interface *)
|
|
|
-
|
|
|
- PROCEDURE & Init* (initialSize: LONGINT);
|
|
|
- BEGIN
|
|
|
- Init^(initialSize);
|
|
|
- SELF.initialSize := initialSize;
|
|
|
- END Init;
|
|
|
-
|
|
|
- PROCEDURE Get2D*(key1, key2: ANY):ANY;
|
|
|
- VAR
|
|
|
- any: ANY;
|
|
|
- second: HashTable;
|
|
|
- BEGIN
|
|
|
- any := Get(key1);
|
|
|
- second := any(HashTable);
|
|
|
- RETURN second.Get(key2);
|
|
|
- END Get2D;
|
|
|
-
|
|
|
- PROCEDURE Put2D*(key1, key2, value: ANY);
|
|
|
- VAR
|
|
|
- any: ANY;
|
|
|
- second: HashTable;
|
|
|
- BEGIN
|
|
|
- IF ~Has(key1) THEN
|
|
|
- NEW(second, initialSize);
|
|
|
- Put(key1, second);
|
|
|
- ELSE
|
|
|
- any := Get(key1);
|
|
|
- second := any(HashTable);
|
|
|
- END;
|
|
|
- second.Put(key2, value);
|
|
|
- END Put2D;
|
|
|
-
|
|
|
- PROCEDURE Has2D*(key1, key2: ANY):BOOLEAN;
|
|
|
- VAR
|
|
|
- any: ANY;
|
|
|
- second: HashTable;
|
|
|
- BEGIN
|
|
|
- IF ~Has(key1) THEN RETURN FALSE; END;
|
|
|
- any := Get(key1);
|
|
|
- second := any(HashTable);
|
|
|
- RETURN second.Has(key2);
|
|
|
- END Has2D;
|
|
|
-
|
|
|
- END HashTable2D;
|
|
|
-
|
|
|
- (* Data structure implementing a stack using lists *)
|
|
|
- Stack* = OBJECT
|
|
|
- VAR
|
|
|
- list: List;
|
|
|
-
|
|
|
- PROCEDURE & Init*;
|
|
|
- BEGIN NEW(list,InitListSize); END Init;
|
|
|
-
|
|
|
- (* Push on top of stack *)
|
|
|
- PROCEDURE Push*(x: ANY);
|
|
|
- BEGIN list.Add(x); END Push;
|
|
|
-
|
|
|
- (* Get top element *)
|
|
|
- PROCEDURE Peek*():ANY;
|
|
|
- BEGIN RETURN list.Get(list.Length() - 1); END Peek;
|
|
|
-
|
|
|
- (* Get and remove top element *)
|
|
|
- PROCEDURE Pop*():ANY;
|
|
|
- VAR old: ANY;
|
|
|
- BEGIN
|
|
|
- old := Peek();
|
|
|
- RemoveTop();
|
|
|
- RETURN old;
|
|
|
- END Pop;
|
|
|
-
|
|
|
- (* Remove top element without reading it *)
|
|
|
- PROCEDURE RemoveTop*;
|
|
|
- BEGIN list.RemoveByIndex(list.Length() - 1); END RemoveTop;
|
|
|
-
|
|
|
- (* Check if empty *)
|
|
|
- PROCEDURE Empty*():BOOLEAN;
|
|
|
- BEGIN RETURN list.Length() = 0; END Empty;
|
|
|
-
|
|
|
- PROCEDURE Length*():LONGINT;
|
|
|
- BEGIN RETURN list.count; END Length;
|
|
|
-
|
|
|
- END Stack;
|
|
|
-
|
|
|
- (* Data structure implementing a stack using lists *)
|
|
|
- IntegerStack* = OBJECT
|
|
|
- VAR
|
|
|
- list: IntegerList;
|
|
|
-
|
|
|
- PROCEDURE & Init*;
|
|
|
- BEGIN NEW(list,InitListSize); END Init;
|
|
|
-
|
|
|
- (* Push on top of stack *)
|
|
|
- PROCEDURE Push*(x: LONGINT);
|
|
|
- BEGIN list.Add(x); END Push;
|
|
|
-
|
|
|
- (* Get top element *)
|
|
|
- PROCEDURE Peek*():LONGINT;
|
|
|
- BEGIN RETURN list.Get(list.Length() - 1); END Peek;
|
|
|
-
|
|
|
- (* Get and remove top element *)
|
|
|
- PROCEDURE Pop*():LONGINT;
|
|
|
- VAR old: LONGINT;
|
|
|
- BEGIN
|
|
|
- old := Peek();
|
|
|
- RemoveTop();
|
|
|
- RETURN old;
|
|
|
- END Pop;
|
|
|
-
|
|
|
- (* Remove top element without reading it *)
|
|
|
- PROCEDURE RemoveTop*;
|
|
|
- BEGIN list.RemoveByIndex(list.Length() - 1); END RemoveTop;
|
|
|
-
|
|
|
- (* Check if empty *)
|
|
|
- PROCEDURE Empty*():BOOLEAN;
|
|
|
- BEGIN RETURN list.Length() = 0; END Empty;
|
|
|
-
|
|
|
- PROCEDURE Length*():LONGINT;
|
|
|
- BEGIN RETURN list.count; END Length;
|
|
|
-
|
|
|
- END IntegerStack;
|
|
|
-
|
|
|
- QueueEntry = POINTER TO RECORD
|
|
|
- value: ANY;
|
|
|
- next: QueueEntry;
|
|
|
- END;
|
|
|
-
|
|
|
- Queue* = OBJECT
|
|
|
- VAR
|
|
|
- top, last: QueueEntry;
|
|
|
-
|
|
|
- PROCEDURE & Init *;
|
|
|
- BEGIN
|
|
|
- top := NIL; last := NIL;
|
|
|
- END Init;
|
|
|
-
|
|
|
- (* Add to end of queue *)
|
|
|
- PROCEDURE Append*(x: ANY);
|
|
|
- VAR entry: QueueEntry;
|
|
|
- BEGIN
|
|
|
- NEW(entry);
|
|
|
- entry.value := x;
|
|
|
-
|
|
|
- IF top = NIL THEN
|
|
|
- top := entry;
|
|
|
- ELSE
|
|
|
- last.next := entry;
|
|
|
- END;
|
|
|
-
|
|
|
- last := entry;
|
|
|
- END Append;
|
|
|
-
|
|
|
- (* Get top element *)
|
|
|
- PROCEDURE Peek*():ANY;
|
|
|
- BEGIN
|
|
|
- RETURN top.value;
|
|
|
- END Peek;
|
|
|
-
|
|
|
- (* Get and remove top element *)
|
|
|
- PROCEDURE Pop*():ANY;
|
|
|
- VAR old: QueueEntry;
|
|
|
- BEGIN
|
|
|
- ASSERT(~Empty());
|
|
|
- old := top;
|
|
|
- top := top.next;
|
|
|
- RETURN old.value;
|
|
|
- END Pop;
|
|
|
-
|
|
|
- (* Check if empty *)
|
|
|
- PROCEDURE Empty*():BOOLEAN;
|
|
|
- BEGIN
|
|
|
- RETURN top = NIL;
|
|
|
- END Empty;
|
|
|
-
|
|
|
- END Queue;
|
|
|
-
|
|
|
- PQItem = RECORD
|
|
|
- key: LONGINT;
|
|
|
- value: ANY;
|
|
|
- END;
|
|
|
-
|
|
|
- PQItemList = POINTER TO ARRAY OF PQItem;
|
|
|
-
|
|
|
- (* Priority queue using binary heap *)
|
|
|
- PriorityQueue* = OBJECT
|
|
|
- VAR
|
|
|
- heap: PQItemList;
|
|
|
- count-: LONGINT;
|
|
|
-
|
|
|
- (** Interface **)
|
|
|
-
|
|
|
- PROCEDURE & Init(size: LONGINT);
|
|
|
- BEGIN
|
|
|
- NEW(heap, size + 1);
|
|
|
- count := 0;
|
|
|
- END Init;
|
|
|
-
|
|
|
- PROCEDURE Min*():ANY; (* O(n) *)
|
|
|
- BEGIN
|
|
|
- ASSERT(count > 0);
|
|
|
- RETURN heap[1].value;
|
|
|
- END Min;
|
|
|
-
|
|
|
- PROCEDURE RemoveMin*():ANY; (* O(log n) *)
|
|
|
- VAR min: ANY;
|
|
|
- BEGIN
|
|
|
- min := Min();
|
|
|
- heap[1] := heap[count];
|
|
|
- DEC(count);
|
|
|
- IF count > 0 THEN BubbleDown(1); END;
|
|
|
- RETURN min;
|
|
|
- END RemoveMin;
|
|
|
-
|
|
|
- PROCEDURE Insert*(key: LONGINT; value: ANY); (* O(log n) *)
|
|
|
- VAR index: LONGINT;
|
|
|
- BEGIN
|
|
|
- INC(count);
|
|
|
- index := count;
|
|
|
- heap[index].key := key;
|
|
|
- heap[index].value := value;
|
|
|
- BubbleUp(index);
|
|
|
- END Insert;
|
|
|
-
|
|
|
- PROCEDURE Empty*():BOOLEAN;
|
|
|
- BEGIN
|
|
|
- RETURN count = 0;
|
|
|
- END Empty;
|
|
|
-
|
|
|
- (** Implementation **)
|
|
|
-
|
|
|
- PROCEDURE BubbleUp(VAR index: LONGINT);
|
|
|
- VAR swap: PQItem;
|
|
|
- BEGIN
|
|
|
- WHILE (index > 1) & (heap[index].key < heap[index DIV 2].key) DO
|
|
|
- swap := heap[index DIV 2];
|
|
|
- heap[index DIV 2] := heap[index];
|
|
|
- heap[index] := swap;
|
|
|
- index := index DIV 2;
|
|
|
- END;
|
|
|
- END BubbleUp;
|
|
|
-
|
|
|
- PROCEDURE BubbleDown(index: LONGINT);
|
|
|
- VAR min, minkey: LONGINT; swap: PQItem;
|
|
|
-
|
|
|
- PROCEDURE Child(child: LONGINT);
|
|
|
- BEGIN
|
|
|
- IF (child <= count) & (heap[child].key < minkey) THEN
|
|
|
- min := child;
|
|
|
- minkey := heap[child].key;
|
|
|
- END;
|
|
|
- END Child;
|
|
|
- BEGIN
|
|
|
- REPEAT
|
|
|
- min := 0;
|
|
|
- minkey := heap[index].key;
|
|
|
- Child(index * 2);
|
|
|
- Child((index * 2) + 1);
|
|
|
- IF min # 0 THEN
|
|
|
- swap := heap[min];
|
|
|
- heap[min] := heap[index];
|
|
|
- heap[index] := swap;
|
|
|
- index := min;
|
|
|
- END;
|
|
|
- UNTIL
|
|
|
- min = 0;
|
|
|
- END BubbleDown;
|
|
|
-
|
|
|
- END PriorityQueue;
|
|
|
-
|
|
|
- IndexList = POINTER TO ARRAY OF LONGINT;
|
|
|
-
|
|
|
- Edge* = OBJECT
|
|
|
- VAR
|
|
|
- from-, to-: Block;
|
|
|
-
|
|
|
- PROCEDURE Accept(v: GraphVisitor);
|
|
|
- BEGIN v.VisitEdge(SELF); END Accept;
|
|
|
-
|
|
|
- END Edge;
|
|
|
-
|
|
|
- Graph* = OBJECT
|
|
|
- VAR
|
|
|
- firstBlock*, lastBlock-: Block;
|
|
|
- blocks*: BlockList;
|
|
|
- edges-: EdgeList;
|
|
|
- edgesLookup: HashTable2D;
|
|
|
-
|
|
|
- PROCEDURE & Init *;
|
|
|
- BEGIN
|
|
|
- NEW(blocks,InitListSize);
|
|
|
- NEW(edges,InitListSize);
|
|
|
- NEW(edgesLookup, 1024);
|
|
|
- END Init;
|
|
|
-
|
|
|
- PROCEDURE AddBlock*(block: Block);
|
|
|
- BEGIN
|
|
|
- IF blocks.Length() = 0 THEN firstBlock := block; END;
|
|
|
- block.index := blocks.Length();
|
|
|
- blocks.Add(block);
|
|
|
- lastBlock := block;
|
|
|
- END AddBlock;
|
|
|
-
|
|
|
- PROCEDURE Connect*(from, to: Block);
|
|
|
- VAR edge: Edge;
|
|
|
- BEGIN
|
|
|
- IF edgesLookup.Has2D(from, to) THEN RETURN; END;
|
|
|
- from.successors.Add(to);
|
|
|
- to.predecessors.Add(from);
|
|
|
-
|
|
|
- NEW(edge);
|
|
|
- edge.from := from;
|
|
|
- edge.to := to;
|
|
|
- edges.Add(edge);
|
|
|
- edgesLookup.Put2D(from, to, edge);
|
|
|
- END Connect;
|
|
|
-
|
|
|
- PROCEDURE Split*(from, to: Block);
|
|
|
- BEGIN
|
|
|
- from.successors.Remove(to);
|
|
|
- to.predecessors.Remove(from);
|
|
|
-
|
|
|
- edges.Remove(edgesLookup.Get2D(from, to));
|
|
|
- END Split;
|
|
|
-
|
|
|
- (* Reorder blocks so that they form a reverse post order *)
|
|
|
- PROCEDURE ReIndex*;
|
|
|
- VAR b: Block; i: LONGINT; done: POINTER TO ARRAY OF BOOLEAN; new: BlockList;
|
|
|
-
|
|
|
- PROCEDURE Work(b: Block);
|
|
|
- VAR i: LONGINT; p: Block;
|
|
|
- BEGIN
|
|
|
- done[b.index] := TRUE;
|
|
|
-
|
|
|
- FOR i := 0 TO b.successors.Length() - 1 DO
|
|
|
- p := b.successors.GetBlock(i);
|
|
|
- IF ~done[p.index] THEN
|
|
|
- Work(p);
|
|
|
- END;
|
|
|
- END;
|
|
|
-
|
|
|
- new.Add(b);
|
|
|
- END Work;
|
|
|
- BEGIN
|
|
|
- NEW(new,InitListSize);
|
|
|
- NEW(done, blocks.Length());
|
|
|
- i := 0;
|
|
|
-
|
|
|
- Work(blocks.GetBlock(0));
|
|
|
-
|
|
|
- NEW(blocks,InitListSize);
|
|
|
- FOR i := new.Length() - 1 TO 0 BY -1 DO
|
|
|
- b := new.GetBlock(i);
|
|
|
- b.index := blocks.Length();
|
|
|
- blocks.Add(b);
|
|
|
- END;
|
|
|
- END ReIndex;
|
|
|
-
|
|
|
- (* Calculate dominance tree. Algorithm taken from:
|
|
|
- "A simple, fast dominance algorithm" (Cooper, Harvey, Kennedy) *)
|
|
|
- PROCEDURE CalculateDominance*;
|
|
|
- VAR
|
|
|
- doms: IndexList;
|
|
|
- i, j, len, runner, newIdom: LONGINT;
|
|
|
- changed: BOOLEAN;
|
|
|
- block, pred: Block;
|
|
|
-
|
|
|
- PROCEDURE Intersect(b1, b2: LONGINT):LONGINT;
|
|
|
- BEGIN
|
|
|
- WHILE(b1 # b2) DO
|
|
|
- WHILE(b1 > b2) DO
|
|
|
- IF b1 = doms[b1] THEN HALT(100); END;
|
|
|
- b1 := doms[b1];
|
|
|
- END;
|
|
|
- WHILE(b2 > b1) DO
|
|
|
- IF b2 = doms[b2] THEN HALT(100); END;
|
|
|
- b2 := doms[b2];
|
|
|
- END;
|
|
|
- END;
|
|
|
-
|
|
|
- RETURN b1;
|
|
|
- END Intersect;
|
|
|
-
|
|
|
- BEGIN
|
|
|
- (* Initialize the arrays *)
|
|
|
- len := blocks.Length();
|
|
|
-
|
|
|
- NEW(doms, len);
|
|
|
- FOR i := 0 TO len - 1 DO
|
|
|
- doms[i] := -1;
|
|
|
- END;
|
|
|
- doms[0] := 0;
|
|
|
-
|
|
|
- (* Iteration loop *)
|
|
|
- changed := TRUE;
|
|
|
- WHILE(changed) DO
|
|
|
- changed := FALSE;
|
|
|
-
|
|
|
- FOR i := 1 TO len - 1 DO
|
|
|
- block := blocks.GetBlock(i);
|
|
|
- pred := block.predecessors.GetBlock(0);
|
|
|
- newIdom := pred.index;
|
|
|
- FOR j := 1 TO block.predecessors.Length() - 1 DO
|
|
|
- pred := block.predecessors.GetBlock(j);
|
|
|
- IF doms[pred.index] # -1 THEN
|
|
|
- newIdom := Intersect(pred.index, newIdom);
|
|
|
- END;
|
|
|
- END;
|
|
|
- IF doms[i] # newIdom THEN
|
|
|
- doms[i] := newIdom;
|
|
|
- changed := TRUE;
|
|
|
- END;
|
|
|
- END;
|
|
|
- END;
|
|
|
-
|
|
|
- FOR i := 0 TO len - 1 DO
|
|
|
- block := blocks.GetBlock(i);
|
|
|
-
|
|
|
- (* Set immediate dominators *)
|
|
|
- block.immediateDominator := doms[i];
|
|
|
-
|
|
|
- (* Calculate frontier *)
|
|
|
- IF block.predecessors.Length() >= 2 THEN
|
|
|
- FOR j := 0 TO block.predecessors.Length() - 1 DO
|
|
|
- pred := block.predecessors.GetBlock(j);
|
|
|
- runner := pred.index;
|
|
|
- WHILE runner # doms[block.index] DO
|
|
|
- pred := blocks.GetBlock(runner);
|
|
|
- IF ~pred.dominanceFrontier.Contains(block) THEN
|
|
|
- pred.dominanceFrontier.Add(block);
|
|
|
- END;
|
|
|
- runner := doms[runner];
|
|
|
- END;
|
|
|
- END;
|
|
|
- END;
|
|
|
- END;
|
|
|
- END CalculateDominance;
|
|
|
-
|
|
|
- END Graph;
|
|
|
-
|
|
|
- BlockList* = OBJECT(List)
|
|
|
- VAR
|
|
|
- PROCEDURE GetBlock*(i: LONGINT):Block;
|
|
|
- VAR block: ANY;
|
|
|
- BEGIN
|
|
|
- block := Get(i);
|
|
|
- RETURN block(Block);
|
|
|
- END GetBlock;
|
|
|
-
|
|
|
- PROCEDURE GetIndex*(i: LONGINT):LONGINT;
|
|
|
- VAR block: Block;
|
|
|
- BEGIN
|
|
|
- block := GetBlock(i);
|
|
|
- RETURN block.index;
|
|
|
- END GetIndex;
|
|
|
-
|
|
|
- END BlockList;
|
|
|
-
|
|
|
- EdgeList* = OBJECT(List)
|
|
|
- VAR
|
|
|
- PROCEDURE GetEdge*(i: LONGINT):Edge;
|
|
|
- VAR
|
|
|
- edge: ANY;
|
|
|
- BEGIN
|
|
|
- edge := Get(i);
|
|
|
- RETURN edge(Edge);
|
|
|
- END GetEdge;
|
|
|
- END EdgeList;
|
|
|
-
|
|
|
- Block* = OBJECT
|
|
|
- VAR
|
|
|
- predecessors-, successors-, dominanceFrontier-: BlockList;
|
|
|
- index*, immediateDominator*: LONGINT;
|
|
|
-
|
|
|
- PROCEDURE & Init*;
|
|
|
- BEGIN
|
|
|
- NEW(predecessors,InitListSize);
|
|
|
- NEW(successors,InitListSize);
|
|
|
- NEW(dominanceFrontier,InitListSize);
|
|
|
- END Init;
|
|
|
-
|
|
|
- PROCEDURE Accept(v: GraphVisitor);
|
|
|
- BEGIN v.VisitBlock(SELF); END Accept;
|
|
|
-
|
|
|
- PROCEDURE PredecessorIndex*(block: Block):LONGINT;
|
|
|
- VAR i: LONGINT;
|
|
|
- BEGIN
|
|
|
- FOR i := 0 TO predecessors.Length() - 1 DO
|
|
|
- IF predecessors.Get(i) = block THEN
|
|
|
- RETURN i;
|
|
|
- END;
|
|
|
- END;
|
|
|
- HALT(100);
|
|
|
- END PredecessorIndex;
|
|
|
- END Block;
|
|
|
-
|
|
|
- ContentFunction = PROCEDURE {DELEGATE} (block: Block);
|
|
|
-
|
|
|
- GraphVisitor* = OBJECT
|
|
|
- VAR
|
|
|
- block-: Block;
|
|
|
- edge-: Edge;
|
|
|
- graph-: Graph;
|
|
|
-
|
|
|
- PROCEDURE VisitEdge*(edge: Edge);
|
|
|
- BEGIN END VisitEdge;
|
|
|
-
|
|
|
- PROCEDURE VisitBlock*(block: Block);
|
|
|
- BEGIN END VisitBlock;
|
|
|
-
|
|
|
- PROCEDURE VisitGraph*(graph: Graph);
|
|
|
- VAR i: LONGINT;
|
|
|
- BEGIN
|
|
|
- SELF.graph := graph;
|
|
|
- FOR i := 0 TO graph.blocks.Length() - 1 DO
|
|
|
- block := graph.blocks.GetBlock(i);
|
|
|
- block.Accept(SELF);
|
|
|
- END;
|
|
|
-
|
|
|
- FOR i := 0 TO graph.edges.Length() - 1 DO
|
|
|
- edge := graph.edges.GetEdge(i);
|
|
|
- edge.Accept(SELF);
|
|
|
- END;
|
|
|
- END VisitGraph;
|
|
|
-
|
|
|
- END GraphVisitor;
|
|
|
-
|
|
|
- (** Outputs a .dot file which can be parsed into a graph by GraphViz *)
|
|
|
- GraphPrinter* = OBJECT(GraphVisitor)
|
|
|
- VAR
|
|
|
- active-: Block;
|
|
|
- writer-: Streams.Writer;
|
|
|
- content: ContentFunction;
|
|
|
-
|
|
|
- PROCEDURE VisitEdge*(edge: Edge);
|
|
|
- BEGIN
|
|
|
- writer.String("block"); writer.Int(edge.from.index, 0);
|
|
|
- writer.String("->");
|
|
|
- writer.String("block"); writer.Int(edge.to.index, 0);
|
|
|
- writer.String(";"); writer.Ln;
|
|
|
- END VisitEdge;
|
|
|
-
|
|
|
- PROCEDURE VisitBlock*(block: Block);
|
|
|
- VAR
|
|
|
- i: LONGINT;
|
|
|
- dom: Block;
|
|
|
- BEGIN
|
|
|
- writer.String("block");
|
|
|
- writer.Int(block.index, 0);
|
|
|
-
|
|
|
- writer.String(' [ label=<<table border="0" cellpadding="1" cellspacing="1"><tr><td>#');
|
|
|
- writer.Int(block.index, 0);
|
|
|
- writer.String("</td><td>idom=");
|
|
|
- writer.Int(block.immediateDominator, 0);
|
|
|
- writer.String("</td><td>df=");
|
|
|
- FOR i := 0 TO block.dominanceFrontier.Length() - 1 DO
|
|
|
- dom := block.dominanceFrontier.GetBlock(i);
|
|
|
- writer.Int(dom.index, 0);
|
|
|
- writer.String(" ");
|
|
|
- END;
|
|
|
- writer.String("</td></tr>");
|
|
|
-
|
|
|
- content(block);
|
|
|
-
|
|
|
- writer.String('</table>>]; ');
|
|
|
- writer.Ln;
|
|
|
- END VisitBlock;
|
|
|
-
|
|
|
- PROCEDURE VisitGraph*(graph: Graph);
|
|
|
- BEGIN
|
|
|
- SELF.graph := graph;
|
|
|
-
|
|
|
- (* Print header of dot file *)
|
|
|
- writer.String("digraph G {"); writer.Ln;
|
|
|
-
|
|
|
- (* Print all blocks *)
|
|
|
- writer.String("node [shape=box]; ");
|
|
|
- VisitGraph^(graph);
|
|
|
-
|
|
|
- (* Footer *)
|
|
|
- writer.Ln;
|
|
|
- writer.String("overlap=false;"); writer.Ln;
|
|
|
- writer.String('label=" Created with OC";'); writer.Ln;
|
|
|
- writer.String("fontsize=12;"); writer.Ln;
|
|
|
- writer.String("}");
|
|
|
- END VisitGraph;
|
|
|
-
|
|
|
- PROCEDURE SetWriter*(w: Streams.Writer);
|
|
|
- BEGIN
|
|
|
- writer := w;
|
|
|
- END SetWriter;
|
|
|
-
|
|
|
- PROCEDURE & Init*(c: ContentFunction);
|
|
|
- BEGIN
|
|
|
- content := c;
|
|
|
- END Init;
|
|
|
-
|
|
|
- END GraphPrinter;
|
|
|
-
|
|
|
IntegerObject = OBJECT
|
|
|
END IntegerObject;
|
|
|
|
|
@@ -1608,7 +786,7 @@ TYPE
|
|
|
|
|
|
END Writer;
|
|
|
|
|
|
- TracingDiagnostics=OBJECT (Diagnostics.Diagnostics)
|
|
|
+ TracingDiagnostics = OBJECT (Diagnostics.Diagnostics)
|
|
|
VAR diagnostics: Diagnostics.Diagnostics;
|
|
|
|
|
|
PROCEDURE &InitDiagnostics(diagnostics: Diagnostics.Diagnostics);
|