1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ==++==
//
//
//
// ==--==
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX XX
XX SSA XX
XX XX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
*/
#pragma once
#include "jitstd.h"
struct SsaRenameStateForBlock
{
BasicBlock* m_bb;
unsigned m_count;
SsaRenameStateForBlock(BasicBlock* bb, unsigned count) : m_bb(bb), m_count(count)
{
}
SsaRenameStateForBlock() : m_bb(nullptr), m_count(0)
{
}
};
// A record indicating that local "m_loc" was defined in block "m_bb".
struct SsaRenameStateLocDef
{
BasicBlock* m_bb;
unsigned m_lclNum;
SsaRenameStateLocDef(BasicBlock* bb, unsigned lclNum) : m_bb(bb), m_lclNum(lclNum)
{
}
};
struct SsaRenameState
{
typedef jitstd::list<SsaRenameStateForBlock> Stack;
typedef Stack** Stacks;
typedef unsigned* Counts;
typedef jitstd::list<SsaRenameStateLocDef> DefStack;
SsaRenameState(const jitstd::allocator<int>& allocator, unsigned lvaCount);
void EnsureCounts();
void EnsureStacks();
// Requires "lclNum" to be a variable number for which a new count corresponding to a
// definition is desired. The method post increments the counter for the "lclNum."
unsigned CountForDef(unsigned lclNum);
// Requires "lclNum" to be a variable number for which an ssa number at the top of the
// stack is required i.e., for variable "uses."
unsigned CountForUse(unsigned lclNum);
// Requires "lclNum" to be a variable number, and requires "count" to represent
// an ssa number, that needs to be pushed on to the stack corresponding to the lclNum.
void Push(BasicBlock* bb, unsigned lclNum, unsigned count);
// Pop all stacks that have an entry for "bb" on top.
void PopBlockStacks(BasicBlock* bb);
// Similar functions for the special implicit "Heap" variable.
unsigned CountForHeapDef()
{
if (heapCount == 0)
{
heapCount = SsaConfig::FIRST_SSA_NUM;
}
unsigned res = heapCount;
heapCount++;
return res;
}
unsigned CountForHeapUse()
{
return heapStack.back().m_count;
}
void PushHeap(BasicBlock* bb, unsigned count)
{
heapStack.push_back(SsaRenameStateForBlock(bb, count));
}
void PopBlockHeapStack(BasicBlock* bb);
unsigned HeapCount()
{
return heapCount;
}
#ifdef DEBUG
// Debug interface
void DumpStacks();
#endif
private:
// Map of lclNum -> count.
Counts counts;
// Map of lclNum -> SsaRenameStateForBlock.
Stacks stacks;
// This list represents the set of locals defined in the current block.
DefStack definedLocs;
// Same state for the special implicit Heap variable.
Stack heapStack;
unsigned heapCount;
// Number of stacks/counts to allocate.
unsigned lvaCount;
// Allocator to allocate stacks.
jitstd::allocator<void> m_alloc;
};
|