-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathIRBuilderAsmJs.h
321 lines (294 loc) · 17.8 KB
/
IRBuilderAsmJs.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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
#ifdef ASMJS_PLAT
namespace AsmJsRegSlots
{
enum ConstSlots
{
ReturnReg = 0,
ModuleMemReg,
ArrayReg,
WasmMemoryReg,
BufferReg,
LengthReg,
SharedContents,
RefCountedBuffer,
RegCount
};
};
struct JitLoopBodyData
{
private:
BVFixed* m_ldSlots = nullptr;
StackSym* m_loopBodyRetIPSym = nullptr;
BVFixed* m_yieldRegs = nullptr;
uint32 m_loopCurRegs[WAsmJs::LIMIT];
public:
JitLoopBodyData(BVFixed* ldSlots, BVFixed* stSlots, StackSym* loopBodyRetIPSym)
{
Assert(ldSlots && stSlots && loopBodyRetIPSym);
m_ldSlots = ldSlots;
m_loopBodyRetIPSym = loopBodyRetIPSym;
}
// Use m_yieldRegs initialization to determine if m_loopCurRegs is initialized
bool IsLoopCurRegsInitialized() const { return !!m_yieldRegs; }
template<typename T> void InitLoopCurRegs(__in_ecount(WAsmJs::LIMIT) T* curRegs, BVFixed* yieldRegs)
{
Assert(yieldRegs && curRegs);
m_yieldRegs = yieldRegs;
for (WAsmJs::Types type = WAsmJs::Types(0); type != WAsmJs::LIMIT; type = WAsmJs::Types(type + 1))
{
m_loopCurRegs[type] = curRegs[type];
}
}
bool IsRegOutsideOfLoop(uint32 typeReg, WAsmJs::Types type) const
{
Assert(IsLoopCurRegsInitialized());
return typeReg < m_loopCurRegs[type];
}
bool IsYieldReg(Js::RegSlot reg) const
{
if (!m_yieldRegs)
{
return false;
}
AssertOrFailFast(reg < m_yieldRegs->Length());
return m_yieldRegs->Test(reg);
}
void SetRegIsYield(Js::RegSlot reg)
{
Assert(m_yieldRegs);
AssertOrFailFast(reg < m_yieldRegs->Length());
m_yieldRegs->Set(reg);
}
BVFixed* GetLdSlots() const { return m_ldSlots; }
StackSym* GetLoopBodyRetIPSym() const { return m_loopBodyRetIPSym; }
#if DBG
BVFixed* m_usedAsTemp;
#endif
};
class IRBuilderAsmJs
{
friend struct IRBuilderAsmJsSwitchAdapter;
public:
IRBuilderAsmJs(Func * func)
: m_func(func)
, m_switchAdapter(this)
, m_switchBuilder(&m_switchAdapter)
{
if (!m_func->GetJITFunctionBody()->IsWasmFunction())
{
m_statementReader = Anew(func->m_alloc, Js::StatementReader<Js::FunctionBody::ArenaStatementMapList>);
}
func->m_workItem->InitializeReader(&m_jnReader, m_statementReader, func->m_alloc);
m_asmFuncInfo = m_func->GetJITFunctionBody()->GetAsmJsInfo();
#if 0
// templatized JIT loop body
if (func->IsLoopBody())
{
Js::LoopEntryPointInfo* loopEntryPointInfo = (Js::LoopEntryPointInfo*)(func->m_workItem->GetEntryPoint());
if (loopEntryPointInfo->GetIsTJMode())
{
m_IsTJLoopBody = true;
func->isTJLoopBody = true;
}
}
#endif
}
void Build();
private:
struct MemAccessTypeInfo
{
WAsmJs::Types valueRegType;
IRType type;
ValueType arrayType;
};
void LoadNativeCodeData();
void AddInstr(IR::Instr * instr, uint32 offset);
bool IsLoopBody()const;
uint GetLoopBodyExitInstrOffset() const;
IR::SymOpnd * BuildAsmJsLoopBodySlotOpnd(Js::RegSlot regSlot, IRType opndType);
void EnsureLoopBodyAsmJsLoadSlot(Js::RegSlot regSlot, IRType type);
void EnsureLoopBodyAsmJsStoreSlot(Js::RegSlot regSlot, IRType type);
bool IsLoopBodyOuterOffset(uint offset) const;
bool IsLoopBodyReturnIPInstr(IR::Instr * instr) const;
IR::Opnd * InsertLoopBodyReturnIPInstr(uint targetOffset, uint offset);
IR::RegOpnd * BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type);
IR::RegOpnd * BuildSrcOpnd(Js::RegSlot srcRegSlot, IRType type);
IR::RegOpnd * BuildIntConstOpnd(Js::RegSlot regSlot);
SymID BuildSrcStackSymID(Js::RegSlot regSlot, IRType type = IRType::TyVar);
IR::SymOpnd * BuildFieldOpnd(Js::RegSlot reg, Js::PropertyId propertyId, PropertyKind propertyKind, IRType type, bool scale = true);
PropertySym * BuildFieldSym(Js::RegSlot reg, Js::PropertyId propertyId, PropertyKind propertyKind);
uint AddStatementBoundary(uint statementIndex, uint offset);
BranchReloc * AddBranchInstr(IR::BranchInstr *instr, uint32 offset, uint32 targetOffset);
BranchReloc * CreateRelocRecord(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset);
void BuildHeapBufferReload(uint32 offset, bool isFirstLoad = false);
template<typename T, typename ConstOpnd, typename F>
void CreateLoadConstInstrForType(byte* table, Js::RegSlot& regAllocated, uint32 constCount, uint32 offset, IRType irType, ValueType valueType, Js::OpCode opcode, F extraProcess);
void BuildConstantLoads();
void BuildImplicitArgIns();
void InsertLabels();
IR::LabelInstr * CreateLabel(IR::BranchInstr * branchInstr, uint& offset);
uint32 GetTypedRegFromRegSlot(Js::RegSlot reg, WAsmJs::Types type);
Js::RegSlot GetRegSlotFromTypedReg(Js::RegSlot srcReg, WAsmJs::Types type);
Js::RegSlot GetRegSlotFromPtrReg(Js::RegSlot srcReg)
{
#if TARGET_32
return GetRegSlotFromIntReg(srcReg);
#elif TARGET_64
return GetRegSlotFromInt64Reg(srcReg);
#endif
}
Js::RegSlot GetRegSlotFromIntReg(Js::RegSlot srcIntReg) {return GetRegSlotFromTypedReg(srcIntReg, WAsmJs::INT32);}
Js::RegSlot GetRegSlotFromInt64Reg(Js::RegSlot srcIntReg) {return GetRegSlotFromTypedReg(srcIntReg, WAsmJs::INT64);}
Js::RegSlot GetRegSlotFromFloatReg(Js::RegSlot srcFloatReg) {return GetRegSlotFromTypedReg(srcFloatReg, WAsmJs::FLOAT32);}
Js::RegSlot GetRegSlotFromDoubleReg(Js::RegSlot srcDoubleReg) {return GetRegSlotFromTypedReg(srcDoubleReg, WAsmJs::FLOAT64);}
Js::RegSlot GetRegSlotFromSimd128Reg(Js::RegSlot srcSimd128Reg) {return GetRegSlotFromTypedReg(srcSimd128Reg, WAsmJs::SIMD);}
Js::RegSlot GetRegSlotFromVarReg(Js::RegSlot srcVarReg);
Js::OpCode GetSimdOpcode(Js::OpCodeAsmJs asmjsOpcode);
void GetSimdTypesFromAsmType(Js::AsmJsType::Which asmType, IRType *pIRType, ValueType *pValueType = nullptr);
IR::Instr * AddExtendedArg(IR::RegOpnd *src1, IR::RegOpnd *src2, uint32 offset);
bool RegIsSimd128ReturnVar(Js::RegSlot reg);
SymID GetMappedTemp(Js::RegSlot reg);
void SetMappedTemp(Js::RegSlot reg, SymID tempId);
bool GetTempUsed(Js::RegSlot reg);
void SetTempUsed(Js::RegSlot reg, bool used);
bool RegIsTemp(Js::RegSlot reg);
bool RegIsConstant(Js::RegSlot reg);
bool RegIsVar(Js::RegSlot reg);
bool RegIsTypedVar(Js::RegSlot reg, WAsmJs::Types type);
bool RegIsTypedConst(Js::RegSlot reg, WAsmJs::Types type);
bool RegIsTypedTmp(Js::RegSlot reg, WAsmJs::Types type);
bool RegIs(Js::RegSlot reg, WAsmJs::Types type);
bool RegIsJitLoopYield(Js::RegSlot reg);
void CheckJitLoopReturn(Js::RegSlot reg, IRType type);
void BuildArgOut(IR::Opnd* srcOpnd, uint32 dstRegSlot, uint32 offset, IRType type, ValueType valueType = ValueType::Uninitialized);
void BuildFromVar(uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, IRType irType, ValueType valueType);
#define LAYOUT_TYPE(layout) \
void Build##layout(Js::OpCodeAsmJs newOpcode, uint32 offset);
#define LAYOUT_TYPE_WMS(layout) \
template <typename SizePolicy> void Build##layout(Js::OpCodeAsmJs newOpcode, uint32 offset);
#define EXCLUDE_FRONTEND_LAYOUT
#include "ByteCode/LayoutTypesAsmJs.h"
void BuildSimd_1Ints(Js::OpCodeAsmJs newOpcode, uint32 offset, IRType dstSimdType, Js::RegSlot* srcRegSlots, Js::RegSlot dstRegSlot, uint LANES);
void BuildSimd_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, IRType simdType);
void BuildSimd_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, Js::RegSlot src3RegSlot, IRType simdType, IRType valType = TyInt32);
void BuildSimd_2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, IRType simdType);
void BuildSimd_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, IRType simdType);
void BuildSimd_3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, IRType simdType);
void BuildSimd_3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, IRType dstSimdType, IRType srcSimdType);
void BuildSimdConversion(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, IRType dstSimdType, IRType srcSimdType);
ValueType GetSimdValueTypeFromIRType(IRType type);
void BuildElementSlot(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 slotIndex, Js::RegSlot value, Js::RegSlot instance);
void BuildAsmUnsigned1(Js::OpCodeAsmJs newOpcode, uint offset);
void BuildWasmLoopStart(Js::OpCodeAsmJs newOpcode, uint offset);
void BuildWasmMemAccess(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, uint32 constOffset, Js::ArrayBufferView::ViewType viewType);
void BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, Js::ArrayBufferView::ViewType viewType);
void BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, Js::ArrayBufferView::ViewType viewType, uint8 DataWidth, uint32 simdOffset);
void BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::ArgSlot argCount, Js::RegSlot ret, Js::RegSlot function, int8 returnType, Js::ProfileId profileId);
void BuildAsmReg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg);
void BuildBrInt1(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src);
void BuildBrInt2(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src1, Js::RegSlot src2);
void BuildBrInt1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src1, int32 src2);
void BuildBrCmp(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, IR::RegOpnd* src1Opnd, IR::Opnd* src2Opnd);
void GenerateLoopBodySlotAccesses(uint offset);
static void InitializeMemAccessTypeInfo(Js::ArrayBufferView::ViewType viewType, _Out_ MemAccessTypeInfo * typeInfo);
Js::PropertyId CalculatePropertyOffset(Js::RegSlot regSlot, IRType type);
IR::RegOpnd* BuildTrapIfZero(IR::RegOpnd* srcOpnd, uint32 offset);
IR::RegOpnd* BuildTrapIfMinIntOverNegOne(IR::RegOpnd* src1Opnd, IR::RegOpnd* src2Opnd, uint32 offset);
IR::Instr* CreateSignExtendInstr(IR::Opnd* dst, IR::Opnd* src, IRType fromType);
JitArenaAllocator * m_tempAlloc;
JitArenaAllocator * m_funcAlloc;
Func * m_func;
IR::Instr * m_lastInstr;
IR::Instr ** m_offsetToInstruction;
Js::ByteCodeReader m_jnReader;
Js::StatementReader<Js::FunctionBody::ArenaStatementMapList>* m_statementReader = nullptr;
SListCounted<IR::Instr *> *m_argStack;
SList<IR::Instr *> * m_tempList;
SList<int32> * m_argOffsetStack;
SList<BranchReloc *> * m_branchRelocList;
// 1 for const, 1 for var, 1 for temps for each type and 1 for last
static const uint32 m_firstsTypeCount = WAsmJs::LIMIT * 3 + 1;
Js::RegSlot m_firstsType[m_firstsTypeCount];
Js::RegSlot m_firstVarConst;
Js::RegSlot m_tempCount;
Js::OpCode * m_simdOpcodesMap;
Js::RegSlot GetFirstConst(WAsmJs::Types type) { return m_firstsType[type]; }
Js::RegSlot GetFirstVar(WAsmJs::Types type) { return m_firstsType[type + WAsmJs::LIMIT]; }
Js::RegSlot GetFirstTmp(WAsmJs::Types type) { return m_firstsType[type + WAsmJs::LIMIT * 2]; }
Js::RegSlot GetLastConst(WAsmJs::Types type) { return m_firstsType[type + 1]; }
Js::RegSlot GetLastVar(WAsmJs::Types type) { return m_firstsType[type + WAsmJs::LIMIT + 1]; }
Js::RegSlot GetLastTmp(WAsmJs::Types type) { return m_firstsType[type + WAsmJs::LIMIT * 2 + 1]; }
JitLoopBodyData& GetJitLoopBodyData() { Assert(IsLoopBody()); return *m_jitLoopBodyData; }
const JitLoopBodyData& GetJitLoopBodyData() const { Assert(IsLoopBody()); return *m_jitLoopBodyData; }
SymID * m_tempMap;
BVFixed * m_fbvTempUsed;
uint32 m_functionStartOffset;
const AsmJsJITInfo * m_asmFuncInfo;
JitLoopBodyData* m_jitLoopBodyData = nullptr;
IRBuilderAsmJsSwitchAdapter m_switchAdapter;
SwitchIRBuilder m_switchBuilder;
uint32 m_offsetToInstructionCount;
#define BUILD_LAYOUT_DEF(layout, ...) void Build##layout (Js::OpCodeAsmJs, uint32, __VA_ARGS__);
#define Reg_Type Js::RegSlot
#define Int_Type Js::RegSlot
#define Long_Type Js::RegSlot
#define Float_Type Js::RegSlot
#define Double_Type Js::RegSlot
#define IntConst_Type int
#define LongConst_Type int64
#define FloatConst_Type float
#define DoubleConst_Type double
#define Float32x4_Type Js::RegSlot
#define Bool32x4_Type Js::RegSlot
#define Int32x4_Type Js::RegSlot
#define Float64x2_Type Js::RegSlot
#define Int64x2_Type Js::RegSlot
#define Int16x8_Type Js::RegSlot
#define Bool16x8_Type Js::RegSlot
#define Int8x16_Type Js::RegSlot
#define Bool8x16_Type Js::RegSlot
#define Uint32x4_Type Js::RegSlot
#define Uint16x8_Type Js::RegSlot
#define Uint8x16_Type Js::RegSlot
#define LAYOUT_TYPE_WMS_REG2(layout, t0, t1) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type)
#define LAYOUT_TYPE_WMS_REG3(layout, t0, t1, t2) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type)
#define LAYOUT_TYPE_WMS_REG4(layout, t0, t1, t2, t3) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type)
#define LAYOUT_TYPE_WMS_REG5(layout, t0, t1, t2, t3, t4) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type)
#define LAYOUT_TYPE_WMS_REG6(layout, t0, t1, t2, t3, t4, t5) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type)
#define LAYOUT_TYPE_WMS_REG7(layout, t0, t1, t2, t3, t4, t5, t6) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type)
#define LAYOUT_TYPE_WMS_REG9(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type)
#define LAYOUT_TYPE_WMS_REG10(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type, t9##_Type)
#define LAYOUT_TYPE_WMS_REG11(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type, t9##_Type, t10##_Type)
#define LAYOUT_TYPE_WMS_REG17(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type, t9##_Type, t10##_Type, t11##_Type, t12##_Type, t13##_Type, t14##_Type, t15##_Type, t16##_Type)
#define LAYOUT_TYPE_WMS_REG18(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type, t9##_Type, t10##_Type, t11##_Type, t12##_Type, t13##_Type, t14##_Type, t15##_Type, t16##_Type, t17##_Type)
#define LAYOUT_TYPE_WMS_REG19(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18) BUILD_LAYOUT_DEF(layout, t0##_Type, t1##_Type, t2##_Type, t3##_Type, t4##_Type, t5##_Type, t6##_Type, t7##_Type, t8##_Type, t9##_Type, t10##_Type, t11##_Type, t12##_Type, t13##_Type, t14##_Type, t15##_Type, t16##_Type, t17##_Type, t18##_Type)
#define EXCLUDE_FRONTEND_LAYOUT
#include "LayoutTypesAsmJs.h"
#undef BUILD_LAYOUT_DEF
#undef RegType
#undef IntType
#undef LongType
#undef FloatType
#undef DoubleType
#undef IntConstType
#undef LongConstType
#undef FloatConstType
#undef DoubleConstType
#undef Float32x4Type
#undef Bool32x4Type
#undef Int32x4Type
#undef Float64x2Type
#undef Int16x8Type
#undef Bool16x8Type
#undef Int8x16Type
#undef Bool8x16Type
#undef Uint32x4Type
#undef Uint16x8Type
#undef Uint8x16Type
};
#endif