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
|
// 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.
#pragma once
class SsaRenameState
{
struct StackNode;
class Stack
{
StackNode* m_top;
public:
Stack() : m_top(nullptr)
{
}
StackNode* Top()
{
return m_top;
}
void Push(StackNode* node)
{
node->m_stackPrev = m_top;
m_top = node;
}
StackNode* Pop()
{
StackNode* top = m_top;
m_top = top->m_stackPrev;
return top;
}
};
struct StackNode
{
// Link to the previous stack top node
StackNode* m_stackPrev;
// Link to the previously pushed stack (used only when popping blocks)
Stack* m_listPrev;
// The basic block (used only when popping blocks)
BasicBlock* m_block;
// The actual information StackNode stores - the SSA number
unsigned m_ssaNum;
StackNode(Stack* listPrev, BasicBlock* block, unsigned ssaNum)
: m_listPrev(listPrev), m_block(block), m_ssaNum(ssaNum)
{
}
};
// Memory allocator
CompAllocator m_alloc;
// Number of local variables to allocate stacks for
unsigned m_lvaCount;
// An array of stack objects, one for each local variable
Stack* m_stacks;
// The tail of the list of stacks that have been pushed to
Stack* m_stackListTail;
// Same state for the special implicit memory variables
Stack m_memoryStack[MemoryKindCount];
// A stack of free stack nodes
Stack m_freeStack;
public:
SsaRenameState(CompAllocator alloc, unsigned lvaCount);
// Get the SSA number at the top of the stack for the specified variable.
unsigned Top(unsigned lclNum);
// Push a SSA number onto the stack for the specified variable.
void Push(BasicBlock* block, unsigned lclNum, unsigned ssaNum);
// Pop all stacks that have an entry for "block" on top.
void PopBlockStacks(BasicBlock* block);
// Similar functions for the special implicit memory variable.
unsigned TopMemory(MemoryKind memoryKind)
{
return m_memoryStack[memoryKind].Top()->m_ssaNum;
}
void PushMemory(MemoryKind memoryKind, BasicBlock* block, unsigned ssaNum)
{
Push(&m_memoryStack[memoryKind], block, ssaNum);
}
private:
void EnsureStacks();
// Allocate a new stack entry (possibly by popping it from the free stack)
template <class... Args>
StackNode* AllocStackNode(Args&&... args)
{
StackNode* stack = m_freeStack.Top();
if (stack != nullptr)
{
m_freeStack.Pop();
}
else
{
stack = m_alloc.allocate<StackNode>(1);
}
return new (stack, jitstd::placement_t()) StackNode(jitstd::forward<Args>(args)...);
}
// Push a SSA number onto a stack
void Push(Stack* stack, BasicBlock* block, unsigned ssaNum);
INDEBUG(void DumpStack(Stack* stack);)
};
|