1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-07 19:18:19 +02:00
Beef/IDEHelper/Compiler/CeMachine.h

1357 lines
No EOL
28 KiB
C++

#pragma once
#include "BfSystem.h"
#include "BfModule.h"
#include "BeefySysLib/util/Heap.h"
#include "BeefySysLib/util/AllocDebug.h"
#include "BfMangler.h"
NS_BF_BEGIN
class BfParser;
class BfReducer;
class BfMethodInstance;
class BeModule;
class BeContext;
class BeDbgLoc;
class BeType;
class BeValue;
class BeConstant;
class BeInst;
class BeDbgFile;
class BePhiInst;
class BeFunction;
class BeSwitchInst;
class BeGlobalVariable;
class CeMachine;
class CeFunction;
class CeDebugger;
class CeBreakpoint;
#define CEOP_SIZED(OPNAME) \
CeOp_##OPNAME##_8, \
CeOp_##OPNAME##_16, \
CeOp_##OPNAME##_32, \
CeOp_##OPNAME##_64, \
CeOp_##OPNAME##_X
#define CEOP_SIZED_FLOAT(OPNAME) \
CeOp_##OPNAME##_F32, \
CeOp_##OPNAME##_F64
#define CEOP_SIZED_NUMERIC(OPNAME) \
CeOp_##OPNAME##_I8, \
CeOp_##OPNAME##_I16, \
CeOp_##OPNAME##_I32, \
CeOp_##OPNAME##_I64
#define CEOP_SIZED_UNUMERIC(OPNAME) \
CeOp_##OPNAME##_U8, \
CeOp_##OPNAME##_U16, \
CeOp_##OPNAME##_U32, \
CeOp_##OPNAME##_U64
#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 CeErrorKind
{
CeErrorKind_None,
CeErrorKind_Error,
CeErrorKind_GlobalVariable,
CeErrorKind_FunctionPointer,
CeErrorKind_Intrinsic,
CeErrorKind_ObjectDynCheckFailed
};
enum CeOp : int16
{
CeOp_InvalidOp,
CeOp_Nop,
CeOp_DbgBreak,
CeOp_Ret,
CeOp_SetRetType,
CeOp_Jmp,
CeOp_JmpIf,
CeOp_JmpIfNot,
CeOp_Error,
CeOp_DynamicCastCheck,
CeOp_GetReflectType,
CeOp_GetString,
CeOp_Malloc,
CeOp_Free,
CeOp_MemSet,
CeOp_MemSet_Const,
CeOp_MemCpy,
CeOp_FrameAddr_32,
CeOp_FrameAddr_64,
CeOp_FrameAddrOfs_32,
CeOp_ConstData,
CeOp_ConstDataRef,
CeOp_Zero,
CEOP_SIZED(Const),
CEOP_SIZED(Load),
CEOP_SIZED(Store),
CEOP_SIZED(Move),
CEOP_SIZED(Push),
CEOP_SIZED(Pop),
CeOp_AdjustSP,
CeOp_AdjustSPNeg,
CeOp_AdjustSPConst,
CeOp_GetSP,
CeOp_SetSP,
CeOp_GetStaticField,
CeOp_GetStaticField_Initializer,
CeOp_GetMethod,
CeOp_GetMethod_Inner,
CeOp_GetMethod_Virt,
CeOp_GetMethod_IFace,
CeOp_Call,
CeOp_Conv_I8_I16,
CeOp_Conv_I8_I32,
CeOp_Conv_I8_I64,
CeOp_Conv_I8_F32,
CeOp_Conv_I8_F64,
CeOp_Conv_I16_I32,
CeOp_Conv_I16_I64,
CeOp_Conv_I16_F32,
CeOp_Conv_I16_F64,
CeOp_Conv_I32_I64,
CeOp_Conv_I32_F32,
CeOp_Conv_I32_F64,
CeOp_Conv_I64_F32,
CeOp_Conv_I64_F64,
CeOp_Conv_U8_U16,
CeOp_Conv_U8_U32,
CeOp_Conv_U8_U64,
CeOp_Conv_U8_F32,
CeOp_Conv_U8_F64,
CeOp_Conv_U16_U32,
CeOp_Conv_U16_U64,
CeOp_Conv_U16_F32,
CeOp_Conv_U16_F64,
CeOp_Conv_U32_U64,
CeOp_Conv_U32_F32,
CeOp_Conv_U32_F64,
CeOp_Conv_U64_F32,
CeOp_Conv_U64_F64,
CeOp_Conv_F32_I8,
CeOp_Conv_F32_I16,
CeOp_Conv_F32_I32,
CeOp_Conv_F32_I64,
CeOp_Conv_F32_U8,
CeOp_Conv_F32_U16,
CeOp_Conv_F32_U32,
CeOp_Conv_F32_U64,
CeOp_Conv_F32_F64,
CeOp_Conv_F64_I8,
CeOp_Conv_F64_I16,
CeOp_Conv_F64_I32,
CeOp_Conv_F64_I64,
CeOp_Conv_F64_U8,
CeOp_Conv_F64_U16,
CeOp_Conv_F64_U32,
CeOp_Conv_F64_U64,
CeOp_Conv_F64_F32,
CEOP_SIZED_NUMERIC_PLUSF(Abs),
CEOP_SIZED_NUMERIC_PLUSF(AddConst),
CEOP_SIZED_NUMERIC_PLUSF(Add),
CEOP_SIZED_NUMERIC_PLUSF(Sub),
CEOP_SIZED_NUMERIC_PLUSF(Mul),
CEOP_SIZED_NUMERIC_PLUSF(Div),
CEOP_SIZED_UNUMERIC(Div),
CEOP_SIZED_NUMERIC_PLUSF(Mod),
CEOP_SIZED_UNUMERIC(Mod),
CEOP_SIZED_NUMERIC(And),
CEOP_SIZED_NUMERIC(Or),
CEOP_SIZED_NUMERIC(Xor),
CEOP_SIZED_NUMERIC(Shl),
CEOP_SIZED_NUMERIC(Shr),
CEOP_SIZED_UNUMERIC(Shr),
CEOP_SIZED_FLOAT(Acos),
CEOP_SIZED_FLOAT(Asin),
CEOP_SIZED_FLOAT(Atan),
CEOP_SIZED_FLOAT(Atan2),
CEOP_SIZED_FLOAT(Ceiling),
CEOP_SIZED_FLOAT(Cos),
CEOP_SIZED_FLOAT(Cosh),
CEOP_SIZED_FLOAT(Exp),
CEOP_SIZED_FLOAT(Floor),
CEOP_SIZED_FLOAT(Log),
CEOP_SIZED_FLOAT(Log10),
CEOP_SIZED_FLOAT(Pow),
CEOP_SIZED_FLOAT(Round),
CEOP_SIZED_FLOAT(Sin),
CEOP_SIZED_FLOAT(Sinh),
CEOP_SIZED_FLOAT(Sqrt),
CEOP_SIZED_FLOAT(Tan),
CEOP_SIZED_FLOAT(Tanh),
CEOP_SIZED_NUMERIC_PLUSF(Cmp_EQ),
CEOP_SIZED_NUMERIC_PLUSF(Cmp_NE),
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(Cmp_SGT),
CEOP_SIZED_NUMERIC(Cmp_UGT),
CEOP_SIZED_NUMERIC_PLUSF(Cmp_SGE),
CEOP_SIZED_NUMERIC(Cmp_UGE),
CEOP_SIZED_NUMERIC_PLUSF(Neg),
CeOp_Not_I1,
CEOP_SIZED_NUMERIC(Not),
CeOp_COUNT
};
enum CeOperandKind
{
CeOperandKind_None,
CeOperandKind_FrameOfs,
CeOperandKind_AllocaAddr,
CeOperandKind_Block,
CeOperandKind_Immediate,
CeOperandKind_ConstStructTableIdx,
CeOperandKind_CallTableIdx
};
class CeOperand
{
public:
CeOperandKind mKind;
union
{
int mFrameOfs;
int mBlockIdx;
int mImmediate;
int mCallTableIdx;
int mStructTableIdx;
BeConstant* mConstant;
};
BeType* mType;
public:
CeOperand()
{
mKind = CeOperandKind_None;
mFrameOfs = 0;
mType = NULL;
}
operator bool() const
{
return mKind != CeOperandKind_None;
}
bool IsImmediate()
{
return mKind == CeOperandKind_Immediate;
}
};
struct CeEmitEntry
{
int mCodePos;
int mScope;
int mLine;
int mColumn;
};
struct CeDbgMethodRef
{
BfMethodRef mMethodRef;
String mNameMod;
String ToString();
bool operator==(const CeDbgMethodRef& second) const
{
return (mMethodRef == second.mMethodRef) && (mNameMod == second.mNameMod);
}
};
struct CeDbgScope
{
public:
enum MethodValFlag
{
MethodValFlag_MethodRef = 0x40000000,
MethodValFlag_IdxMask = 0x3FFFFFFF
};
public:
String mFilePath;
BfMethodRef mMethodRef;
int mInlinedAt;
int mMethodVal; // call table idx or methodRef idx, depending on MethodValFlag_MethodRef
public:
CeDbgScope()
{
mInlinedAt = -1;
mMethodVal = -1;
}
};
struct CeDbgInlineEntry
{
int mScope;
int mLine;
int mColumn;
};
class CeFunctionInfo
{
public:
String mName;
BfMethodInstance* mMethodInstance;
BfMethodRef mMethodRef;
CeFunction* mCeFunction;
int mRefCount;
public:
CeFunctionInfo()
{
mMethodInstance = NULL;
mCeFunction = NULL;
mRefCount = 0;
}
~CeFunctionInfo();
BfTypeInstance* GetOwner()
{
if (mMethodInstance != NULL)
return mMethodInstance->GetOwner();
return mMethodRef.mTypeInstance;
}
};
class CeCallEntry
{
public:
CeFunctionInfo* mFunctionInfo;
int mBindRevision;
CeFunction* mFunction;
public:
CeCallEntry()
{
mFunctionInfo = NULL;
mBindRevision = -1;
mFunction = NULL;
}
};
class CeStringEntry
{
public:
int mStringId;
int mBindExecuteId;
addr_ce mStringAddr;
public:
CeStringEntry()
{
mStringId = -1;
mBindExecuteId = -1;
mStringAddr = 0;
}
};
class CeInternalData
{
public:
enum Kind
{
Kind_None,
Kind_File,
Kind_FindFileData,
Kind_Spawn
};
public:
Kind mKind;
bool mReleased;
int mRefCount;
union
{
BfpFile* mFile;
BfpFindFileData* mFindFileData;
BfpSpawn* mSpawn;
};
CeInternalData()
{
mKind = Kind_None;
mReleased = false;
mRefCount = 1;
}
void AddRef()
{
BfpSystem_InterlockedExchangeAdd32((uint32*)&mRefCount, 1);
}
void Release()
{
if (BfpSystem_InterlockedExchangeAdd32((uint32*)&mRefCount, (uint32)-1) == 1)
delete this;
}
~CeInternalData();
};
enum CeFunctionKind
{
CeFunctionKind_NotSet,
CeFunctionKind_Normal,
CeFunctionKind_Extern,
CeFunctionKind_OOB,
CeFunctionKind_ObjectNotInitialized,
CeFunctionKind_Malloc,
CeFunctionKind_Free,
CeFunctionKind_DynCheckFailed,
CeFunctionKind_FatalError,
CeFunctionKind_DebugWrite,
CeFunctionKind_DebugWrite_Int,
CeFunctionKind_GetReflectTypeDeclById,
CeFunctionKind_GetReflectTypeDeclByName,
CeFunctionKind_GetReflectNextTypeDecl,
CeFunctionKind_GetBaseType,
CeFunctionKind_HasDeclaredMember,
CeFunctionKind_GetReflectType,
CeFunctionKind_GetReflectTypeById,
CeFunctionKind_GetWrappedType,
CeFunctionKind_GetReflectTypeByName,
CeFunctionKind_GetReflectSpecializedType,
CeFunctionKind_Type_ToString,
CeFunctionKind_TypeName_ToString,
CeFunctionKind_Namespace_ToString,
CeFunctionKind_Type_GetCustomAttribute,
CeFunctionKind_Field_GetCustomAttribute,
CeFunctionKind_Method_GetCustomAttribute,
CeFunctionKind_Type_GetCustomAttributeType,
CeFunctionKind_Field_GetCustomAttributeType,
CeFunctionKind_Method_GetCustomAttributeType,
CeFunctionKind_GetMethodCount,
CeFunctionKind_GetMethod,
CeFunctionKind_Method_ToString,
CeFunctionKind_Method_GetName,
CeFunctionKind_Method_GetInfo,
CeFunctionKind_Method_GetParamInfo,
CeFunctionKind_Method_GetGenericArg,
CeFunctionKind_Field_GetStatic,
CeFunctionKind_SetReturnType,
CeFunctionKind_Align,
CeFunctionKind_EmitTypeBody,
CeFunctionKind_EmitAddInterface,
CeFunctionKind_EmitMethodEntry,
CeFunctionKind_EmitMethodExit,
CeFunctionKind_EmitMixin,
CeFunctionKind_GetStringById,
CeFunctionKind_BfpDirectory_Create,
CeFunctionKind_BfpDirectory_Rename,
CeFunctionKind_BfpDirectory_Delete,
CeFunctionKind_BfpDirectory_GetCurrent,
CeFunctionKind_BfpDirectory_SetCurrent,
CeFunctionKind_BfpDirectory_Exists,
CeFunctionKind_BfpDirectory_GetSysDirectory,
CeFunctionKind_BfpFile_Close,
CeFunctionKind_BfpFile_Create,
CeFunctionKind_BfpFile_Flush,
CeFunctionKind_BfpFile_GetFileSize,
CeFunctionKind_BfpFile_Read,
CeFunctionKind_BfpFile_Release,
CeFunctionKind_BfpFile_Seek,
CeFunctionKind_BfpFile_Truncate,
CeFunctionKind_BfpFile_Write,
CeFunctionKind_BfpFile_GetTime_LastWrite,
CeFunctionKind_BfpFile_GetAttributes,
CeFunctionKind_BfpFile_SetAttributes,
CeFunctionKind_BfpFile_Copy,
CeFunctionKind_BfpFile_Rename,
CeFunctionKind_BfpFile_Delete,
CeFunctionKind_BfpFile_Exists,
CeFunctionKind_BfpFile_GetTempPath,
CeFunctionKind_BfpFile_GetTempFileName,
CeFunctionKind_BfpFile_GetFullPath,
CeFunctionKind_BfpFile_GetActualPath,
CeFunctionKind_BfpFindFileData_FindFirstFile,
CeFunctionKind_BfpFindFileData_FindNextFile,
CeFunctionKind_BfpFindFileData_GetFileName,
CeFunctionKind_BfpFindFileData_GetTime_LastWrite,
CeFunctionKind_BfpFindFileData_GetTime_Created,
CeFunctionKind_BfpFindFileData_GetTime_Access,
CeFunctionKind_BfpFindFileData_GetFileAttributes,
CeFunctionKind_BfpFindFileData_GetFileSize,
CeFunctionKind_BfpFindFileData_Release,
CeFunctionKind_BfpSpawn_Create,
CeFunctionKind_BfpSpawn_GetStdHandles,
CeFunctionKind_BfpSpawn_Kill,
CeFunctionKind_BfpSpawn_Release,
CeFunctionKind_BfpSpawn_WaitFor,
CeFunctionKind_BfpSystem_GetTimeStamp,
CeFunctionKind_Sleep,
CeFunctionKind_Char32_ToLower,
CeFunctionKind_Char32_ToUpper,
CeFunctionKind_Char32_IsLower,
CeFunctionKind_Char32_IsUpper,
CeFunctionKind_Char32_IsWhiteSpace_EX,
CeFunctionKind_Char32_IsLetterOrDigit,
CeFunctionKind_Char32_IsLetter,
CeFunctionKind_Char32_IsNumber,
CeFunctionKind_Double_Strtod,
CeFunctionKind_Double_Ftoa,
CeFunctionKind_Double_ToString,
CeFunctionKind_Float_ToString,
CeFunctionKind_Math_Abs,
CeFunctionKind_Math_Acos,
CeFunctionKind_Math_Asin,
CeFunctionKind_Math_Atan,
CeFunctionKind_Math_Atan2,
CeFunctionKind_Math_Ceiling,
CeFunctionKind_Math_Cos,
CeFunctionKind_Math_Cosh,
CeFunctionKind_Math_Exp,
CeFunctionKind_Math_Floor,
CeFunctionKind_Math_Log,
CeFunctionKind_Math_Log10,
CeFunctionKind_Math_Mod,
CeFunctionKind_Math_Pow,
CeFunctionKind_Math_Round,
CeFunctionKind_Math_Sin,
CeFunctionKind_Math_Sinh,
CeFunctionKind_Math_Sqrt,
CeFunctionKind_Math_Tan,
CeFunctionKind_Math_Tanh,
};
class CeConstStructFixup
{
public:
enum Kind
{
Kind_None,
Kind_StringPtr,
Kind_StringCharPtr,
};
public:
Kind mKind;
int mValue;
int mOffset;
};
class CeConstStructData
{
public:
Val128 mHash;
Array<uint8> mData;
Array<uint8> mFixedData;
Array<CeConstStructFixup> mFixups;
addr_ce mAddr;
int mBindExecuteId;
bool mQueueFixups;
public:
CeConstStructData()
{
mBindExecuteId = -1;
mAddr = 0;
mQueueFixups = false;
}
};
class CeInnerFunctionInfo
{
public:
String mName;
BeFunction* mBeFunction;
CeFunction* mOwner;
};
class CeStaticFieldEntry
{
public:
String mName;
int mTypeId;
int mSize;
addr_ce mAddr;
int mBindExecuteId;
public:
CeStaticFieldEntry()
{
mTypeId = -1;
mSize = 0;
mAddr = 0;
mBindExecuteId = -1;
}
};
class CeDbgVariable
{
public:
String mName;
CeOperand mValue;
BfType* mType;
int mScope;
bool mIsConst;
int mStartCodePos;
int mEndCodePos;
};
class CeDbgFunctionInfo
{
public:
Array<CeDbgVariable> mVariables;
};
class CeBreakpointBind
{
public:
CeOp mPrevOpCode;
CeBreakpoint* mBreakpoint;
};
class CeFunction
{
public:
enum InitializeState
{
InitializeState_None,
InitializeState_Initializing,
InitializeState_Initializing_ReEntry,
InitializeState_Initialized
};
public:
CeMachine* mCeMachine;
CeFunctionInfo* mCeFunctionInfo;
CeInnerFunctionInfo* mCeInnerFunctionInfo;
BfMethodInstance* mMethodInstance;
CeFunctionKind mFunctionKind;
InitializeState mInitializeState;
bool mFailed;
bool mIsVarReturn;
Array<uint8> mCode;
Array<CeDbgScope> mDbgScopes;
Array<CeDbgInlineEntry> mDbgInlineTable;
Array<CeDbgMethodRef> mDbgMethodRefTable;
Array<CeEmitEntry> mEmitTable;
Array<CeCallEntry> mCallTable;
Array<CeStringEntry> mStringTable;
Array<CeConstStructData> mConstStructTable;
Array<CeStaticFieldEntry> mStaticFieldTable;
Array<BfType*> mTypeTable;
Array<CeFunction*> mInnerFunctions;
Dictionary<int, CeBreakpointBind> mBreakpoints;
String mGenError;
int mFrameSize;
int mMaxReturnSize;
int mId;
int mBreakpointVersion;
CeDbgFunctionInfo* mDbgInfo;
public:
CeFunction()
{
mCeMachine = NULL;
mCeFunctionInfo = NULL;
mCeInnerFunctionInfo = NULL;
mFunctionKind = CeFunctionKind_NotSet;
mInitializeState = InitializeState_None;
mMethodInstance = NULL;
mFailed = false;
mIsVarReturn = false;
mFrameSize = 0;
mMaxReturnSize = 0;
mBreakpointVersion = 0;
mId = -1;
mDbgInfo = NULL;
}
~CeFunction();
BfTypeInstance* GetOwner();
void Print();
void UnbindBreakpoints();
CeEmitEntry* FindEmitEntry(int loc, int* entryIdx = NULL);
int SafeGetId();
};
enum CeEvalFlags
{
CeEvalFlags_None = 0,
CeEvalFlags_Cascade = 1,
CeEvalFlags_PersistantError = 2,
CeEvalFlags_DeferIfNotOnlyError = 4,
CeEvalFlags_NoRebuild = 8,
CeEvalFlags_ForceReturnThis = 0x10,
CeEvalFlags_IgnoreConstEncodeFailure = 0x20,
CeEvalFlags_DbgCall = 0x40
};
#define BF_CE_DEFAULT_STACK_SIZE 4*1024*1024
#define BF_CE_DEFAULT_HEAP_SIZE 128*1024
#define BF_CE_INITIAL_MEMORY BF_CE_DEFAULT_STACK_SIZE + BF_CE_DEFAULT_HEAP_SIZE
#define BF_CE_MAX_MEMORY 0x7FFFFFFF
#define BF_CE_MAX_CARRYOVER_MEMORY BF_CE_DEFAULT_STACK_SIZE * 2
#define BF_CE_MAX_CARRYOVER_HEAP 1024*1024
enum CeOperandInfoKind
{
CEOI_None,
CEOI_None8 = CEOI_None,
CEOI_None16 = CEOI_None,
CEOI_None32 = CEOI_None,
CEOI_None64 = CEOI_None,
CEOI_NoneF32 = CEOI_None,
CEOI_NoneF64 = CEOI_None,
CEOI_FrameRef,
CEOI_FrameRef8,
CEOI_FrameRef16,
CEOI_FrameRef32,
CEOI_FrameRef64,
CEOI_FrameRefF32,
CEOI_FrameRefF64,
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:
Dictionary<int, CeDbgVariable*> mVarMap;
CeFunction* mCeFunction;
String mStr;
uint8* mStart;
uint8* mPtr;
uint8* mEnd;
int mJmp;
public:
CeDumpContext()
{
mJmp = -1;
}
void DumpOperandInfo(CeOperandInfoKind operandInfoKind);
void Next();
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;
};
struct CeDbgInlineLookup
{
BeDbgFile* mDbgFile;
int mInlineAtIdx;
CeDbgInlineLookup(BeDbgFile* dbgFile, int inlineAtIdx)
{
mDbgFile = dbgFile;
mInlineAtIdx = inlineAtIdx;
}
CeDbgInlineLookup()
{
mDbgFile = NULL;
mInlineAtIdx = -1;
}
bool operator==(const CeDbgInlineLookup& second) const
{
return (mDbgFile == second.mDbgFile) && (mDbgFile == second.mDbgFile);
}
};
class CeBuilder
{
public:
CeBuilder* mParentBuilder;
CeMachine* mCeMachine;
CeFunction* mCeFunction;
BeFunction* mBeFunction;
CeOperand mReturnVal;
BeType* mIntPtrType;
int mPtrSize;
int mRecursiveDepth;
String mError;
BeDbgLoc* mCurDbgLoc;
Array<CeBlock> mBlocks;
Array<CeJumpEntry> mJumpTable;
Dictionary<BeValue*, CeOperand> mValueToOperand;
int mFrameSize;
Dictionary<BeDbgLoc*, int> mDbgInlineMap;
Dictionary<CeDbgInlineLookup, int> mDbgScopeMap;
Dictionary<CeDbgMethodRef, int> mDbgMethodRefMap;
Dictionary<BeFunction*, int> mFunctionMap;
Dictionary<int, int> mStringMap;
Dictionary<BeConstant*, int> mConstDataMap;
Dictionary<BeFunction*, int> mInnerFunctionMap;
Dictionary<BeGlobalVariable*, int> mStaticFieldMap;
Dictionary<String, BfFieldInstance*> mStaticFieldInstanceMap;
Dictionary<BeValue*, int> mDbgVariableMap;
public:
CeBuilder()
{
mParentBuilder = NULL;
mPtrSize = 0;
mRecursiveDepth = -1;
mCeFunction = NULL;
mBeFunction = NULL;
mCeMachine = NULL;
mCurDbgLoc = NULL;
mFrameSize = 0;
}
void Fail(const StringImpl& error);
CeOperand FrameAlloc(BeType* type);
CeOperand EmitConst(int64 val, int size);
CeErrorKind EmitConst(Array<uint8>& arr, BeConstant* constant);
CeOperand GetOperand(BeValue* value, bool allowAlloca = false, bool allowImmediate = false);
CeSizeClass GetSizeClass(int size);
int DbgCreateMethodRef(BfMethodInstance* methodInstance, const StringImpl& nameMod);
int GetCallTableIdx(BeFunction* beFunction, CeOperand* outOperand);
int GetCodePos();
void HandleParams();
void Emit(uint8 val);
void Emit(CeOp val);
void EmitSizedOp(CeOp val, int size);
void Emit(int32 val);
void Emit(int64 val);
void Emit(bool val);
void Emit(void* ptr, int size);
void EmitZeroes(int size);
void EmitJump(CeOp op, const CeOperand& block);
void EmitBinarySwitchSection(BeSwitchInst* switchInst, int startIdx, int endIdx);
CeOperand EmitLoad(CeOperand mcPtr, int loadRefCount = 1);
CeOperand EmitNumericCast(const CeOperand& ceValue, BeType* toType, bool valSigned, bool toSigned);
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 ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance* dupMethodInstance, bool forceIRWrites);
void Build();
};
class CeFrame
{
public:
CeFunction* mFunction;
addr_ce mStackAddr;
addr_ce mFrameAddr;
uint8* mInstPtr;
BfType* mReturnType;
public:
CeFrame()
{
mFunction = NULL;
mStackAddr = 0;
mFrameAddr = 0;
mInstPtr = NULL;
mReturnType = NULL;
}
int GetInstIdx()
{
return (int)(mInstPtr - &mFunction->mCode[0] - 2);
}
};
class CeStaticFieldInfo
{
public:
addr_ce mAddr;
public:
CeStaticFieldInfo()
{
mAddr = 0;
}
};
class CeAppendAllocInfo
{
public:
BfModule* mModule;
BfIRValue mAllocValue;
BfIRValue mAppendSizeValue;
};
class CeRebuildKey
{
public:
enum Kind
{
Kind_None,
Kind_File,
Kind_Directory,
Kind_TypeDeclListHash,
};
public:
Kind mKind;
String mString;
int mInt;
CeRebuildKey()
{
mKind = Kind_None;
mInt = 0;
}
bool operator==(const CeRebuildKey& other) const
{
return (mKind == other.mKind) && (mString == other.mString) && (mInt == other.mInt);
}
};
class CeRebuildValue
{
public:
union
{
uint64 mInt;
};
};
class CeEmitContext
{
public:
BfType* mType;
BfMethodInstance* mMethodInstance;
Array<int32> mInterfaces;
String mEmitData;
String mExitEmitData;
int32 mAlign;
bool mFailed;
CeEmitContext()
{
mType = NULL;
mMethodInstance = NULL;
mFailed = false;
mAlign = -1;
}
bool HasEmissions()
{
return !mEmitData.IsEmpty() || !mInterfaces.IsEmpty() || (mAlign != -1);
}
};
enum BfCeTypeEmitSourceKind : int8
{
BfCeTypeEmitSourceKind_Unknown,
BfCeTypeEmitSourceKind_Type,
BfCeTypeEmitSourceKind_Method
};
class BfCeTypeEmitSource
{
public:
BfCeTypeEmitSourceKind mKind;
int mSrcStart;
int mSrcEnd;
public:
BfCeTypeEmitSource()
{
mKind = BfCeTypeEmitSourceKind_Unknown;
mSrcStart = -1;
mSrcEnd = -1;
}
};
class BfCeTypeEmitEntry
{
public:
String mEmitData;
};
class BfCeTypeInfo
{
public:
Dictionary<int, BfCeTypeEmitEntry> mOnCompileMap;
Dictionary<int, BfCeTypeEmitEntry> mTypeIFaceMap;
Dictionary<int64, BfCeTypeEmitSource> mEmitSourceMap; // key is (extension<<32)|charId
Array<int> mPendingInterfaces;
Dictionary<CeRebuildKey, CeRebuildValue> mRebuildMap;
Val128 mHash;
bool mFastFinished;
bool mFailed;
bool mMayHaveUniqueEmitLocations;
int32 mAlign;
BfCeTypeInfo* mNext;
public:
BfCeTypeInfo()
{
mFastFinished = false;
mFailed = false;
mMayHaveUniqueEmitLocations = false;
mAlign = -1;
mNext = NULL;
}
};
class CeCallSource
{
public:
enum Kind
{
Kind_Unknown,
Kind_TypeInit,
Kind_TypeDone,
Kind_FieldInit,
Kind_MethodInit
};
public:
Kind mKind;
BfAstNode* mRefNode;
BfFieldInstance* mFieldInstance;
BfType* mOrigCalleeType;
public:
CeCallSource(BfAstNode* refNode)
{
mKind = Kind_Unknown;
mRefNode = refNode;
mFieldInstance = NULL;
mOrigCalleeType = NULL;
}
CeCallSource()
{
mKind = Kind_Unknown;
mRefNode = NULL;
mFieldInstance = NULL;
mOrigCalleeType = NULL;
}
};
class CeTypeDeclState
{
public:
Dictionary<int, addr_ce> mReflectDeclMap;
HashSet<BfTypeDef*> mIteratedTypeDefs;
bool mCheckedAllTypeDefs;
public:
CeTypeDeclState()
{
mCheckedAllTypeDefs = false;
}
};
class CeContext
{
public:
CeMachine* mCeMachine;
CeContext* mPrevContext;
int mReflectTypeIdOffset;
int mExecuteId;
CeEvalFlags mCurEvalFlags;
int mRecursiveDepth;
// These are only valid for the current execution
ContiguousHeap* mHeap;
Array<CeFrame> mCallStack;
Array<uint8> mMemory;
int mStackSize;
Dictionary<int, addr_ce> mStringMap;
Dictionary<int, addr_ce> mReflectMap;
CeTypeDeclState* mTypeDeclState;
Dictionary<Val128, addr_ce> mConstDataMap;
HashSet<int> mStaticCtorExecSet;
Dictionary<String, CeStaticFieldInfo> mStaticFieldMap;
Dictionary<int64, CeStaticFieldInfo> mStaticFieldIdMap;
Dictionary<int, CeInternalData*> mInternalDataMap;
int mCurHandleId;
BfMethodInstance* mCallerMethodInstance;
BfTypeInstance* mCallerTypeInstance;
BfTypeDef* mCallerActiveTypeDef;
BfMethodInstance* mCurMethodInstance;
BfType* mCurExpectingType;
CeCallSource* mCurCallSource;
BfModule* mCurModule;
CeFrame* mCurFrame;
CeEmitContext* mCurEmitContext;
String mWorkingDir;
public:
CeContext();
~CeContext();
BfError* Fail(const StringImpl& error);
BfError* Fail(const CeFrame& curFrame, const StringImpl& error);
void CalcWorkingDir();
void FixRelativePath(StringImpl& path);
bool AddRebuild(const CeRebuildKey& key, const CeRebuildValue& value);
void AddTypeSigRebuild(BfType* type);
void AddFileRebuild(const StringImpl& filePath);
uint8* CeMalloc(int size);
uint8* CeMallocZero(int size);
bool CeFree(addr_ce addr);
addr_ce CeAllocArray(BfArrayType* arrayType, int count, addr_ce& elemsAddr);
addr_ce GetReflectTypeDecl(int typeId);
addr_ce GetReflectType(int typeId);
addr_ce GetReflectType(const String& typeName, bool useDeclaration);
int GetTypeIdFromType(addr_ce typeAddr);
addr_ce GetReflectSpecializedType(addr_ce unspecializedType, addr_ce typeArgsSpanAddr);
addr_ce GetString(int stringId);
addr_ce GetString(const StringImpl& str);
addr_ce GetConstantData(BeConstant* constant);
BfType* GetBfType(int typeId);
BfType* GetBfType(BfIRType irType);
void PrepareConstStructEntry(CeConstStructData& constStructData);
bool CheckMemory(addr_ce addr, int32 size);
uint8* GetMemoryPtr(addr_ce addr, int32 size);
bool GetStringFromAddr(addr_ce strInstAddr, StringImpl& str);
bool GetStringFromStringView(addr_ce addr, StringImpl& str);
bool GetCustomAttribute(BfModule* module, BfIRConstHolder* constHolder, BfCustomAttributes* customAttributes, int attributeIdx, addr_ce resultAddr);
BfType* GetCustomAttributeType(BfCustomAttributes* customAttributes, int attributeIdx);
bool WriteConstant(BfModule* module, addr_ce addr, BfConstant* constant, BfType* type, bool isParams = false);
BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL);
BfIRValue CreateAttribute(BfAstNode* targetSrc, BfModule* module, BfIRConstHolder* constHolder, BfCustomAttribute* customAttribute, addr_ce ceAttrAddr = 0);
bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType, BfType*& castReturnType);
BfTypedValue Call(CeCallSource callSource, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
};
struct CeTypeInfo
{
Array<BfMethodInstance*> mMethodInstances;
int mRevision;
};
class CeStepState
{
public:
enum Kind
{
Kind_None,
Kind_StepOver,
Kind_StepOver_Asm,
Kind_StepInfo,
Kind_StepInfo_Asm,
Kind_StepOut,
Kind_StepOut_Asm,
Kind_Jmp,
Kind_Evaluate
};
Kind mKind;
int mNextInstIdx;
int mStartDepth;
public:
CeStepState()
{
mKind = Kind_None;
mNextInstIdx = -1;
mStartDepth = 0;
}
};
class CeMachine
{
public:
Dictionary<BfMethodInstance*, CeFunctionInfo*> mFunctions;
Dictionary<String, CeFunctionInfo*> mNamedFunctionMap;
Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit and debugging
Dictionary<BfType*, CeTypeInfo> mTypeInfoMap;
HashSet<BfMethodInstance*> mMethodInstanceSet;
HashSet<BfFieldInstance*> mFieldInstanceSet;
Array<CeContext*> mContextList;
BfCompiler* mCompiler;
BfModule* mCeModule;
int mRevision;
int mMethodBindRevision;
int mRevisionExecuteTime;
int mCurFunctionId;
int mExecuteId;
int mCurRecursiveDepth;
CeAppendAllocInfo* mAppendAllocInfo;
CeContext* mCurContext;
CeEmitContext* mCurEmitContext;
CeCallSource* mCurCallSource;
CeBuilder* mCurBuilder;
CeFunction* mPreparingFunction;
BfParser* mTempParser;
BfReducer* mTempReducer;
BfPassInstance* mTempPassInstance;
CritSect mCritSect;
SyncEvent mDebugEvent;
CeStepState mStepState;
CeDebugger* mDebugger;
bool mDbgPaused;
bool mSpecialCheck;
bool mDbgWantBreak;
String mFailString;
public:
CeMachine(BfCompiler* compiler);
~CeMachine();
void Fail(const StringImpl& error);
bool HasFailed();
void Init();
BeContext* GetBeContext();
BeModule* GetBeModule();
int GetInstSize(CeFunction* ceFunction, int instIdx);
void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo);
void RemoveFunc(CeFunction* ceFunction);
void RemoveMethod(BfMethodInstance* methodInstance);
void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction);
CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal, CeContext* ceContext, CeBuilder* ceBuilder);
void CheckFunctionKind(CeFunction* ceFunction);
void PrepareFunction(CeFunction* methodInstance, CeBuilder* parentBuilder);
void MapFunctionId(CeFunction* ceFunction);
void CheckFunctions();
CeFunction* GetFunction(BfMethodInstance* methodInstance, BfIRValue func, bool& added);
CeFunction* GetPreparedFunction(BfMethodInstance* methodInstance);
CeTypeInfo* GetTypeInfo(BfType* type);
BfMethodInstance* GetMethodInstance(int64 methodHandle);
BfFieldInstance* GetFieldInstance(int64 fieldHandle);
public:
void CompileStarted();
void CompileDone();
CeFunction* QueueMethod(BfMethodInstance* methodInstance, BfIRValue func);
void QueueMethod(BfModuleMethodInstance moduleMethodInstance);
void QueueStaticField(BfFieldInstance* fieldInstance, const StringImpl& mangledFieldName);
void ClearTypeData(BfTypeInstance* typeInstance);
void SetAppendAllocInfo(BfModule* module, BfIRValue allocValue, BfIRValue appendSizeValue);
void ClearAppendAllocInfo();
CeContext* AllocContext();
void ReleaseContext(CeContext* context);
BfTypedValue Call(CeCallSource callSource, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
BfError* FailCurrent(BfModule* srcModule, const StringImpl& error, BfAstNode* refNode);
void FailCurrentMoreInfo(const StringImpl& error, BfAstNode* refNode);
};
NS_BF_END
namespace std
{
template <>
struct hash<Beefy::CeRebuildKey>
{
size_t operator()(const Beefy::CeRebuildKey& key) const
{
return BeefHash<Beefy::String>()(key.mString) ^ (size_t)key.mKind;
}
};
template <>
struct hash<Beefy::CeDbgInlineLookup>
{
size_t operator()(const Beefy::CeDbgInlineLookup& key) const
{
return (intptr)key.mDbgFile ^ (intptr)key.mInlineAtIdx;
}
};
template <>
struct hash<Beefy::CeDbgMethodRef>
{
size_t operator()(const Beefy::CeDbgMethodRef& key) const
{
return BeefHash<Beefy::BfMethodRef>()(key.mMethodRef) ^ BeefHash<Beefy::String>()(key.mNameMod);
}
};
}