-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathSymInstr.h
235 lines (185 loc) · 7.83 KB
/
SymInstr.h
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#ifndef __SYMINSTR_H__
#define __SYMINSTR_H__
#include "ILBlock.h"
#include "Function.h"
#include "BitVector.h"
#define SYMREG_MIN_SPECIAL_REG 0xffffff00
#define SYMREG_SP 0xfffffff0
#define SYMREG_BP 0xfffffff1
#define SYMREG_LR 0xfffffff2
#define SYMREG_IP 0xfffffff3
#define SYMREG_NONE 0xffffffff
#define SYMREG_NATIVE_REG(r) ((r) | 0x80000000)
#define SYMREG_IS_SPECIAL_REG(r) (((r) & 0x80000000) != 0)
#define SYMFLAG_WRITES_FLAGS 1
#define SYMFLAG_USES_FLAGS 2
#define SYMFLAG_MEMORY_BARRIER 4
#define SYMFLAG_CONTROL_FLOW 8
#define SYMFLAG_CALL 0x10
#define SYMFLAG_COPY 0x20
#define SYMFLAG_STACK 0x40
#define SYMVAR_FRAME_SIZE 0xfffffff0
#define SYMVAR_NEG_FRAME_SIZE 0xfffffff1
enum SymInstrOperandType
{
SYMOPERAND_REG,
SYMOPERAND_IMMED,
SYMOPERAND_STACK_VAR,
SYMOPERAND_GLOBAL_VAR,
SYMOPERAND_BLOCK
};
enum SymInstrOperandAccess
{
SYMOPERAND_READ,
SYMOPERAND_WRITE,
SYMOPERAND_READ_WRITE,
SYMOPERAND_TEMPORARY,
SYMOPERAND_IGNORED
};
class SymInstrBlock;
class SymInstrFunction;
struct SymInstrOperand
{
SymInstrOperandType type;
SymInstrOperandAccess access;
uint32_t reg = 0;
int64_t immed = 0;
Function* func = nullptr;
ILBlock* block = nullptr;
size_t dataFlowBit;
std::vector<size_t> useDefChain;
SymInstrOperand();
void Print(SymInstrFunction* func);
};
class SymInstr
{
protected:
uint32_t m_operation;
uint32_t m_flags;
std::vector<SymInstrOperand> m_operands;
public:
SymInstr();
virtual ~SymInstr();
uint32_t GetOperation() const { return m_operation; }
uint32_t GetFlags() const { return m_flags; }
bool IsFlagSet(uint32_t flag) const { return (m_flags & flag) != 0; }
std::vector<SymInstrOperand>& GetOperands() { return m_operands; }
void SetOperation(uint32_t op) { m_operation = op; }
void EnableFlag(uint32_t flag) { m_flags |= flag; }
void SetFlags(uint32_t flags) { m_flags = flags; }
void AddRegisterOperand(uint32_t reg, SymInstrOperandAccess access);
void AddReadRegisterOperand(uint32_t reg) { AddRegisterOperand(reg, SYMOPERAND_READ); }
void AddWriteRegisterOperand(uint32_t reg) { AddRegisterOperand(reg, SYMOPERAND_WRITE); }
void AddReadWriteRegisterOperand(uint32_t reg) { AddRegisterOperand(reg, SYMOPERAND_READ_WRITE); }
void AddTemporaryRegisterOperand(uint32_t reg) { AddRegisterOperand(reg, SYMOPERAND_TEMPORARY); }
void AddIgnoredRegisterOperand(uint32_t reg) { AddRegisterOperand(reg, SYMOPERAND_IGNORED); }
void AddImmediateOperand(int64_t immed);
void AddStackVarOperand(uint32_t var, int64_t offset);
void AddGlobalVarOperand(int64_t dataOffset);
void AddBlockOperand(Function* func, ILBlock* block);
virtual bool UpdateInstruction(SymInstrFunction* func, const Settings& settings, std::vector<SymInstr*>& replacement);
virtual bool EmitInstruction(SymInstrFunction* func, OutputBlock* out) = 0;
virtual void Print(SymInstrFunction* func) = 0;
};
class SymInstrBlock
{
protected:
size_t m_index;
std::vector<SymInstr*> m_instrs;
std::set<SymInstrBlock*> m_entryBlocks;
std::set<SymInstrBlock*> m_exitBlocks;
BitVector m_defPreserve, m_defGenerate, m_defReachIn, m_defReachOut;
BitVector m_liveDef, m_liveUse, m_liveIn, m_liveOut;
public:
SymInstrBlock(size_t i);
virtual ~SymInstrBlock();
size_t GetIndex() const { return m_index; }
std::vector<SymInstr*>& GetInstructions() { return m_instrs; }
void AddInstruction(SymInstr* instr) { m_instrs.push_back(instr); }
void ReplaceInstruction(size_t i, const std::vector<SymInstr*>& replacement);
void InsertInstructions(size_t i, const std::vector<SymInstr*>& code);
const std::set<SymInstrBlock*>& GetEntryBlocks() const { return m_entryBlocks; }
const std::set<SymInstrBlock*>& GetExitBlocks() const { return m_exitBlocks; }
void AddEntryBlock(SymInstrBlock* block) { m_entryBlocks.insert(block); }
void AddExitBlock(SymInstrBlock* block) { m_exitBlocks.insert(block); }
void ResetDataFlowInfo(size_t defs, size_t regs);
BitVector& GetPreservedDefinitions() { return m_defPreserve; }
BitVector& GetGeneratedDefinitions() { return m_defGenerate; }
BitVector& GetReachingDefinitionsInput() { return m_defReachIn; }
BitVector& GetReachingDefinitionsOutput() { return m_defReachOut; }
BitVector& GetLiveDefinitions() { return m_liveDef; }
BitVector& GetLiveUses() { return m_liveUse; }
BitVector& GetLiveInput() { return m_liveIn; }
BitVector& GetLiveOutput() { return m_liveOut; }
bool IsRegisterLiveAtDefinition(uint32_t reg, size_t instr);
bool EmitCode(SymInstrFunction* func, OutputBlock* out);
virtual void Print(SymInstrFunction* func);
};
class SymInstrFunction
{
protected:
Settings m_settings;
Function* m_function;
std::vector<SymInstrBlock*> m_blocks;
std::map<ILBlock*, SymInstrBlock*> m_blockMap;
std::vector<uint32_t> m_symRegClass;
std::vector<ILParameterType> m_symRegType;
std::vector<uint32_t> m_symRegVar;
std::vector<int64_t> m_symRegOffset;
std::vector<uint32_t> m_symRegAssignment;
std::vector<int64_t> m_stackVarOffsets;
std::vector<bool> m_stackVarIsParam;
std::vector<size_t> m_stackVarWidths;
std::vector<ILParameterType> m_stackVarTypes;
int64_t m_stackFrameSize;
std::set<SymInstrBlock*> m_exitBlocks;
BitVector m_exitReachingDefs;
std::map< uint32_t, std::vector<size_t> > m_regDefs;
std::vector< std::pair<SymInstrBlock*, size_t> > m_defLocs;
std::vector< std::vector< std::pair<SymInstrBlock*, size_t> > > m_defUseChains;
std::vector< std::set<uint32_t> > m_regInterference;
std::vector< std::set<uint32_t> > m_preferSameReg;
std::vector< std::map<uint32_t, size_t> > m_preferSameRegCount;
std::set<uint32_t> m_alreadySpilled;
std::vector<uint32_t> m_clobberedCalleeSavedRegs;
SymInstrBlock* AddBlock(ILBlock* il);
void AddExitBlock(SymInstrBlock* block, SymInstrBlock* exitBlock);
void PerformDataFlowAnalysis();
void SplitRegisters();
bool SpillRegister(uint32_t reg);
public:
SymInstrFunction(const Settings& settings, Function* func);
virtual ~SymInstrFunction();
void InitializeBlocks(Function* func);
SymInstrBlock* GetBlock(ILBlock* block) const;
uint32_t AddRegister(uint32_t cls, ILParameterType type = ILTYPE_VOID, int64_t offset = 0, uint32_t var = SYMREG_NONE);
void AssignRegister(uint32_t reg, uint32_t native);
const std::vector<uint32_t>& GetRegisters() const { return m_symRegClass; }
uint32_t GetRegisterClass(uint32_t i) const { return m_symRegClass[i]; }
uint32_t GetPossibleMatchRegister(size_t i) const { return (uint32_t)(m_symRegClass.size() + i); }
uint32_t AddStackVar(int64_t offset, bool param, size_t width, ILParameterType type);
int64_t GetStackVarOffset(uint32_t var) const;
const std::vector<size_t>& GetStackVarWidths() const { return m_stackVarWidths; }
const std::vector<ILParameterType>& GetStackVarTypes() const { return m_stackVarTypes; }
const std::vector<uint32_t>& GetClobberedCalleeSavedRegisters() const { return m_clobberedCalleeSavedRegs; }
const Settings& GetSettings() const { return m_settings; }
Function* GetFunction() const { return m_function; }
bool AllocateRegisters();
virtual std::vector<uint32_t> GetCallerSavedRegisters() = 0;
virtual std::vector<uint32_t> GetCalleeSavedRegisters() = 0;
virtual std::set<uint32_t> GetRegisterClassInterferences(uint32_t cls) = 0;
virtual bool IsRegisterClassFixed(uint32_t cls) = 0;
virtual uint32_t GetFixedRegisterForClass(uint32_t cls) = 0;
virtual uint32_t GetSpecialRegisterAssignment(uint32_t reg) = 0;
virtual bool DoesRegisterClassConflictWithSpecialRegisters(uint32_t cls) = 0;
virtual size_t GetNativeSize() = 0;
virtual void LayoutStackFrame() = 0;
virtual bool GenerateSpillLoad(uint32_t reg, uint32_t var, int64_t offset,
ILParameterType type, std::vector<SymInstr*>& code) = 0;
virtual bool GenerateSpillStore(uint32_t reg, uint32_t var, int64_t offset,
ILParameterType type, std::vector<SymInstr*>& code) = 0;
virtual void PrintRegisterClass(uint32_t cls) = 0;
virtual void PrintRegister(uint32_t reg);
virtual void Print();
};
#endif