1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00
Beef/BeefLibs/corlib/src/Runtime.bf
2020-09-04 08:09:04 -07:00

331 lines
8.3 KiB
Beef

#if BF_ENABLE_OBJECT_DEBUG_FLAGS || BF_DEBUG_ALLOC
#define BF_DBG_RUNTIME
#endif
namespace System
{
[StaticInitPriority(100)]
class Runtime
{
const int32 cVersion = 8;
[CRepr, AlwaysInclude]
struct BfDebugMessageData
{
enum MessageType : int32
{
None = 0,
Error = 1,
ProfilerCmd = 2
};
MessageType mMessageType;
int32 mStackWindbackCount;
int32 mBufferParamLen;
char8* mBufferParam;
void* mPCOverride;
char8* mBufferPtr = null;
int mStrSize = 0;
[CLink]
public static BfDebugMessageData gBfDebugMessageData;
public static ~this()
{
if (gBfDebugMessageData.mBufferPtr != null)
{
Internal.Free(gBfDebugMessageData.mBufferPtr);
gBfDebugMessageData.mBufferPtr = null;
gBfDebugMessageData.mStrSize = 0;
}
}
public void SetupError(char8* str, int32 stackWindbackCount = 0) mut
{
mMessageType = .Error;
mStackWindbackCount = stackWindbackCount;
int size = Internal.CStrLen(str) + 1;
if (mStrSize < size)
{
if (mBufferPtr != null)
Internal.Free(mBufferPtr);
mStrSize = size;
mBufferPtr = (char8*)Internal.Malloc(mStrSize);
}
Internal.MemCpy(mBufferPtr, str, size);
mBufferParam = mBufferPtr;
mBufferParamLen = (int32)size - 1;
mPCOverride = null;
}
public void SetupProfilerCmd(char8* str) mut
{
mMessageType = .ProfilerCmd;
mStackWindbackCount = 0;
int size = Internal.CStrLen(str) + 1;
if (mStrSize < size)
{
if (mBufferPtr != null)
Internal.Free(mBufferPtr);
mStrSize = size;
mBufferPtr = (char8*)Internal.Malloc(mStrSize);
}
Internal.MemCpy(mBufferPtr, str, size);
mBufferParam = mBufferPtr;
mBufferParamLen = (int32)size - 1;
mPCOverride = null;
}
public void Fatal() mut
{
var str = scope String();
str.Reference(mBufferPtr, mBufferParamLen, 0);
Internal.FatalError(str, -1);
}
public void Clear() mut
{
mMessageType = .None;
if (mBufferPtr != null)
mBufferPtr[0] = 0;
mBufferParamLen = 0;
}
}
struct BfRtCallbacks
{
public static BfRtCallbacks sCallbacks = .();
function void* (int size) mAlloc;
function void (void* ptr) mFree;
function void (Object obj) mObject_Delete;
function void (Object obj, String str) mObject_ToString;
function Type (Object obj) mObject_GetType;
function void (Object obj) mObject_GCMarkMembers;
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
function void (Type type, String str) mType_GetFullName;
function String () mString_Alloc;
function char8* (String str) mString_ToCStr;
function Object () mThread_Alloc;
function Object () mThread_GetMainThread;
function void (Object thread) mThread_ThreadProc;
function void* (Object thread) mThread_GetInternalThread;
function void (Object thread, void* internalThread) mThread_SetInternalThread;
function bool (Object thread) mThread_IsAutoDelete;
function void (Object thread) mThread_AutoDelete;
function int32 (Object thread) mThread_GetMaxStackSize;
function void () mGC_MarkAllStaticMembers;
function bool () mGC_CallRootCallbacks;
function void () mGC_Shutdown;
function void (char8* str) mSetErrorString;
function void (char8* str, int32 stackWindbackCount) mDebugMessageData_SetupError;
function void (char8* str) mDebugMessageData_SetupProfilerCmd;
function void () mDebugMessageData_Fatal;
function void () mDebugMessageData_Clear;
static void* Alloc(int size)
{
return Internal.Malloc(size);
}
static void Free(void* ptr)
{
Internal.Free(ptr);
}
static void Object_Delete(Object obj)
{
delete obj;
}
static void Object_ToString(Object obj, String str)
{
#if BF_DBG_RUNTIME
obj.ToString(str);
#endif
}
static Type Object_GetType(Object obj)
{
#if BF_DBG_RUNTIME
return obj.[Friend]RawGetType();
#else
return null;
#endif
}
static void Object_GCMarkMembers(Object obj)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
obj.[Friend, DisableObjectAccessChecks]GCMarkMembers();
#endif
}
static Object Object_DynamicCastToTypeId(Object obj, int32 typeId)
{
#if BF_DYNAMIC_CAST_CHECK
return obj.DynamicCastToTypeId(typeId);
#else
return null;
#endif
}
static void Type_GetFullName(Type type, String str)
{
#if BF_DBG_RUNTIME
type.GetFullName(str);
#else
//
#endif
}
static String String_Alloc()
{
return new String();
}
static char8* String_ToCStr(String str)
{
return str.CStr();
}
static void GC_MarkAllStaticMembers()
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
GC.[Friend]MarkAllStaticMembers();
#endif
}
static bool GC_CallRootCallbacks()
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
return GC.[Friend]CallRootCallbacks();
#else
return true;
#endif
}
static void GC_Shutdown()
{
#if BF_DBG_RUNTIME
GC.Shutdown();
#endif
}
static void DebugMessageData_SetupError(char8* str, int32 stackWindbackCount)
{
BfDebugMessageData.gBfDebugMessageData.SetupError(str, stackWindbackCount);
}
static void DebugMessageData_SetupProfilerCmd(char8* str)
{
BfDebugMessageData.gBfDebugMessageData.SetupProfilerCmd(str);
}
static void DebugMessageData_Fatal()
{
BfDebugMessageData.gBfDebugMessageData.Fatal();
}
static void DebugMessageData_Clear()
{
BfDebugMessageData.gBfDebugMessageData.Clear();
}
public void Init() mut
{
mAlloc = => Alloc;
mFree = => Free;
mObject_Delete = => Object_Delete;
mObject_ToString = => Object_ToString;
mObject_GetType = => Object_GetType;
mObject_GCMarkMembers = => Object_GCMarkMembers;
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;
mType_GetFullName = => Type_GetFullName;
mString_Alloc = => String_Alloc;
mString_ToCStr = => String_ToCStr;
mGC_MarkAllStaticMembers = => GC_MarkAllStaticMembers;
mGC_CallRootCallbacks = => GC_CallRootCallbacks;
mGC_Shutdown = => GC_Shutdown;
mSetErrorString = => SetErrorString;
mDebugMessageData_SetupError = => DebugMessageData_SetupError;
mDebugMessageData_SetupProfilerCmd = => DebugMessageData_SetupProfilerCmd;
mDebugMessageData_Fatal = => DebugMessageData_Fatal;
mDebugMessageData_Clear = => DebugMessageData_Clear;
}
};
private static extern void Init(int32 version, int32 flags, BfRtCallbacks* callbacks);
private static extern void AddCrashInfoFunc(void* func);
private static extern void Dbg_Init(int32 version, int32 flags, BfRtCallbacks* callbacks);
private static extern void SetErrorString(char8* error);
private static extern void* Dbg_GetCrashInfoFunc();
public static extern void SetCrashReportKind(RtCrashReportKind crashReportKind);
public enum RtCrashReportKind : int32
{
Default,
GUI,
Console,
PrintOnly,
None
}
enum RtFlags : int32
{
ObjectHasDebugFlags = 1,
LeakCheck = 2,
SilentCrash = 4,
DebugAlloc = 8,
NoThreadExitWait = 0x10
}
static RtFlags sExtraFlags;
public static this()
{
BfRtCallbacks.sCallbacks.Init();
RtFlags flags = sExtraFlags;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
flags |= .ObjectHasDebugFlags;
#endif
#if BF_ENABLE_REALTIME_LEAK_CHECK
flags |= .LeakCheck;
#endif
#if BF_DEBUG_ALLOC
flags |= .DebugAlloc;
#endif
Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks);
#if BF_DBG_RUNTIME
Dbg_Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks);
#endif
}
[NoReturn]
public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
{
String failStr = scope .()..AppendF("{} at line {} in {}", msg, line, filePath);
Internal.FatalError(failStr, 1);
}
[NoReturn]
public static void NotImplemented(String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
{
String failStr = scope .()..AppendF("Not Implemented at line {} in {}", line, filePath);
Internal.FatalError(failStr, 1);
}
public static void Assert(bool condition, String error = Compiler.CallerExpression[0], String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
{
if (!condition)
{
String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath);
Internal.FatalError(failStr, 1);
}
}
}
}