Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/CodeGen/src/CodeGen.cpp
2725 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#include "Luau/CodeGen.h"
3
4
#include "CodeGenLower.h"
5
6
#include "Luau/CodeGenCommon.h"
7
#include "Luau/CodeAllocator.h"
8
#include "Luau/CodeBlockUnwind.h"
9
#include "Luau/IrBuilder.h"
10
11
#include "Luau/UnwindBuilder.h"
12
#include "Luau/UnwindBuilderDwarf2.h"
13
#include "Luau/UnwindBuilderWin.h"
14
15
#include "Luau/AssemblyBuilderA64.h"
16
#include "Luau/AssemblyBuilderX64.h"
17
18
#include "CodeGenContext.h"
19
#include "NativeState.h"
20
21
#include "CodeGenA64.h"
22
#include "CodeGenX64.h"
23
24
#include "lapi.h"
25
#include "lmem.h"
26
27
#include <memory>
28
#include <optional>
29
30
#if defined(CODEGEN_TARGET_X64)
31
#ifdef _MSC_VER
32
#include <intrin.h> // __cpuid
33
#else
34
#include <cpuid.h> // __cpuid
35
#endif
36
#endif
37
38
#if defined(CODEGEN_TARGET_A64)
39
#ifdef __APPLE__
40
#include <sys/sysctl.h>
41
#endif
42
#endif
43
44
LUAU_FASTFLAGVARIABLE(DebugCodegenOptSize)
45
LUAU_FASTFLAGVARIABLE(DebugCodegenSkipNumbering)
46
47
// Per-module IR instruction count limit
48
LUAU_FASTINTVARIABLE(CodegenHeuristicsInstructionLimit, 1'048'576) // 1 M
49
50
// Per-function IR block limit
51
// Current value is based on some member variables being limited to 16 bits
52
// Because block check is made before optimization passes and optimization can generate new blocks, limit is lowered 2x
53
// The limit will probably be adjusted in the future to avoid performance issues with analysis that's more complex than O(n)
54
LUAU_FASTINTVARIABLE(CodegenHeuristicsBlockLimit, 32'768) // 32 K
55
56
// Per-function IR instruction limit
57
// Current value is based on some member variables being limited to 16 bits
58
LUAU_FASTINTVARIABLE(CodegenHeuristicsBlockInstructionLimit, 65'536) // 64 K
59
60
namespace Luau
61
{
62
namespace CodeGen
63
{
64
65
std::string toString(const CodeGenCompilationResult& result)
66
{
67
switch (result)
68
{
69
case CodeGenCompilationResult::Success:
70
return "Success";
71
case CodeGenCompilationResult::NothingToCompile:
72
return "NothingToCompile";
73
case CodeGenCompilationResult::NotNativeModule:
74
return "NotNativeModule";
75
case CodeGenCompilationResult::CodeGenNotInitialized:
76
return "CodeGenNotInitialized";
77
case CodeGenCompilationResult::CodeGenOverflowInstructionLimit:
78
return "CodeGenOverflowInstructionLimit";
79
case CodeGenCompilationResult::CodeGenOverflowBlockLimit:
80
return "CodeGenOverflowBlockLimit";
81
case CodeGenCompilationResult::CodeGenOverflowBlockInstructionLimit:
82
return "CodeGenOverflowBlockInstructionLimit";
83
case CodeGenCompilationResult::CodeGenAssemblerFinalizationFailure:
84
return "CodeGenAssemblerFinalizationFailure";
85
case CodeGenCompilationResult::CodeGenLoweringFailure:
86
return "CodeGenLoweringFailure";
87
case CodeGenCompilationResult::AllocationFailed:
88
return "AllocationFailed";
89
case CodeGenCompilationResult::Count:
90
return "Count";
91
}
92
93
CODEGEN_ASSERT(false);
94
return "";
95
}
96
97
void onDisable(lua_State* L, Proto* proto)
98
{
99
// do nothing if proto already uses bytecode
100
if (proto->codeentry == proto->code)
101
return;
102
103
// ensure that VM does not call native code for this proto
104
proto->codeentry = proto->code;
105
106
// prevent native code from entering proto with breakpoints
107
proto->exectarget = 0;
108
109
// walk all thread call stacks and clear the LUA_CALLINFO_NATIVE flag from any
110
// entries pointing to the current proto that has native code enabled.
111
luaM_visitgco(
112
L,
113
proto,
114
[](void* context, lua_Page* page, GCObject* gco)
115
{
116
Proto* proto = (Proto*)context;
117
118
if (gco->gch.tt != LUA_TTHREAD)
119
return false;
120
121
lua_State* th = gco2th(gco);
122
123
for (CallInfo* ci = th->ci; ci > th->base_ci; ci--)
124
{
125
if (isLua(ci))
126
{
127
Proto* p = clvalue(ci->func)->l.p;
128
129
if (p == proto)
130
{
131
ci->flags &= ~LUA_CALLINFO_NATIVE;
132
}
133
}
134
}
135
136
return false;
137
}
138
);
139
}
140
141
#if defined(CODEGEN_TARGET_A64)
142
unsigned int getCpuFeaturesA64()
143
{
144
unsigned int result = 0;
145
146
#ifdef __APPLE__
147
int jscvt = 0;
148
size_t jscvtLen = sizeof(jscvt);
149
if (sysctlbyname("hw.optional.arm.FEAT_JSCVT", &jscvt, &jscvtLen, nullptr, 0) == 0 && jscvt == 1)
150
result |= A64::Feature_JSCVT;
151
152
int advSIMD = 0;
153
size_t advSIMDLen = sizeof(advSIMD);
154
if (sysctlbyname("hw.optional.arm.AdvSIMD", &advSIMD, &advSIMDLen, nullptr, 0) == 0 && advSIMD == 1)
155
result |= A64::Feature_AdvSIMD;
156
#endif
157
158
return result;
159
}
160
#else
161
unsigned int getCpuFeaturesX64()
162
{
163
unsigned int result = 0;
164
165
int cpuinfo[4] = {0, 0, 0, 0};
166
#if defined(CODEGEN_TARGET_X64)
167
#ifdef _MSC_VER
168
__cpuid(cpuinfo, 1);
169
#else
170
__cpuid(1, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]);
171
#endif
172
#endif
173
174
if ((cpuinfo[2] & 0x00001000) != 0)
175
result |= X64::Feature_FMA3;
176
177
if ((cpuinfo[2] & 0x10000000) != 0)
178
result |= X64::Feature_AVX;
179
180
return result;
181
}
182
#endif
183
184
bool isSupported()
185
{
186
if (LUA_EXTRA_SIZE != 1)
187
return false;
188
189
if (sizeof(TValue) != 16)
190
return false;
191
192
if (sizeof(LuaNode) != 32)
193
return false;
194
195
// Windows CRT uses stack unwinding in longjmp so we have to use unwind data; on other platforms, it's only necessary for C++ EH.
196
#if defined(_WIN32)
197
if (!isUnwindSupported())
198
return false;
199
#else
200
if (!LUA_USE_LONGJMP && !isUnwindSupported())
201
return false;
202
#endif
203
204
#if defined(CODEGEN_TARGET_X64)
205
int cpuinfo[4] = {};
206
#ifdef _MSC_VER
207
__cpuid(cpuinfo, 1);
208
#else
209
__cpuid(1, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]);
210
#endif
211
212
// We require AVX1 support for VEX encoded XMM operations
213
// We also require SSE4.1 support for ROUNDSD but the AVX check below covers it
214
// https://en.wikipedia.org/wiki/CPUID#EAX=1:_Processor_Info_and_Feature_Bits
215
if ((cpuinfo[2] & (1 << 28)) == 0)
216
return false;
217
218
return true;
219
#elif defined(CODEGEN_TARGET_A64)
220
return true;
221
#else
222
return false;
223
#endif
224
}
225
226
} // namespace CodeGen
227
} // namespace Luau
228
229