Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/Compiler/src/Builtins.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 "Builtins.h"
3
4
#include "Luau/Bytecode.h"
5
#include "Luau/Compiler.h"
6
#include "Luau/Lexer.h"
7
8
#include <array>
9
10
LUAU_FASTFLAGVARIABLE(LuauIntegerFastcalls)
11
12
namespace Luau
13
{
14
namespace Compile
15
{
16
17
Builtin getBuiltin(AstExpr* node, const DenseHashMap<AstName, Global>& globals, const DenseHashMap<AstLocal*, Variable>& variables)
18
{
19
if (AstExprLocal* expr = node->as<AstExprLocal>())
20
{
21
const Variable* v = variables.find(expr->local);
22
23
return v && !v->written && v->init ? getBuiltin(v->init, globals, variables) : Builtin();
24
}
25
else if (AstExprIndexName* expr = node->as<AstExprIndexName>())
26
{
27
if (AstExprLocal* object = expr->expr->as<AstExprLocal>())
28
{
29
const Variable* v = variables.find(object->local);
30
31
// Local that is initialized and not modified might hold the built-in library itself
32
if (v && !v->written && v->init)
33
{
34
AstExprGlobal* object = nullptr;
35
36
// Look for patterns like 'local m = math' and 'local math = math or replacement'
37
// Fastcall is used in safe env where libraries like 'math' are built-in
38
// This means that if we are still in safe env, 'math' was truthy and local was initialized to the library value
39
// If safe env is false, 'math' could be a polyfill or something else and fastcall takes the fallback, preserving the behavior
40
if (AstExprGlobal* global = v->init->as<AstExprGlobal>())
41
object = global;
42
else if (AstExprBinary* cond = v->init->as<AstExprBinary>(); cond && cond->op == AstExprBinary::Or)
43
object = cond->left->as<AstExprGlobal>();
44
45
if (object)
46
return getGlobalState(globals, object->name) == Global::Default ? Builtin{object->name, expr->index} : Builtin();
47
}
48
}
49
50
if (AstExprGlobal* object = expr->expr->as<AstExprGlobal>())
51
{
52
return getGlobalState(globals, object->name) == Global::Default ? Builtin{object->name, expr->index} : Builtin();
53
}
54
else
55
{
56
return Builtin();
57
}
58
}
59
else if (AstExprGlobal* expr = node->as<AstExprGlobal>())
60
{
61
return getGlobalState(globals, expr->name) == Global::Default ? Builtin{AstName(), expr->name} : Builtin();
62
}
63
else
64
{
65
return Builtin();
66
}
67
}
68
69
static int getBuiltinFunctionId(const Builtin& builtin, const CompileOptions& options)
70
{
71
if (builtin.isGlobal("assert"))
72
return LBF_ASSERT;
73
74
if (builtin.isGlobal("type"))
75
return LBF_TYPE;
76
77
if (builtin.isGlobal("typeof"))
78
return LBF_TYPEOF;
79
80
if (builtin.isGlobal("rawset"))
81
return LBF_RAWSET;
82
if (builtin.isGlobal("rawget"))
83
return LBF_RAWGET;
84
if (builtin.isGlobal("rawequal"))
85
return LBF_RAWEQUAL;
86
if (builtin.isGlobal("rawlen"))
87
return LBF_RAWLEN;
88
89
if (builtin.isGlobal("unpack"))
90
return LBF_TABLE_UNPACK;
91
92
if (builtin.isGlobal("select"))
93
return LBF_SELECT_VARARG;
94
95
if (builtin.isGlobal("getmetatable"))
96
return LBF_GETMETATABLE;
97
if (builtin.isGlobal("setmetatable"))
98
return LBF_SETMETATABLE;
99
100
if (builtin.isGlobal("tonumber"))
101
return LBF_TONUMBER;
102
if (builtin.isGlobal("tostring"))
103
return LBF_TOSTRING;
104
105
if (builtin.object == "math")
106
{
107
if (builtin.method == "abs")
108
return LBF_MATH_ABS;
109
if (builtin.method == "acos")
110
return LBF_MATH_ACOS;
111
if (builtin.method == "asin")
112
return LBF_MATH_ASIN;
113
if (builtin.method == "atan2")
114
return LBF_MATH_ATAN2;
115
if (builtin.method == "atan")
116
return LBF_MATH_ATAN;
117
if (builtin.method == "ceil")
118
return LBF_MATH_CEIL;
119
if (builtin.method == "cosh")
120
return LBF_MATH_COSH;
121
if (builtin.method == "cos")
122
return LBF_MATH_COS;
123
if (builtin.method == "deg")
124
return LBF_MATH_DEG;
125
if (builtin.method == "exp")
126
return LBF_MATH_EXP;
127
if (builtin.method == "floor")
128
return LBF_MATH_FLOOR;
129
if (builtin.method == "fmod")
130
return LBF_MATH_FMOD;
131
if (builtin.method == "frexp")
132
return LBF_MATH_FREXP;
133
if (builtin.method == "ldexp")
134
return LBF_MATH_LDEXP;
135
if (builtin.method == "log10")
136
return LBF_MATH_LOG10;
137
if (builtin.method == "log")
138
return LBF_MATH_LOG;
139
if (builtin.method == "max")
140
return LBF_MATH_MAX;
141
if (builtin.method == "min")
142
return LBF_MATH_MIN;
143
if (builtin.method == "modf")
144
return LBF_MATH_MODF;
145
if (builtin.method == "pow")
146
return LBF_MATH_POW;
147
if (builtin.method == "rad")
148
return LBF_MATH_RAD;
149
if (builtin.method == "sinh")
150
return LBF_MATH_SINH;
151
if (builtin.method == "sin")
152
return LBF_MATH_SIN;
153
if (builtin.method == "sqrt")
154
return LBF_MATH_SQRT;
155
if (builtin.method == "tanh")
156
return LBF_MATH_TANH;
157
if (builtin.method == "tan")
158
return LBF_MATH_TAN;
159
if (builtin.method == "clamp")
160
return LBF_MATH_CLAMP;
161
if (builtin.method == "sign")
162
return LBF_MATH_SIGN;
163
if (builtin.method == "round")
164
return LBF_MATH_ROUND;
165
if (builtin.method == "lerp")
166
return LBF_MATH_LERP;
167
if (builtin.method == "isnan")
168
return LBF_MATH_ISNAN;
169
if (builtin.method == "isinf")
170
return LBF_MATH_ISINF;
171
if (builtin.method == "isfinite")
172
return LBF_MATH_ISFINITE;
173
}
174
175
if (builtin.object == "bit32")
176
{
177
if (builtin.method == "arshift")
178
return LBF_BIT32_ARSHIFT;
179
if (builtin.method == "band")
180
return LBF_BIT32_BAND;
181
if (builtin.method == "bnot")
182
return LBF_BIT32_BNOT;
183
if (builtin.method == "bor")
184
return LBF_BIT32_BOR;
185
if (builtin.method == "bxor")
186
return LBF_BIT32_BXOR;
187
if (builtin.method == "btest")
188
return LBF_BIT32_BTEST;
189
if (builtin.method == "extract")
190
return LBF_BIT32_EXTRACT;
191
if (builtin.method == "lrotate")
192
return LBF_BIT32_LROTATE;
193
if (builtin.method == "lshift")
194
return LBF_BIT32_LSHIFT;
195
if (builtin.method == "replace")
196
return LBF_BIT32_REPLACE;
197
if (builtin.method == "rrotate")
198
return LBF_BIT32_RROTATE;
199
if (builtin.method == "rshift")
200
return LBF_BIT32_RSHIFT;
201
if (builtin.method == "countlz")
202
return LBF_BIT32_COUNTLZ;
203
if (builtin.method == "countrz")
204
return LBF_BIT32_COUNTRZ;
205
if (builtin.method == "byteswap")
206
return LBF_BIT32_BYTESWAP;
207
}
208
209
if (builtin.object == "string")
210
{
211
if (builtin.method == "byte")
212
return LBF_STRING_BYTE;
213
if (builtin.method == "char")
214
return LBF_STRING_CHAR;
215
if (builtin.method == "len")
216
return LBF_STRING_LEN;
217
if (builtin.method == "sub")
218
return LBF_STRING_SUB;
219
}
220
221
if (builtin.object == "table")
222
{
223
if (builtin.method == "insert")
224
return LBF_TABLE_INSERT;
225
if (builtin.method == "unpack")
226
return LBF_TABLE_UNPACK;
227
}
228
229
if (builtin.object == "buffer")
230
{
231
if (builtin.method == "readi8")
232
return LBF_BUFFER_READI8;
233
if (builtin.method == "readu8")
234
return LBF_BUFFER_READU8;
235
if (builtin.method == "writei8" || builtin.method == "writeu8")
236
return LBF_BUFFER_WRITEU8;
237
if (builtin.method == "readi16")
238
return LBF_BUFFER_READI16;
239
if (builtin.method == "readu16")
240
return LBF_BUFFER_READU16;
241
if (builtin.method == "writei16" || builtin.method == "writeu16")
242
return LBF_BUFFER_WRITEU16;
243
if (builtin.method == "readi32")
244
return LBF_BUFFER_READI32;
245
if (builtin.method == "readu32")
246
return LBF_BUFFER_READU32;
247
if (builtin.method == "writei32" || builtin.method == "writeu32")
248
return LBF_BUFFER_WRITEU32;
249
if (builtin.method == "readf32")
250
return LBF_BUFFER_READF32;
251
if (builtin.method == "writef32")
252
return LBF_BUFFER_WRITEF32;
253
if (builtin.method == "readf64")
254
return LBF_BUFFER_READF64;
255
if (builtin.method == "writef64")
256
return LBF_BUFFER_WRITEF64;
257
}
258
259
if (builtin.object == "vector")
260
{
261
if (builtin.method == "create")
262
return LBF_VECTOR;
263
if (builtin.method == "magnitude")
264
return LBF_VECTOR_MAGNITUDE;
265
if (builtin.method == "normalize")
266
return LBF_VECTOR_NORMALIZE;
267
if (builtin.method == "cross")
268
return LBF_VECTOR_CROSS;
269
if (builtin.method == "dot")
270
return LBF_VECTOR_DOT;
271
if (builtin.method == "floor")
272
return LBF_VECTOR_FLOOR;
273
if (builtin.method == "ceil")
274
return LBF_VECTOR_CEIL;
275
if (builtin.method == "abs")
276
return LBF_VECTOR_ABS;
277
if (builtin.method == "sign")
278
return LBF_VECTOR_SIGN;
279
if (builtin.method == "clamp")
280
return LBF_VECTOR_CLAMP;
281
if (builtin.method == "min")
282
return LBF_VECTOR_MIN;
283
if (builtin.method == "max")
284
return LBF_VECTOR_MAX;
285
if (builtin.method == "lerp")
286
return LBF_VECTOR_LERP;
287
}
288
289
if (FFlag::LuauIntegerFastcalls && builtin.object == "integer")
290
{
291
if (builtin.method == "add")
292
return LBF_INTEGER_ADD;
293
if (builtin.method == "sub")
294
return LBF_INTEGER_SUB;
295
if (builtin.method == "mod")
296
return LBF_INTEGER_MOD;
297
if (builtin.method == "mul")
298
return LBF_INTEGER_MUL;
299
if (builtin.method == "div")
300
return LBF_INTEGER_DIV;
301
if (builtin.method == "idiv")
302
return LBF_INTEGER_IDIV;
303
if (builtin.method == "udiv")
304
return LBF_INTEGER_UDIV;
305
if (builtin.method == "rem")
306
return LBF_INTEGER_REM;
307
if (builtin.method == "urem")
308
return LBF_INTEGER_UREM;
309
if (builtin.method == "min")
310
return LBF_INTEGER_MIN;
311
if (builtin.method == "max")
312
return LBF_INTEGER_MAX;
313
if (builtin.method == "neg")
314
return LBF_INTEGER_NEG;
315
if (builtin.method == "create")
316
return LBF_INTEGER_CREATE;
317
if (builtin.method == "clamp")
318
return LBF_INTEGER_CLAMP;
319
if (builtin.method == "band")
320
return LBF_INTEGER_BAND;
321
if (builtin.method == "bor")
322
return LBF_INTEGER_BOR;
323
if (builtin.method == "bxor")
324
return LBF_INTEGER_BXOR;
325
if (builtin.method == "bnot")
326
return LBF_INTEGER_BNOT;
327
if (builtin.method == "btest")
328
return LBF_INTEGER_BTEST;
329
if (builtin.method == "bswap")
330
return LBF_INTEGER_BSWAP;
331
if (builtin.method == "lt")
332
return LBF_INTEGER_LT;
333
if (builtin.method == "le")
334
return LBF_INTEGER_LE;
335
if (builtin.method == "ult")
336
return LBF_INTEGER_ULT;
337
if (builtin.method == "ule")
338
return LBF_INTEGER_ULE;
339
if (builtin.method == "gt")
340
return LBF_INTEGER_GT;
341
if (builtin.method == "ge")
342
return LBF_INTEGER_GE;
343
if (builtin.method == "ugt")
344
return LBF_INTEGER_UGT;
345
if (builtin.method == "uge")
346
return LBF_INTEGER_UGE;
347
if (builtin.method == "lshift")
348
return LBF_INTEGER_LSHIFT;
349
if (builtin.method == "rshift")
350
return LBF_INTEGER_RSHIFT;
351
if (builtin.method == "arshift")
352
return LBF_INTEGER_ARSHIFT;
353
if (builtin.method == "lrotate")
354
return LBF_INTEGER_LROTATE;
355
if (builtin.method == "rrotate")
356
return LBF_INTEGER_RROTATE;
357
if (builtin.method == "countrz")
358
return LBF_INTEGER_COUNTRZ;
359
if (builtin.method == "countlz")
360
return LBF_INTEGER_COUNTLZ;
361
if (builtin.method == "extract")
362
return LBF_INTEGER_EXTRACT;
363
if (builtin.method == "tonumber")
364
return LBF_INTEGER_TONUMBER;
365
}
366
367
if (options.vectorCtor)
368
{
369
if (options.vectorLib)
370
{
371
if (builtin.isMethod(options.vectorLib, options.vectorCtor))
372
return LBF_VECTOR;
373
}
374
else
375
{
376
if (builtin.isGlobal(options.vectorCtor))
377
return LBF_VECTOR;
378
}
379
}
380
381
return -1;
382
}
383
384
struct BuiltinVisitor : AstVisitor
385
{
386
DenseHashMap<AstExprCall*, int>& result;
387
std::array<bool, 256> builtinIsDisabled;
388
389
const DenseHashMap<AstName, Global>& globals;
390
const DenseHashMap<AstLocal*, Variable>& variables;
391
392
const CompileOptions& options;
393
const AstNameTable& names;
394
395
BuiltinVisitor(
396
DenseHashMap<AstExprCall*, int>& result,
397
const DenseHashMap<AstName, Global>& globals,
398
const DenseHashMap<AstLocal*, Variable>& variables,
399
const CompileOptions& options,
400
const AstNameTable& names
401
)
402
: result(result)
403
, globals(globals)
404
, variables(variables)
405
, options(options)
406
, names(names)
407
{
408
builtinIsDisabled.fill(false);
409
410
if (const char* const* ptr = options.disabledBuiltins)
411
{
412
for (; *ptr; ++ptr)
413
{
414
if (const char* dot = strchr(*ptr, '.'))
415
{
416
AstName library = names.getWithType(*ptr, dot - *ptr).first;
417
AstName name = names.get(dot + 1);
418
419
if (library.value && name.value && getGlobalState(globals, name) == Global::Default)
420
{
421
Builtin builtin = Builtin{library, name};
422
423
if (int bfid = getBuiltinFunctionId(builtin, options); bfid >= 0)
424
builtinIsDisabled[bfid] = true;
425
}
426
}
427
else
428
{
429
if (AstName name = names.get(*ptr); name.value && getGlobalState(globals, name) == Global::Default)
430
{
431
Builtin builtin = Builtin{AstName(), name};
432
433
if (int bfid = getBuiltinFunctionId(builtin, options); bfid >= 0)
434
builtinIsDisabled[bfid] = true;
435
}
436
}
437
}
438
}
439
}
440
441
bool visit(AstExprCall* node) override
442
{
443
Builtin builtin = node->self ? Builtin() : getBuiltin(node->func, globals, variables);
444
if (builtin.empty())
445
return true;
446
447
int bfid = getBuiltinFunctionId(builtin, options);
448
449
if (bfid >= 0 && builtinIsDisabled[bfid])
450
bfid = -1;
451
452
// getBuiltinFunctionId optimistically assumes all select() calls are builtin but actually the second argument must be a vararg
453
if (bfid == LBF_SELECT_VARARG && !(node->args.size == 2 && node->args.data[1]->is<AstExprVarargs>()))
454
bfid = -1;
455
456
if (bfid >= 0)
457
result[node] = bfid;
458
459
return true; // propagate to nested calls
460
}
461
};
462
463
void analyzeBuiltins(
464
DenseHashMap<AstExprCall*, int>& result,
465
const DenseHashMap<AstName, Global>& globals,
466
const DenseHashMap<AstLocal*, Variable>& variables,
467
const CompileOptions& options,
468
AstNode* root,
469
const AstNameTable& names
470
)
471
{
472
BuiltinVisitor visitor{result, globals, variables, options, names};
473
root->visit(&visitor);
474
}
475
476
BuiltinInfo getBuiltinInfo(int bfid)
477
{
478
switch (LuauBuiltinFunction(bfid))
479
{
480
case LBF_NONE:
481
return {-1, -1};
482
483
case LBF_ASSERT:
484
return {-1, -1}; // assert() returns all values when first value is truthy
485
486
case LBF_MATH_ABS:
487
case LBF_MATH_ACOS:
488
case LBF_MATH_ASIN:
489
return {1, 1, BuiltinInfo::Flag_NoneSafe};
490
491
case LBF_MATH_ATAN2:
492
return {2, 1, BuiltinInfo::Flag_NoneSafe};
493
494
case LBF_MATH_ATAN:
495
case LBF_MATH_CEIL:
496
case LBF_MATH_COSH:
497
case LBF_MATH_COS:
498
case LBF_MATH_DEG:
499
case LBF_MATH_EXP:
500
case LBF_MATH_FLOOR:
501
return {1, 1, BuiltinInfo::Flag_NoneSafe};
502
503
case LBF_MATH_FMOD:
504
return {2, 1, BuiltinInfo::Flag_NoneSafe};
505
506
case LBF_MATH_FREXP:
507
return {1, 2, BuiltinInfo::Flag_NoneSafe};
508
509
case LBF_MATH_LDEXP:
510
return {2, 1, BuiltinInfo::Flag_NoneSafe};
511
512
case LBF_MATH_LOG10:
513
return {1, 1, BuiltinInfo::Flag_NoneSafe};
514
515
case LBF_MATH_LOG:
516
return {-1, 1}; // 1 or 2 parameters
517
518
case LBF_MATH_MAX:
519
case LBF_MATH_MIN:
520
return {-1, 1}; // variadic
521
522
case LBF_MATH_MODF:
523
return {1, 2, BuiltinInfo::Flag_NoneSafe};
524
525
case LBF_MATH_POW:
526
return {2, 1, BuiltinInfo::Flag_NoneSafe};
527
528
case LBF_MATH_RAD:
529
case LBF_MATH_SINH:
530
case LBF_MATH_SIN:
531
case LBF_MATH_SQRT:
532
case LBF_MATH_TANH:
533
case LBF_MATH_TAN:
534
return {1, 1, BuiltinInfo::Flag_NoneSafe};
535
536
case LBF_BIT32_ARSHIFT:
537
return {2, 1, BuiltinInfo::Flag_NoneSafe};
538
539
case LBF_BIT32_BAND:
540
return {-1, 1}; // variadic
541
542
case LBF_BIT32_BNOT:
543
return {1, 1, BuiltinInfo::Flag_NoneSafe};
544
545
case LBF_BIT32_BOR:
546
case LBF_BIT32_BXOR:
547
case LBF_BIT32_BTEST:
548
return {-1, 1}; // variadic
549
550
case LBF_BIT32_EXTRACT:
551
return {-1, 1}; // 2 or 3 parameters
552
553
case LBF_BIT32_LROTATE:
554
case LBF_BIT32_LSHIFT:
555
return {2, 1, BuiltinInfo::Flag_NoneSafe};
556
557
case LBF_BIT32_REPLACE:
558
return {-1, 1}; // 3 or 4 parameters
559
560
case LBF_BIT32_RROTATE:
561
case LBF_BIT32_RSHIFT:
562
return {2, 1, BuiltinInfo::Flag_NoneSafe};
563
564
case LBF_TYPE:
565
return {1, 1};
566
567
case LBF_STRING_BYTE:
568
return {-1, -1}; // 1, 2 or 3 parameters
569
570
case LBF_STRING_CHAR:
571
return {-1, 1}; // variadic
572
573
case LBF_STRING_LEN:
574
return {1, 1, BuiltinInfo::Flag_NoneSafe};
575
576
case LBF_TYPEOF:
577
return {1, 1};
578
579
case LBF_STRING_SUB:
580
return {-1, 1}; // 2 or 3 parameters
581
582
case LBF_MATH_CLAMP:
583
return {3, 1, BuiltinInfo::Flag_NoneSafe};
584
585
case LBF_MATH_SIGN:
586
case LBF_MATH_ROUND:
587
return {1, 1, BuiltinInfo::Flag_NoneSafe};
588
589
case LBF_RAWSET:
590
return {3, 1};
591
592
case LBF_RAWGET:
593
case LBF_RAWEQUAL:
594
return {2, 1};
595
596
case LBF_TABLE_INSERT:
597
return {-1, 0}; // 2 or 3 parameters
598
599
case LBF_TABLE_UNPACK:
600
return {-1, -1}; // 1, 2 or 3 parameters
601
602
case LBF_VECTOR:
603
return {-1, 1}; // 3 or 4 parameters in some configurations
604
605
case LBF_BIT32_COUNTLZ:
606
case LBF_BIT32_COUNTRZ:
607
return {1, 1, BuiltinInfo::Flag_NoneSafe};
608
609
case LBF_SELECT_VARARG:
610
return {-1, -1}; // variadic
611
612
case LBF_RAWLEN:
613
return {1, 1, BuiltinInfo::Flag_NoneSafe};
614
615
case LBF_BIT32_EXTRACTK:
616
return {3, 1, BuiltinInfo::Flag_NoneSafe};
617
618
case LBF_GETMETATABLE:
619
return {1, 1};
620
621
case LBF_SETMETATABLE:
622
return {2, 1};
623
624
case LBF_TONUMBER:
625
return {-1, 1}; // 1 or 2 parameters
626
627
case LBF_TOSTRING:
628
return {1, 1};
629
630
case LBF_BIT32_BYTESWAP:
631
return {1, 1, BuiltinInfo::Flag_NoneSafe};
632
633
case LBF_BUFFER_READI8:
634
case LBF_BUFFER_READU8:
635
case LBF_BUFFER_READI16:
636
case LBF_BUFFER_READU16:
637
case LBF_BUFFER_READI32:
638
case LBF_BUFFER_READU32:
639
case LBF_BUFFER_READF32:
640
case LBF_BUFFER_READF64:
641
return {2, 1, BuiltinInfo::Flag_NoneSafe};
642
643
case LBF_BUFFER_WRITEU8:
644
case LBF_BUFFER_WRITEU16:
645
case LBF_BUFFER_WRITEU32:
646
case LBF_BUFFER_WRITEF32:
647
case LBF_BUFFER_WRITEF64:
648
return {3, 0, BuiltinInfo::Flag_NoneSafe};
649
650
case LBF_VECTOR_MAGNITUDE:
651
case LBF_VECTOR_NORMALIZE:
652
return {1, 1, BuiltinInfo::Flag_NoneSafe};
653
case LBF_VECTOR_CROSS:
654
case LBF_VECTOR_DOT:
655
return {2, 1, BuiltinInfo::Flag_NoneSafe};
656
case LBF_VECTOR_FLOOR:
657
case LBF_VECTOR_CEIL:
658
case LBF_VECTOR_ABS:
659
case LBF_VECTOR_SIGN:
660
return {1, 1, BuiltinInfo::Flag_NoneSafe};
661
case LBF_VECTOR_CLAMP:
662
return {3, 1, BuiltinInfo::Flag_NoneSafe};
663
case LBF_VECTOR_MIN:
664
case LBF_VECTOR_MAX:
665
return {-1, 1}; // variadic
666
case LBF_VECTOR_LERP:
667
return {3, 1, BuiltinInfo::Flag_NoneSafe};
668
669
case LBF_MATH_LERP:
670
return {3, 1, BuiltinInfo::Flag_NoneSafe};
671
case LBF_MATH_ISNAN:
672
return {1, 1, BuiltinInfo::Flag_NoneSafe};
673
case LBF_MATH_ISINF:
674
return {1, 1, BuiltinInfo::Flag_NoneSafe};
675
case LBF_MATH_ISFINITE:
676
return {1, 1, BuiltinInfo::Flag_NoneSafe};
677
678
case LBF_INTEGER_BAND:
679
case LBF_INTEGER_BOR:
680
case LBF_INTEGER_BXOR:
681
case LBF_INTEGER_BTEST:
682
case LBF_INTEGER_MIN:
683
case LBF_INTEGER_MAX:
684
return {-1, 1}; // variadic
685
686
case LBF_INTEGER_EXTRACT:
687
return {-1, 1}; // 2 or 3 parameters
688
689
case LBF_INTEGER_BNOT:
690
case LBF_INTEGER_BSWAP:
691
case LBF_INTEGER_NEG:
692
case LBF_INTEGER_COUNTLZ:
693
case LBF_INTEGER_COUNTRZ:
694
case LBF_INTEGER_TONUMBER:
695
case LBF_INTEGER_CREATE:
696
return {1, 1, BuiltinInfo::Flag_NoneSafe};
697
698
case LBF_INTEGER_CLAMP:
699
return {3, 1, BuiltinInfo::Flag_NoneSafe};
700
701
case LBF_INTEGER_ADD:
702
case LBF_INTEGER_SUB:
703
case LBF_INTEGER_DIV:
704
case LBF_INTEGER_REM:
705
case LBF_INTEGER_UDIV:
706
case LBF_INTEGER_UREM:
707
case LBF_INTEGER_MOD:
708
case LBF_INTEGER_MUL:
709
case LBF_INTEGER_IDIV:
710
case LBF_INTEGER_LT:
711
case LBF_INTEGER_LE:
712
case LBF_INTEGER_ULT:
713
case LBF_INTEGER_ULE:
714
case LBF_INTEGER_GT:
715
case LBF_INTEGER_GE:
716
case LBF_INTEGER_UGT:
717
case LBF_INTEGER_UGE:
718
case LBF_INTEGER_LSHIFT:
719
case LBF_INTEGER_RSHIFT:
720
case LBF_INTEGER_ARSHIFT:
721
case LBF_INTEGER_LROTATE:
722
case LBF_INTEGER_RROTATE:
723
return {2, 1, BuiltinInfo::Flag_NoneSafe};
724
}
725
726
LUAU_UNREACHABLE();
727
}
728
729
} // namespace Compile
730
} // namespace Luau
731
732