luau/CodeGen/include/Luau/IrBuilder.h
vegorov-rbx 4b267aa5c5
Sync to upstream/release/574 (#910)
* Added a limit on how many instructions the Compiler can safely produce
(reported by @TheGreatSageEqualToHeaven)

C++ API Changes:
* With work started on read-only and write-only properties,
`Property::type` member variable has been replaced with `TypeId type()`
and `setType(TypeId)` functions.
* New `LazyType` unwrap callback now has a `void` return type, all
that's required from the callback is to write into `unwrapped` field.

In our work on the new type solver, the following issues were fixed:

* Work has started to support https://github.com/Roblox/luau/pull/77 and
https://github.com/Roblox/luau/pull/79
* Refinements are no longer applied on l-values, removing some
false-positive errors
* Improved overload resolution against expected result type
* `Frontend::prepareModuleScope` now works in the new solver
* Cofinite strings are now comparable

And these are the changes in native code generation (JIT):

* Fixed MIN_NUM and MAX_NUM constant fold when one of the arguments is
NaN
* Added constant folding for number conversions and bit operations
* Value spilling and rematerialization is now supported on arm64
* Improved FASTCALL2K IR generation to support second argument constant
* Added value numbering and load/store propagation optimizations
* Added STORE_VECTOR on arm64, completing the IR lowering on this target
2023-04-28 12:55:13 -07:00

118 lines
3.2 KiB
C++

// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
#pragma once
#include "Luau/Bytecode.h"
#include "Luau/Common.h"
#include "Luau/DenseHash.h"
#include "Luau/IrData.h"
#include <vector>
struct Proto;
typedef uint32_t Instruction;
namespace Luau
{
namespace CodeGen
{
struct AssemblyOptions;
struct IrBuilder
{
IrBuilder();
void buildFunctionIr(Proto* proto);
void rebuildBytecodeBasicBlocks(Proto* proto);
void translateInst(LuauOpcode op, const Instruction* pc, int i);
bool isInternalBlock(IrOp block);
void beginBlock(IrOp block);
void loadAndCheckTag(IrOp loc, uint8_t tag, IrOp fallback);
// Clones all instructions into the current block
// Source block that is cloned cannot use values coming in from a predecessor
void clone(const IrBlock& source, bool removeCurrentTerminator);
IrOp undef();
IrOp constBool(bool value);
IrOp constInt(int value);
IrOp constUint(unsigned value);
IrOp constDouble(double value);
IrOp constTag(uint8_t value);
IrOp constAny(IrConst constant, uint64_t asCommonKey);
IrOp cond(IrCondition cond);
IrOp inst(IrCmd cmd);
IrOp inst(IrCmd cmd, IrOp a);
IrOp inst(IrCmd cmd, IrOp a, IrOp b);
IrOp inst(IrCmd cmd, IrOp a, IrOp b, IrOp c);
IrOp inst(IrCmd cmd, IrOp a, IrOp b, IrOp c, IrOp d);
IrOp inst(IrCmd cmd, IrOp a, IrOp b, IrOp c, IrOp d, IrOp e);
IrOp inst(IrCmd cmd, IrOp a, IrOp b, IrOp c, IrOp d, IrOp e, IrOp f);
IrOp block(IrBlockKind kind); // Requested kind can be ignored if we are in an outlined sequence
IrOp blockAtInst(uint32_t index);
IrOp vmReg(uint8_t index);
IrOp vmConst(uint32_t index);
IrOp vmUpvalue(uint8_t index);
bool inTerminatedBlock = false;
bool activeFastcallFallback = false;
IrOp fastcallFallbackReturn;
IrFunction function;
uint32_t activeBlockIdx = ~0u;
std::vector<uint32_t> instIndexToBlock; // Block index at the bytecode instruction
// Similar to BytecodeBuilder, duplicate constants are removed used the same method
struct ConstantKey
{
IrConstKind kind;
// Note: this stores value* from IrConst; when kind is Double, this stores the same bits as double does but in uint64_t.
uint64_t value;
bool operator==(const ConstantKey& key) const
{
return kind == key.kind && value == key.value;
}
};
struct ConstantKeyHash
{
size_t operator()(const ConstantKey& key) const
{
// finalizer from MurmurHash64B
const uint32_t m = 0x5bd1e995;
uint32_t h1 = uint32_t(key.value);
uint32_t h2 = uint32_t(key.value >> 32) ^ (int(key.kind) * m);
h1 ^= h2 >> 18;
h1 *= m;
h2 ^= h1 >> 22;
h2 *= m;
h1 ^= h2 >> 17;
h1 *= m;
h2 ^= h1 >> 19;
h2 *= m;
// ... truncated to 32-bit output (normally hash is equal to (uint64_t(h1) << 32) | h2, but we only really need the lower 32-bit half)
return size_t(h2);
}
};
DenseHashMap<ConstantKey, uint32_t, ConstantKeyHash> constantMap;
};
} // namespace CodeGen
} // namespace Luau