mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
359 lines
6.2 KiB
C++
359 lines
6.2 KiB
C++
#pragma once
|
|
|
|
#include "BfSystem.h"
|
|
#include "BfModule.h"
|
|
|
|
NS_BF_BEGIN
|
|
|
|
class BfMethodInstance;
|
|
class BeDbgLoc;
|
|
class BeType;
|
|
class BeValue;
|
|
class BeInst;
|
|
class BeDbgFile;
|
|
class BePhiInst;
|
|
class BeFunction;
|
|
class BeSwitchInst;
|
|
class CeMachine;
|
|
class CeFunction;
|
|
|
|
#define CEOP_SIZED(OPNAME) \
|
|
CeOp_##OPNAME##_8, \
|
|
CeOp_##OPNAME##_16, \
|
|
CeOp_##OPNAME##_32, \
|
|
CeOp_##OPNAME##_64, \
|
|
CeOp_##OPNAME##_X
|
|
|
|
#define CEOP_SIZED_NUMERIC(OPNAME) \
|
|
CeOp_##OPNAME##_I8, \
|
|
CeOp_##OPNAME##_I16, \
|
|
CeOp_##OPNAME##_I32, \
|
|
CeOp_##OPNAME##_I64
|
|
|
|
#define CEOP_SIZED_NUMERIC_PLUSF(OPNAME) \
|
|
CeOp_##OPNAME##_I8, \
|
|
CeOp_##OPNAME##_I16, \
|
|
CeOp_##OPNAME##_I32, \
|
|
CeOp_##OPNAME##_I64, \
|
|
CeOp_##OPNAME##_F32, \
|
|
CeOp_##OPNAME##_F64
|
|
|
|
enum CeOp : int16
|
|
{
|
|
CeOp_InvalidOp,
|
|
CeOp_Ret,
|
|
CeOp_Jmp,
|
|
CeOp_JmpIf,
|
|
CeOp_JmpIfNot,
|
|
|
|
CeOp_FrameAddr32,
|
|
CeOp_FrameAddr64,
|
|
|
|
CeOp_Zero,
|
|
CEOP_SIZED(Const),
|
|
CEOP_SIZED(Load),
|
|
CEOP_SIZED(Store),
|
|
CEOP_SIZED(Move),
|
|
CEOP_SIZED(Push),
|
|
CEOP_SIZED(Pop),
|
|
|
|
CeOp_AdjustSP,
|
|
CeOp_Call,
|
|
|
|
CeOp_Conv_I32_I64,
|
|
|
|
CEOP_SIZED_NUMERIC_PLUSF(AddConst),
|
|
CEOP_SIZED_NUMERIC_PLUSF(Add),
|
|
CEOP_SIZED_NUMERIC_PLUSF(Sub),
|
|
CEOP_SIZED_NUMERIC_PLUSF(Mul),
|
|
CEOP_SIZED_NUMERIC_PLUSF(SDiv),
|
|
CEOP_SIZED_NUMERIC(UDiv),
|
|
CEOP_SIZED_NUMERIC_PLUSF(SMod),
|
|
CEOP_SIZED_NUMERIC(UMod),
|
|
CEOP_SIZED_NUMERIC_PLUSF(Cmp_EQ),
|
|
CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLT),
|
|
CEOP_SIZED_NUMERIC(Cmp_ULT),
|
|
CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLE),
|
|
CEOP_SIZED_NUMERIC(Cmp_ULE),
|
|
|
|
CEOP_SIZED_NUMERIC_PLUSF(Neg),
|
|
|
|
CeOp_COUNT
|
|
};
|
|
|
|
struct CeEmitEntry
|
|
{
|
|
int mCodePos;
|
|
int mFile;
|
|
int mLine;
|
|
int mColumn;
|
|
};
|
|
|
|
class CeCallEntry
|
|
{
|
|
public:
|
|
String mFunctionName;
|
|
int mBindRevision;
|
|
CeFunction* mFunction;
|
|
|
|
public:
|
|
CeCallEntry()
|
|
{
|
|
mBindRevision = -1;
|
|
mFunction = NULL;
|
|
}
|
|
};
|
|
|
|
class CeFunction
|
|
{
|
|
public:
|
|
BfMethodInstance* mMethodInstance;
|
|
String mName;
|
|
bool mInitialized;
|
|
bool mFailed;
|
|
Array<uint8> mCode;
|
|
Array<String> mFiles;
|
|
Array<CeEmitEntry> mEmitTable;
|
|
Array<CeCallEntry> mCallTable;
|
|
String mGenError;
|
|
int mFrameSize;
|
|
|
|
public:
|
|
CeFunction()
|
|
{
|
|
mInitialized = false;
|
|
mMethodInstance = NULL;
|
|
mFailed = false;
|
|
mFrameSize = 0;
|
|
}
|
|
};
|
|
|
|
enum CeEvalFlags
|
|
{
|
|
CeEvalFlags_None = 0
|
|
};
|
|
|
|
enum CeOperandKind
|
|
{
|
|
CeOperandKind_None,
|
|
CeOperandKind_FrameOfs,
|
|
CeOperandKind_AllocaAddr,
|
|
CeOperandKind_Block,
|
|
CeOperandKind_Immediate
|
|
};
|
|
|
|
class CeOperand
|
|
{
|
|
public:
|
|
CeOperandKind mKind;
|
|
union
|
|
{
|
|
int mFrameOfs;
|
|
int mBlockIdx;
|
|
int mImmediate;
|
|
};
|
|
BeType* mType;
|
|
|
|
public:
|
|
CeOperand()
|
|
{
|
|
mKind = CeOperandKind_None;
|
|
mFrameOfs = 0;
|
|
mType = NULL;
|
|
}
|
|
|
|
operator bool() const
|
|
{
|
|
return mKind != CeOperandKind_None;
|
|
}
|
|
|
|
bool IsImmediate()
|
|
{
|
|
return mKind == CeOperandKind_Immediate;
|
|
}
|
|
};
|
|
|
|
#define BF_CE_STACK_SIZE 1024*1024
|
|
|
|
enum CeOperandInfoKind
|
|
{
|
|
CEOI_None,
|
|
CEOI_FrameRef,
|
|
CEOI_IMM8,
|
|
CEOI_IMM16,
|
|
CEOI_IMM32,
|
|
CEOI_IMM64,
|
|
CEOI_IMMF32,
|
|
CEOI_IMMF64,
|
|
CEOI_IMM_VAR,
|
|
CEOI_JMPREL
|
|
};
|
|
|
|
enum CeSizeClass
|
|
{
|
|
CeSizeClass_8,
|
|
CeSizeClass_16,
|
|
CeSizeClass_32,
|
|
CeSizeClass_64,
|
|
CeSizeClass_X,
|
|
};
|
|
|
|
class CeDumpContext
|
|
{
|
|
|
|
|
|
public:
|
|
CeFunction* mCeFunction;
|
|
String mStr;
|
|
uint8* mStart;
|
|
uint8* mPtr;
|
|
uint8* mEnd;
|
|
|
|
public:
|
|
void DumpOperandInfo(CeOperandInfoKind operandInfoKind);
|
|
|
|
void Dump();
|
|
};
|
|
|
|
struct CePhiOutgoing
|
|
{
|
|
BeValue* mPhiValue;
|
|
BePhiInst* mPhiInst;
|
|
int mPhiBlockIdx;
|
|
};
|
|
|
|
class CeBlock
|
|
{
|
|
public:
|
|
int mEmitOfs;
|
|
Array<CePhiOutgoing> mPhiOutgoing;
|
|
|
|
public:
|
|
CeBlock()
|
|
{
|
|
mEmitOfs = -1;
|
|
}
|
|
};
|
|
|
|
class CeJumpEntry
|
|
{
|
|
public:
|
|
int mEmitPos;
|
|
int mBlockIdx;
|
|
};
|
|
|
|
class CeBuilder
|
|
{
|
|
public:
|
|
CeMachine* mCeMachine;
|
|
CeFunction* mCeFunction;
|
|
BeFunction* mBeFunction;
|
|
CeOperand mReturnVal;
|
|
BeType* mIntPtrType;
|
|
int mPtrSize;
|
|
|
|
String mError;
|
|
BeDbgLoc* mCurDbgLoc;
|
|
Array<CeBlock> mBlocks;
|
|
Array<CeJumpEntry> mJumpTable;
|
|
Dictionary<BeValue*, CeOperand> mValueToOperand;
|
|
int mFrameSize;
|
|
Dictionary<BeDbgFile*, int> mDbgFileMap;
|
|
Dictionary<BeFunction*, int> mFunctionMap;
|
|
|
|
public:
|
|
CeBuilder()
|
|
{
|
|
mPtrSize = 0;
|
|
mCeFunction = NULL;
|
|
mBeFunction = NULL;
|
|
mCeMachine = NULL;
|
|
mCurDbgLoc = NULL;
|
|
mFrameSize = 0;
|
|
}
|
|
|
|
void Fail(const StringImpl& error);
|
|
|
|
CeOperand FrameAlloc(BeType* type);
|
|
CeOperand GetOperand(BeValue* value, bool allowAlloca = false, bool allowImmediate = false);
|
|
CeSizeClass GetSizeClass(int size);
|
|
int GetCodePos();
|
|
|
|
void HandleParams();
|
|
|
|
void Emit(uint8 val);
|
|
void Emit(CeOp val);
|
|
void Emit(int32 val);
|
|
void Emit(bool val);
|
|
void Emit(void* ptr, int size);
|
|
void EmitJump(CeOp op, const CeOperand& block);
|
|
void EmitBinarySwitchSection(BeSwitchInst* switchInst, int startIdx, int endIdx);
|
|
|
|
void EmitFrameOffset(const CeOperand& val);
|
|
void FlushPhi(CeBlock* ceBlock, int targetBlockIdx);
|
|
|
|
void EmitBinaryOp(CeOp iOp, CeOp fOp, const CeOperand& lhs, const CeOperand& rhs, CeOperand& result);
|
|
void EmitUnaryOp(CeOp iOp, CeOp fOp, const CeOperand& val, CeOperand& result);
|
|
void EmitSizedOp(CeOp op, const CeOperand& operand, CeOperand* result, bool allowNonStdSize);
|
|
void Build();
|
|
};
|
|
|
|
class CeFrame
|
|
{
|
|
public:
|
|
CeFunction* mFunction;
|
|
uint8* mStackPtr;
|
|
uint8* mFramePtr;
|
|
uint8* mInstPtr;
|
|
|
|
public:
|
|
CeFrame()
|
|
{
|
|
mFunction = NULL;
|
|
mStackPtr = NULL;
|
|
mFramePtr = NULL;
|
|
mInstPtr = NULL;
|
|
}
|
|
};
|
|
|
|
class CeMachine
|
|
{
|
|
public:
|
|
Dictionary<BfMethodInstance*, CeFunction*> mFunctions;
|
|
Dictionary<String, CeFunction*> mNamedFunctionMap;
|
|
BfCompiler* mCompiler;
|
|
BfModule* mCeModule;
|
|
int mRevision;
|
|
|
|
Array<CeFrame> mCallStack;
|
|
Array<uint8> mMemory;
|
|
uint8* mStackMin;
|
|
Array<CeFunction*> mWorkQueue;
|
|
|
|
BfAstNode* mCurTargetSrc;
|
|
BfModule* mCurModule;
|
|
|
|
public:
|
|
CeMachine(BfCompiler* compiler);
|
|
~CeMachine();
|
|
|
|
void Fail(const CeFrame& curFrame, const StringImpl& error);
|
|
|
|
void Init();
|
|
void RemoveMethod(BfMethodInstance* methodInstance);
|
|
int GetConstantSize(BfConstant* constant);
|
|
void WriteConstant(uint8* ptr, BfConstant* constant);
|
|
void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction);
|
|
bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr);
|
|
|
|
void PrepareFunction(CeFunction* methodInstance);
|
|
void ProcessWorkQueue();
|
|
CeFunction* GetFunction(BfMethodInstance* methodInstance, bool& added);
|
|
|
|
public:
|
|
void CompileStarted();
|
|
void QueueMethod(BfMethodInstance* methodInstance);
|
|
BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags);
|
|
};
|
|
|
|
NS_BF_END
|