#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 HostIrHooks;
struct IrBuilder
{
IrBuilder(const HostIrHooks& hostHooks);
void buildFunctionIr(Proto* proto);
void rebuildBytecodeBasicBlocks(Proto* proto);
void translateInst(LuauOpcode op, const Instruction* pc, int i);
void handleFastcallFallback(IrOp fallbackOrUndef, const Instruction* pc, int i);
bool isInternalBlock(IrOp block);
void beginBlock(IrOp block);
void loadAndCheckTag(IrOp loc, uint8_t tag, IrOp fallback);
void checkSafeEnv(int pcpos);
void clone(std::vector<uint32_t> sourceIdxs, bool removeCurrentTerminator);
IrOp undef();
IrOp constInt(int value);
IrOp constUint(unsigned value);
IrOp constImport(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, const IrOps& ops);
IrOp inst(IrCmd cmd, std::initializer_list<IrOp> ops);
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 inst(IrCmd cmd, IrOp a, IrOp b, IrOp c, IrOp d, IrOp e, IrOp f, IrOp g);
IrOp block(IrBlockKind kind);
IrOp blockAtInst(uint32_t index);
IrOp fallbackBlock(uint32_t pcpos);
IrOp vmReg(uint8_t index);
IrOp vmConst(uint32_t index);
IrOp vmUpvalue(uint8_t index);
IrOp vmExit(uint32_t pcpos);
const HostIrHooks& hostHooks;
bool inTerminatedBlock = false;
bool interruptRequested = false;
bool activeFastcallFallback = false;
IrOp fastcallFallbackReturn;
int cmdSkipTarget = -1;
IrFunction function;
uint32_t activeBlockIdx = ~0u;
std::vector<uint32_t> instIndexToBlock;
struct LoopInfo
{
IrOp step;
int startpc = 0;
};
std::vector<LoopInfo> numericLoopStack;
struct ConstantKey
{
IrConstKind kind;
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
{
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;
return size_t(h2);
}
};
DenseHashMap<ConstantKey, uint32_t, ConstantKeyHash> constantMap;
};
}
}