mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Extensive runtime refactor to reduce generated executable sizes
This commit is contained in:
parent
4e750a7e1a
commit
ddd9b1b218
74 changed files with 2514 additions and 717 deletions
|
@ -15,12 +15,8 @@ namespace FMOD
|
|||
*/
|
||||
public class VERSION
|
||||
{
|
||||
public const int32 number = 0x00010803;
|
||||
#if BF_64_BIT
|
||||
public const String dll = "fmod64.dll";
|
||||
#else
|
||||
public const int32 number = 0x00020220;
|
||||
public const String dll = "fmod.dll";
|
||||
#endif
|
||||
}
|
||||
|
||||
public class CONSTANTS
|
||||
|
@ -1385,7 +1381,7 @@ namespace FMOD
|
|||
public int fileuserdata; /* [w] Optional. Specify 0 to ignore. User data to be passed into the file callbacks. */
|
||||
public int32 filebuffersize; /* [w] Optional. Specify 0 to ignore. Buffer size for reading the file, -1 to disable buffering, or 0 for system default. */
|
||||
public CHANNELORDER channelorder; /* [w] Optional. Specify 0 to ignore. Use this to differ the way fmod maps multichannel sounds to speakers. See FMOD_CHANNELORDER for more. */
|
||||
public CHANNELMASK channelmask; /* [w] Optional. Specify 0 to ignore. Use this to differ the way fmod maps multichannel sounds to speakers. See FMOD_CHANNELMASK for more. */
|
||||
//public CHANNELMASK channelmask; /* [w] Optional. Specify 0 to ignore. Use this to differ the way fmod maps multichannel sounds to speakers. See FMOD_CHANNELMASK for more. */
|
||||
public int initialsoundgroup; /* [w] Optional. Specify 0 to ignore. Specify a sound group if required, to put sound in as it is created. */
|
||||
public uint32 initialseekposition; /* [w] Optional. Specify 0 to ignore. For streams. Specify an initial position to seek the stream to. */
|
||||
public TIMEUNIT initialseekpostype; /* [w] Optional. Specify 0 to ignore. For streams. Specify the time unit for the position set in initialseekposition. */
|
||||
|
@ -1587,7 +1583,7 @@ namespace FMOD
|
|||
RESULT result = RESULT.OK;
|
||||
int rawPtr = 0;
|
||||
|
||||
result = FMOD_System_Create(out rawPtr);
|
||||
result = FMOD_System_Create(out rawPtr, VERSION.number);
|
||||
if (result != RESULT.OK)
|
||||
{
|
||||
return result;
|
||||
|
@ -1602,7 +1598,7 @@ namespace FMOD
|
|||
#region importfunctions
|
||||
|
||||
[Import(VERSION.dll), CLink, CallingConvention(.Stdcall)]
|
||||
private static extern RESULT FMOD_System_Create (out int system);
|
||||
private static extern RESULT FMOD_System_Create (out int system, uint headerversion);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -2008,6 +2004,7 @@ namespace FMOD
|
|||
stringData = name.CStr();
|
||||
|
||||
exinfo.cbsize = (int32)sizeof(CREATESOUNDEXINFO);
|
||||
//int offset = offsetof(CREATESOUNDEXINFO, channelmask);
|
||||
|
||||
int soundraw;
|
||||
RESULT result = FMOD_System_CreateSound(rawPtr, stringData, mode, ref exinfo, out soundraw);
|
||||
|
|
|
@ -172,6 +172,12 @@ namespace System
|
|||
|
||||
}
|
||||
|
||||
[AttributeUsage(.MemberAccess)]
|
||||
public struct NoStaticCtorAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
[AttributeUsage(.Block)]
|
||||
public struct ConstSkipAttribute : Attribute
|
||||
|
|
|
@ -13,8 +13,38 @@ namespace System
|
|||
CtrlBreak
|
||||
}
|
||||
|
||||
static Encoding InputEncoding = Encoding.ASCII;
|
||||
static Encoding OutputEncoding = Encoding.ASCII;
|
||||
public struct CancelInfo
|
||||
{
|
||||
public static Event<delegate void (CancelKind cancelKind, ref bool terminate)> sOnCancel ~ _.Dispose();
|
||||
public static bool sCancelEventRegistered;
|
||||
}
|
||||
|
||||
static Encoding sInputEncoding;
|
||||
static Encoding sOutputEncoding;
|
||||
|
||||
static Encoding InputEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
return sInputEncoding ?? Encoding.ASCII;
|
||||
}
|
||||
set
|
||||
{
|
||||
sInputEncoding = value;
|
||||
}
|
||||
}
|
||||
static Encoding OutputEncoding
|
||||
{
|
||||
get
|
||||
{
|
||||
return sOutputEncoding ?? Encoding.ASCII;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetupOutStringEx();
|
||||
sOutputEncoding = value;
|
||||
}
|
||||
}
|
||||
|
||||
static ConsoleColor sForegroundColor = .White;
|
||||
static ConsoleColor sBackgroundColor = .Black;
|
||||
|
@ -22,9 +52,6 @@ namespace System
|
|||
static readonly ConsoleColor sOriginalForegroundColor = sForegroundColor;
|
||||
static readonly ConsoleColor sOriginalBackgroundColor = sBackgroundColor;
|
||||
|
||||
static Event<delegate void (CancelKind cancelKind, ref bool terminate)> sOnCancel ~ _.Dispose();
|
||||
static bool sCancelEventRegistered;
|
||||
|
||||
public static ConsoleColor ForegroundColor
|
||||
{
|
||||
get { return sForegroundColor; }
|
||||
|
@ -56,18 +83,39 @@ namespace System
|
|||
{
|
||||
}
|
||||
|
||||
static void SetupOutStringEx()
|
||||
{
|
||||
OutString = => OutString_Ex;
|
||||
}
|
||||
|
||||
static function void(StringView str) OutString = => OutString_Simple;
|
||||
|
||||
[CLink, CallingConvention(.Cdecl)]
|
||||
static extern void putchar(char8 c);
|
||||
|
||||
static void OutString_Simple(StringView str)
|
||||
{
|
||||
for (var c in str.RawChars)
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
static void OutString_Ex(StringView str)
|
||||
{
|
||||
Out.Write(str).IgnoreError();
|
||||
}
|
||||
|
||||
public static ref Event<delegate void (CancelKind cancelKind, ref bool terminate)> OnCancel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!sCancelEventRegistered)
|
||||
if (!CancelInfo.sCancelEventRegistered)
|
||||
{
|
||||
sCancelEventRegistered = true;
|
||||
CancelInfo.sCancelEventRegistered = true;
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
SetConsoleCtrlHandler(=> ConsoleCtrlHandler, true);
|
||||
#endif
|
||||
}
|
||||
return ref sOnCancel;
|
||||
return ref CancelInfo.sOnCancel;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +125,7 @@ namespace System
|
|||
{
|
||||
bool terminate = true;
|
||||
if ((ctrlType == 0) || (ctrlType == 1))
|
||||
sOnCancel((.)ctrlType, ref terminate);
|
||||
CancelInfo.sOnCancel((.)ctrlType, ref terminate);
|
||||
return terminate ? false : true;
|
||||
}
|
||||
|
||||
|
@ -286,7 +334,7 @@ namespace System
|
|||
|
||||
public static void Write(StringView line)
|
||||
{
|
||||
Out.Write(line).IgnoreError();
|
||||
OutString(line);
|
||||
}
|
||||
|
||||
public static void Write(StringView fmt, params Object[] args)
|
||||
|
@ -308,12 +356,13 @@ namespace System
|
|||
|
||||
public static void WriteLine()
|
||||
{
|
||||
Out.Write("\n").IgnoreError();
|
||||
OutString("\n");
|
||||
}
|
||||
|
||||
public static void WriteLine(StringView line)
|
||||
{
|
||||
Out.WriteLine(line).IgnoreError();
|
||||
OutString(line);
|
||||
OutString("\n");
|
||||
}
|
||||
|
||||
public static void WriteLine(StringView fmt, params Object[] args)
|
||||
|
|
|
@ -14,7 +14,14 @@ namespace System.Diagnostics.Contracts
|
|||
Assume,
|
||||
}
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
static extern void ReportFailure(ContractFailureKind failureKind, char8* userMessage, int32 userMessageLen, char8* conditionText, int32 conditionTextLen);
|
||||
#else
|
||||
static void ReportFailure(ContractFailureKind failureKind, char8* userMessage, int32 userMessageLen, char8* conditionText, int32 conditionTextLen)
|
||||
{
|
||||
Internal.FatalError("Contract.ReportFailure");
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly.
|
||||
|
|
|
@ -9,10 +9,16 @@ namespace System.Diagnostics
|
|||
{
|
||||
if (!condition)
|
||||
{
|
||||
if (Runtime.CheckErrorHandlers(scope Runtime.AssertError(.Debug, error, filePath, line)) == .Ignore)
|
||||
if ((Runtime.CheckAssertError != null) && (Runtime.CheckAssertError(.Debug, error, filePath, line) == .Ignore))
|
||||
return;
|
||||
String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath);
|
||||
#if !BF_RUNTIME_REDUCED
|
||||
String failStr = scope .()..Append("Assert failed: ", error, " at line ");
|
||||
line.ToString(failStr);
|
||||
failStr.Append(" in ", filePath);
|
||||
Internal.FatalError(failStr, 1);
|
||||
#else
|
||||
Internal.FatalError("Assert failed", 1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +27,9 @@ namespace System.Diagnostics
|
|||
#endif
|
||||
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);
|
||||
String failStr = scope .()..Append(msg, " at line ");
|
||||
line.ToString(failStr);
|
||||
failStr.Append(" in ", filePath);
|
||||
Internal.FatalError(failStr, 1);
|
||||
}
|
||||
|
||||
|
@ -87,7 +95,7 @@ namespace System.Diagnostics
|
|||
}
|
||||
|
||||
static bool gIsDebuggerPresent = IsDebuggerPresent;
|
||||
[LinkName("IsDebuggerPresent"), CallingConvention(.Stdcall)]
|
||||
[LinkName("IsDebuggerPresent"), CallingConvention(.Stdcall), Import("kernel32.lib")]
|
||||
static extern int32 Internal_IsDebuggerPresent();
|
||||
|
||||
public static bool IsDebuggerPresent
|
||||
|
|
|
@ -199,7 +199,11 @@ namespace System
|
|||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern int32 ftoa(float val, char8* str);
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
static extern int32 ToString(double val, char8* str, bool roundTrip);
|
||||
#else
|
||||
static int32 ToString(double val, char8* str, bool roundTrip) => Runtime.NotImplemented();
|
||||
#endif
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace System
|
||||
{
|
||||
|
@ -12,7 +13,23 @@ namespace System
|
|||
public static readonly String NewLine = "\n";
|
||||
#endif // BF_PLATFORM_WINDOWS
|
||||
|
||||
public static OperatingSystem OSVersion = new OperatingSystem() ~ delete _;
|
||||
|
||||
static OperatingSystem sOSVersion ~ delete _;
|
||||
public static OperatingSystem OSVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
var osVersion = new OperatingSystem();
|
||||
let prevValue = Interlocked.CompareExchange(ref sOSVersion, null, osVersion);
|
||||
if (prevValue != null)
|
||||
{
|
||||
// This was already set - race condition
|
||||
delete osVersion;
|
||||
return prevValue;
|
||||
}
|
||||
return osVersion;
|
||||
}
|
||||
}
|
||||
|
||||
public static void* ModuleHandle => Internal.[Friend]sModuleHandle;
|
||||
|
||||
|
|
|
@ -147,7 +147,11 @@ namespace System
|
|||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern int32 ftoa(float val, char8* str);
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
static extern int32 ToString(float val, char8* str, bool roundTrip);
|
||||
#else
|
||||
static int32 ToString(float val, char8* str, bool roundTrip) => Runtime.FatalError();
|
||||
#endif
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace System
|
|||
#endif
|
||||
}
|
||||
|
||||
#if BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC
|
||||
#if (BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC) && !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Cdecl)]
|
||||
public extern static void Report();
|
||||
[CallingConvention(.Cdecl)]
|
||||
|
|
|
@ -13,6 +13,14 @@ namespace System
|
|||
case InvalidChar(int partialResult);
|
||||
}
|
||||
|
||||
public struct Simple : int
|
||||
{
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
((int)this).ToString(strBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public const int MaxValue = (sizeof(int) == 8) ? 0x7FFFFFFFFFFFFFFFL : 0x7FFFFFFF;
|
||||
public const int MinValue = (sizeof(int) == 8) ? -0x8000000000000000L : -0x80000000;
|
||||
|
||||
|
|
|
@ -63,11 +63,6 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
//static char8[] sHexUpperChars = new char8[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'} ~ delete _;
|
||||
//static char8[] sHexLowerChars = new char8[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'} ~ delete _;
|
||||
|
||||
static String sHexUpperChars = "0123456789ABCDEF";
|
||||
static String sHexLowerChars = "0123456789abcdef";
|
||||
public void ToString(String outString, String format, IFormatProvider formatProvider)
|
||||
{
|
||||
if(format == null || format.IsEmpty)
|
||||
|
|
|
@ -81,12 +81,6 @@ namespace System
|
|||
public static extern Object UnsafeCastToObject(void* ptr);
|
||||
[Intrinsic("cast")]
|
||||
public static extern void* UnsafeCastToPtr(Object obj);
|
||||
[CallingConvention(.Cdecl), NoReturn]
|
||||
public static extern void ThrowIndexOutOfRange(int stackOffset = 0);
|
||||
[CallingConvention(.Cdecl), NoReturn]
|
||||
public static extern void ThrowObjectNotInitialized(int stackOffset = 0);
|
||||
[CallingConvention(.Cdecl), NoReturn]
|
||||
public static extern void FatalError(String error, int stackOffset = 0);
|
||||
[Intrinsic("memcpy")]
|
||||
public static extern void MemCpy(void* dest, void* src, int length, int32 align = 1, bool isVolatile = false);
|
||||
[Intrinsic("memmove")]
|
||||
|
@ -103,6 +97,32 @@ namespace System
|
|||
public static extern void StdFree(void* ptr);
|
||||
[Intrinsic("returnaddress")]
|
||||
public static extern void* GetReturnAddress(int32 level = 0);
|
||||
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern void Test_Init(char8* testData);
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern void Test_Error(char8* error);
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern void Test_Write(char8* str);
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern int32 Test_Query();
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern void Test_Finish();
|
||||
|
||||
static void* sModuleHandle;
|
||||
[AlwaysInclude]
|
||||
static void SetModuleHandle(void* handle)
|
||||
{
|
||||
sModuleHandle = handle;
|
||||
}
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Cdecl), NoReturn]
|
||||
public static extern void ThrowIndexOutOfRange(int stackOffset = 0);
|
||||
[CallingConvention(.Cdecl), NoReturn]
|
||||
public static extern void ThrowObjectNotInitialized(int stackOffset = 0);
|
||||
[CallingConvention(.Cdecl), NoReturn]
|
||||
public static extern void FatalError(String error, int stackOffset = 0);
|
||||
[CallingConvention(.Cdecl)]
|
||||
public static extern void* VirtualAlloc(int size, bool canExecute, bool canWrite);
|
||||
[CallingConvention(.Cdecl)]
|
||||
|
@ -160,25 +180,236 @@ namespace System
|
|||
[CallingConvention(.Cdecl)]
|
||||
public static extern void Dbg_RawFree(void* ptr);
|
||||
|
||||
[CallingConvention(.Cdecl), AlwaysInclude]
|
||||
static extern void Shutdown();
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern void Test_Init(char8* testData);
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern void Test_Error(char8* error);
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern void Test_Write(char8* str);
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern int32 Test_Query();
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern void Test_Finish();
|
||||
static extern void Shutdown_Internal();
|
||||
|
||||
static void* sModuleHandle;
|
||||
[AlwaysInclude]
|
||||
static void SetModuleHandle(void* handle)
|
||||
[CallingConvention(.Cdecl), AlwaysInclude]
|
||||
static void Shutdown()
|
||||
{
|
||||
sModuleHandle = handle;
|
||||
Shutdown_Internal();
|
||||
Runtime.Shutdown();
|
||||
}
|
||||
#else
|
||||
|
||||
enum BfObjectFlags : uint8
|
||||
{
|
||||
None = 0,
|
||||
Mark1 = 0x01,
|
||||
Mark2 = 0x02,
|
||||
Mark3 = 0x03,
|
||||
Allocated = 0x04,
|
||||
StackAlloc = 0x08,
|
||||
AppendAlloc = 0x10,
|
||||
AllocInfo = 0x20,
|
||||
AllocInfo_Short = 0x40,
|
||||
Deleted = 0x80
|
||||
};
|
||||
|
||||
[NoReturn]
|
||||
static void Crash()
|
||||
{
|
||||
char8* ptr = null;
|
||||
*ptr = 'A';
|
||||
}
|
||||
|
||||
[AlwaysInclude, NoReturn]
|
||||
public static void ThrowIndexOutOfRange(int stackOffset = 0)
|
||||
{
|
||||
Crash();
|
||||
}
|
||||
|
||||
[AlwaysInclude, NoReturn]
|
||||
public static void ThrowObjectNotInitialized(int stackOffset = 0)
|
||||
{
|
||||
Crash();
|
||||
}
|
||||
|
||||
[AlwaysInclude, NoReturn]
|
||||
public static void FatalError(String error, int stackOffset = 0)
|
||||
{
|
||||
Crash();
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public static void* VirtualAlloc(int size, bool canExecute, bool canWrite)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int32 CStrLen(char8* charPtr)
|
||||
{
|
||||
int32 len = 0;
|
||||
while (charPtr[len] != 0)
|
||||
len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
public static int64 GetTickCountMicro()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
[AlwaysInclude]
|
||||
public static void BfDelegateTargetCheck(void* target)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public static void* LoadSharedLibrary(char8* filePath)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public static void LoadSharedLibraryInto(char8* filePath, void** libDest)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public static void* GetSharedProcAddress(void* libHandle, char8* procName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public static void GetSharedProcAddressInto(void* libHandle, char8* procName, void** procDest)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public static char8* GetCommandLineArgs()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void ProfilerCmd(char8* str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void ReportMemory()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void ObjectDynCheck(Object obj, int32 typeId, bool allowNull)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void ObjectDynCheckFailed(Object obj, int32 typeId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[DisableChecks, DisableObjectAccessChecks]
|
||||
public static void Dbg_ObjectCreated(Object obj, int size, ClassVData* classVData)
|
||||
{
|
||||
}
|
||||
|
||||
[DisableChecks, DisableObjectAccessChecks]
|
||||
public static void Dbg_ObjectCreatedEx(Object obj, int size, ClassVData* classVData)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[DisableChecks, DisableObjectAccessChecks]
|
||||
public static void Dbg_ObjectAllocated(Object obj, int size, ClassVData* classVData)
|
||||
{
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
obj.[Friend]mClassVData = (.)(void*)classVData;
|
||||
obj.[Friend]mDbgAllocInfo = (.)GetReturnAddress(0);
|
||||
#else
|
||||
obj.[Friend]mClassVData = classVData;
|
||||
#endif
|
||||
}
|
||||
|
||||
[DisableChecks, DisableObjectAccessChecks]
|
||||
public static void Dbg_ObjectAllocatedEx(Object obj, int size, ClassVData* classVData)
|
||||
{
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
obj.[Friend]mClassVData = (.)(void*)classVData;
|
||||
obj.[Friend]mDbgAllocInfo = (.)GetReturnAddress(0);
|
||||
#else
|
||||
obj.[Friend]mClassVData = classVData;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static int Dbg_PrepareStackTrace(int baseAllocSize, int maxStackTraceDepth)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
[DisableChecks, DisableObjectAccessChecks]
|
||||
public static void Dbg_ObjectStackInit(Object obj, ClassVData* classVData)
|
||||
{
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
obj.[Friend]mClassVData = (.)(void*)classVData;
|
||||
obj.[Friend]mClassVData |= (.)BfObjectFlags.StackAlloc;
|
||||
obj.[Friend]mDbgAllocInfo = (.)GetReturnAddress(0);
|
||||
#else
|
||||
obj.[Friend]mClassVData = classVData;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Object Dbg_ObjectAlloc(TypeInstance typeInst, int size)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void Dbg_ObjectPreDelete(Object obj)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void Dbg_ObjectPreCustomDelete(Object obj)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static void Dbg_MarkObjectDeleted(Object obj)
|
||||
{
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
obj.[Friend]mClassVData |= (.)BfObjectFlags.Deleted;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void* Dbg_RawAlloc(int size)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void* Dbg_RawObjectAlloc(int size)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void* Dbg_RawAlloc(int size, DbgRawAllocData* rawAllocData)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void Dbg_RawFree(void* ptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
static void Shutdown()
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
[AlwaysInclude]
|
||||
static void AddRtFlags(int32 flags)
|
||||
{
|
||||
|
@ -254,9 +485,9 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public static String[] CreateParamsArray()
|
||||
{
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
char8* cmdLine = GetCommandLineArgs();
|
||||
//Windows.MessageBoxA(default, scope String()..AppendF("CmdLine: {0}", StringView(cmdLine)), "HI", 0);
|
||||
|
||||
|
@ -357,9 +588,11 @@ namespace System
|
|||
}
|
||||
|
||||
return strVals;
|
||||
#else
|
||||
return new String[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public static void DeleteStringArray(String[] arr)
|
||||
{
|
||||
for (var str in arr)
|
||||
|
@ -367,8 +600,10 @@ namespace System
|
|||
delete arr;
|
||||
}
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
extern static this();
|
||||
extern static ~this();
|
||||
#endif
|
||||
}
|
||||
|
||||
struct CRTAlloc
|
||||
|
|
|
@ -224,6 +224,7 @@ namespace System
|
|||
return intPart;
|
||||
}
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
public static extern float Sqrt(float f);
|
||||
public static extern double Sqrt(double d);
|
||||
public static extern float Cbrt(float f);
|
||||
|
@ -236,6 +237,20 @@ namespace System
|
|||
public static extern double Exp(double d);
|
||||
public static extern float Pow(float x, float y);
|
||||
public static extern double Pow(double x, double y);
|
||||
#else
|
||||
public static float Sqrt(float f) => Runtime.NotImplemented();
|
||||
public static double Sqrt(double d) => Runtime.NotImplemented();
|
||||
public static float Cbrt(float f) => Runtime.NotImplemented();
|
||||
public static double Cbrt(double d) => Runtime.NotImplemented();
|
||||
public static float Log(float f) => Runtime.NotImplemented();
|
||||
public static double Log(double d) => Runtime.NotImplemented();
|
||||
public static float Log10(float f) => Runtime.NotImplemented();
|
||||
public static double Log10(double d) => Runtime.NotImplemented();
|
||||
public static float Exp(float f) => Runtime.NotImplemented();
|
||||
public static double Exp(double d) => Runtime.NotImplemented();
|
||||
public static float Pow(float x, float y) => Runtime.NotImplemented();
|
||||
public static double Pow(double x, double y) => Runtime.NotImplemented();
|
||||
#endif
|
||||
|
||||
public static float IEEERemainder(float x, float y)
|
||||
{
|
||||
|
|
|
@ -1130,12 +1130,14 @@ namespace System
|
|||
// Hexadecimal digits representation.
|
||||
private static uint32 FastToDecHex (int32 val)
|
||||
{
|
||||
var decHexDigits = DecHexDigits;
|
||||
|
||||
if (val < 100)
|
||||
return (uint32)DecHexDigits [val];
|
||||
return (uint32)decHexDigits[val];
|
||||
|
||||
// Uses 2^19 (524288) to compute val / 100 for val < 10000.
|
||||
int32 v = (val * 5243) >> 19;
|
||||
return (uint32)((DecHexDigits [v] << 8) | DecHexDigits [val - v * 100]);
|
||||
return (uint32)((decHexDigits[v] << 8) | decHexDigits[val - v * 100]);
|
||||
}
|
||||
|
||||
// Helper to translate an int in the range 0 .. 99999999 to its
|
||||
|
@ -1741,6 +1743,31 @@ namespace System
|
|||
inst.IntegerToString(format, fp, outString);
|
||||
}
|
||||
|
||||
public static void AddrToString (uint value, String outString)
|
||||
{
|
||||
const int bufLen = 18;
|
||||
char8* strChars = scope:: char8[bufLen]* (?);
|
||||
int32 curLen = 0;
|
||||
uint64 valLeft = (.)value;
|
||||
while (valLeft > 0)
|
||||
{
|
||||
if (curLen == 8)
|
||||
strChars[bufLen - curLen++ - 1] = '\'';
|
||||
strChars[bufLen - curLen++ - 1] = DigitUpperTable[(int)(valLeft & 0xF)];
|
||||
valLeft >>= 4;
|
||||
}
|
||||
|
||||
while (curLen < 10)
|
||||
{
|
||||
if (curLen == 8)
|
||||
strChars[bufLen - curLen++ - 1] = '\'';
|
||||
strChars[bufLen - curLen++ - 1] = '0';
|
||||
}
|
||||
|
||||
char8* char8Ptr = &strChars[bufLen - curLen];
|
||||
outString.Append(char8Ptr, curLen);
|
||||
}
|
||||
|
||||
public static void NumberToString (StringView format, int32 value, IFormatProvider fp, String outString)
|
||||
{
|
||||
NumberFormatter inst = GetInstance!(fp);
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace System
|
|||
ClassVData* mClassVData;
|
||||
#endif
|
||||
|
||||
[AlwaysInclude]
|
||||
public virtual ~this()
|
||||
{
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
|
@ -47,42 +48,79 @@ namespace System
|
|||
if (Compiler.IsComptime)
|
||||
return Comptime_GetType();
|
||||
|
||||
Type type;
|
||||
ClassVData* classVData;
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
type = maskedVData.mType;
|
||||
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
#else
|
||||
type = mClassVData.mType;
|
||||
classVData = mClassVData;
|
||||
#endif
|
||||
|
||||
#if BF_32_BIT
|
||||
Type type = Type.[Friend]GetType_(classVData.mType2);
|
||||
#else
|
||||
Type type = Type.[Friend]GetType_((.)(classVData.mType >> 32));
|
||||
#endif
|
||||
if ((type.[Friend]mTypeFlags & TypeFlags.Boxed) != 0)
|
||||
{
|
||||
//int32 underlyingType = (int32)((TypeInstance)type).mUnderlyingType;
|
||||
type = Type.[Friend]GetType(((TypeInstance)type).[Friend]mUnderlyingType);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
TypeId GetTypeId()
|
||||
{
|
||||
ClassVData* classVData;
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
#else
|
||||
classVData = mClassVData;
|
||||
#endif
|
||||
|
||||
#if BF_32_BIT
|
||||
return (.)classVData.mType2;
|
||||
#else
|
||||
return (.)(classVData.mType >> 32);
|
||||
#endif
|
||||
}
|
||||
|
||||
[NoShow]
|
||||
Type RawGetType()
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
return Comptime_GetType();
|
||||
|
||||
Type type;
|
||||
ClassVData* classVData;
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
type = maskedVData.mType;
|
||||
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
#else
|
||||
type = mClassVData.mType;
|
||||
classVData = mClassVData;
|
||||
#endif
|
||||
|
||||
#if BF_32_BIT
|
||||
Type type = Type.[Friend]GetType_(classVData.mType);
|
||||
#else
|
||||
Type type = Type.[Friend]GetType_((.)(classVData.mType & 0xFFFFFFFF));
|
||||
#endif
|
||||
return type;
|
||||
}
|
||||
|
||||
TypeId RawGetTypeId()
|
||||
{
|
||||
ClassVData* classVData;
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
#else
|
||||
classVData = mClassVData;
|
||||
#endif
|
||||
|
||||
#if BF_32_BIT
|
||||
return (.)classVData.mType;
|
||||
#else
|
||||
return (.)(classVData.mType & 0xFFFFFFFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BF_DYNAMIC_CAST_CHECK || BF_ENABLE_REALTIME_LEAK_CHECK
|
||||
[NoShow]
|
||||
public virtual Object DynamicCastToTypeId(int32 typeId)
|
||||
{
|
||||
if (typeId == (int32)RawGetType().[Friend]mTypeId)
|
||||
if (typeId == (.)RawGetTypeId())
|
||||
return this;
|
||||
return null;
|
||||
}
|
||||
|
@ -101,6 +139,10 @@ namespace System
|
|||
|
||||
public virtual void ToString(String strBuffer)
|
||||
{
|
||||
#if BF_REFLECT_MINIMAL
|
||||
strBuffer.AppendF($"Type#{(Int.Simple)GetTypeId()}@0x");
|
||||
NumberFormatter.AddrToString((uint)Internal.UnsafeCastToPtr(this), strBuffer);
|
||||
#else
|
||||
let t = RawGetType();
|
||||
if (t.IsBoxedStructPtr)
|
||||
{
|
||||
|
@ -108,13 +150,15 @@ namespace System
|
|||
let innerPtr = *(void**)((uint8*)Internal.UnsafeCastToPtr(this) + ti.[Friend]mMemberDataOffset);
|
||||
strBuffer.Append("(");
|
||||
ti.UnderlyingType.GetFullName(strBuffer);
|
||||
strBuffer.AppendF("*)0x{0:A}", (uint)(void*)innerPtr);
|
||||
//strBuffer.AppendF("*)0x{0:A}", (UInt.Simple)(uint)(void*)innerPtr);
|
||||
strBuffer.Append("*)0x");
|
||||
NumberFormatter.AddrToString((uint)(void*)innerPtr, strBuffer);
|
||||
return;
|
||||
}
|
||||
t.GetFullName(strBuffer);
|
||||
strBuffer.Append("@0x");
|
||||
|
||||
((int)Internal.UnsafeCastToPtr(this)).ToString(strBuffer, "A", null);
|
||||
NumberFormatter.AddrToString((uint)Internal.UnsafeCastToPtr(this), strBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void ToString(Object obj, String strBuffer)
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace System
|
|||
public uint32 dwFileDateLS; // e.g. 0
|
||||
}
|
||||
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
[Import("kernel32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||
extern static bool GetVersionExA(OSVersionInfoExA* lpVersionInformation);
|
||||
|
||||
[CLink, CallingConvention(.Stdcall)]
|
||||
|
@ -274,9 +274,9 @@ namespace System
|
|||
String arch = Arch32;
|
||||
#endif
|
||||
if (Version.Revision == 0)
|
||||
outVar.AppendF("{} (Version {}.{}, Build {}, {})", Name, Version.Major, Version.Minor, Version.Build, arch);
|
||||
outVar.AppendF("{} (Version {}.{}, Build {}, {})", Name, (UInt.Simple)Version.Major, (UInt.Simple)Version.Minor, (UInt.Simple)Version.Build, arch);
|
||||
else
|
||||
outVar.AppendF("{} Service Pack {} (Version {}.{}, Build {}, {})", Name, Version.Revision, Version.Major, Version.Minor, Version.Build, arch);
|
||||
outVar.AppendF("{} Service Pack {} (Version {}.{}, Build {}, {})", Name, (UInt.Simple)Version.Revision, (UInt.Simple)Version.Major, (UInt.Simple)Version.Minor, (UInt.Simple)Version.Build, arch);
|
||||
#elif BF_PLATFORM_LINUX
|
||||
outVar.AppendF("{} {} (Version {}.{}.{})", PrettyName, Name, Version.Major, Version.Minor, Version.Revision);
|
||||
#else // MACOS and ANDROID
|
||||
|
|
|
@ -34,15 +34,29 @@ namespace System
|
|||
NotEmpty
|
||||
};
|
||||
|
||||
public struct BfpCritSect {}
|
||||
public struct BfpSpawn {}
|
||||
public struct BfpFile {}
|
||||
public struct BfpFindFileData {}
|
||||
public struct BfpDynLib {}
|
||||
public struct BfpEvent {};
|
||||
|
||||
public struct BfpFileWatcher {}
|
||||
public struct BfpProcess {}
|
||||
public struct BfpTLS;
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
public struct BfpCritSect {}
|
||||
public struct BfpEvent {};
|
||||
#else
|
||||
public struct BfpCritSect
|
||||
{
|
||||
public int mEmpty;
|
||||
}
|
||||
|
||||
public struct BfpEvent
|
||||
{
|
||||
public bool mSet;
|
||||
public bool mAuto;
|
||||
};
|
||||
#endif
|
||||
|
||||
public enum BfpSystemResult : int32
|
||||
{
|
||||
|
@ -51,6 +65,7 @@ namespace System
|
|||
TempFileError = (int)Result.TempFileError
|
||||
}
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern uint32 BfpSystem_TickCount();
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
|
@ -107,6 +122,62 @@ namespace System
|
|||
public static extern void BfpTLS_SetValue(BfpTLS* tls, void* value);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void* BfpTLS_GetValue(BfpTLS* tls);
|
||||
#else
|
||||
|
||||
public static uint32 BfpSystem_TickCount() => Runtime.NotImplemented();
|
||||
|
||||
public static uint32 BfpSystem_SetCrashRelaunchCmd(char8* cmd) => Runtime.NotImplemented();
|
||||
|
||||
public static BfpTimeStamp BfpSystem_GetTimeStamp() => Runtime.NotImplemented();
|
||||
|
||||
public static uint8 BfpSystem_InterlockedExchange8(uint8* ptr, uint8 val) => Runtime.NotImplemented();
|
||||
|
||||
public static uint16 BfpSystem_InterlockedExchange16(uint16* ptr, uint16 val) => Runtime.NotImplemented();
|
||||
|
||||
public static uint32 BfpSystem_InterlockedExchange32(uint32* ptr, uint32 val) => Runtime.NotImplemented();
|
||||
|
||||
public static uint64 BfpSystem_InterlockedExchange64(uint64* ptr, uint64 val) => Runtime.NotImplemented();
|
||||
|
||||
public static uint8 BfpSystem_InterlockedExchangeAdd8(uint8* ptr, uint8 val) => Runtime.NotImplemented();
|
||||
|
||||
public static uint16 BfpSystem_InterlockedExchangeAdd16(uint16* ptr, uint16 val) => Runtime.NotImplemented(); /// Returns the initial value in 'ptr'
|
||||
|
||||
public static uint32 BfpSystem_InterlockedExchangeAdd32(uint32* ptr, uint32 val) => Runtime.NotImplemented(); /// Returns the initial value in 'ptr'
|
||||
|
||||
public static uint64 BfpSystem_InterlockedExchangeAdd64(uint64* ptr, uint64 val) => Runtime.NotImplemented();
|
||||
|
||||
public static uint8 BfpSystem_InterlockedCompareExchange8(uint8* ptr, uint8 oldVal, uint8 newVal) => Runtime.NotImplemented();
|
||||
|
||||
public static uint16 BfpSystem_InterlockedCompareExchange16(uint16* ptr, uint16 oldVal, uint16 newVal) => Runtime.NotImplemented();
|
||||
|
||||
public static uint32 BfpSystem_InterlockedCompareExchange32(uint32* ptr, uint32 oldVal, uint32 newVal) => Runtime.NotImplemented();
|
||||
|
||||
public static uint64 BfpSystem_InterlockedCompareExchange64(uint64* ptr, uint64 oldVal, uint64 newVal) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpSystem_GetExecutablePath(char8* outStr, int32* inOutStrSize, BfpSystemResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpSystem_GetEnvironmentStrings(char8* outStr, int32* inOutStrSize, BfpSystemResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static int32 BfpSystem_GetNumLogicalCPUs(BfpSystemResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static int64 BfpSystem_GetCPUTick() => Runtime.NotImplemented();
|
||||
|
||||
public static int64 BfpSystem_GetCPUTickFreq() => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpSystem_CreateGUID(Guid* outGuid) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpSystem_GetComputerName(char8* outStr, int32* inOutStrSize, BfpSystemResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static int BfpThread_GetCurrentId() => Runtime.NotImplemented();
|
||||
|
||||
public static BfpTLS* BfpTLS_Create(function [CallingConvention(.Stdcall)] void(void*) exitProc) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpTLS_Release(BfpTLS* tls) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpTLS_SetValue(BfpTLS* tls, void* value) => Runtime.NotImplemented();
|
||||
|
||||
public static void* BfpTLS_GetValue(BfpTLS* tls) => Runtime.NotImplemented();
|
||||
#endif
|
||||
|
||||
public enum BfpFileWatcherFlags : int32
|
||||
{
|
||||
|
@ -125,10 +196,16 @@ namespace System
|
|||
|
||||
public function void BfpDirectoryChangeFunc(BfpFileWatcher* watcher, void* userData, BfpFileChangeKind changeKind, char8* directory, char8* fileName, char8* oldName);
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern BfpFileWatcher* BfpFileWatcher_WatchDirectory(char8* path, BfpDirectoryChangeFunc callback, BfpFileWatcherFlags flags, void* userData, BfpFileResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpFileWatcher_Release(BfpFileWatcher* fileWatcher);
|
||||
#else
|
||||
public static BfpFileWatcher* BfpFileWatcher_WatchDirectory(char8* path, BfpDirectoryChangeFunc callback, BfpFileWatcherFlags flags, void* userData, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFileWatcher_Release(BfpFileWatcher* fileWatcher) => Runtime.NotImplemented();
|
||||
#endif
|
||||
|
||||
public enum BfpProcessResult : int32
|
||||
{
|
||||
|
@ -136,6 +213,7 @@ namespace System
|
|||
InsufficientBuffer = (int)Result.InsufficientBuffer
|
||||
}
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern bool BfpProcess_IsRemoteMachine(char8* machineName);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
|
@ -150,6 +228,22 @@ namespace System
|
|||
public static extern void BfpProcess_GetProcessName(BfpProcess* process, char8* outName, int32* inOutNameSize, BfpProcessResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern int32 BfpProcess_GetProcessId(BfpProcess* process);
|
||||
#else
|
||||
|
||||
public static bool BfpProcess_IsRemoteMachine(char8* machineName) => Runtime.NotImplemented();
|
||||
|
||||
public static BfpProcess* BfpProcess_GetById(char8* machineName, int32 processId, BfpProcessResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpProcess_Enumerate(char8* machineName, BfpProcess** outProcesses, int32* inOutProcessesSize, BfpProcessResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpProcess_Release(BfpProcess* process) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpProcess_GetMainWindowTitle(BfpProcess* process, char8* outTitle, int32* inOutTitleSize, BfpProcessResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpProcess_GetProcessName(BfpProcess* process, char8* outName, int32* inOutNameSize, BfpProcessResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static int32 BfpProcess_GetProcessId(BfpProcess* process) => Runtime.NotImplemented();
|
||||
#endif
|
||||
|
||||
public enum BfpSpawnFlags : int32
|
||||
{
|
||||
|
@ -181,6 +275,7 @@ namespace System
|
|||
UnknownError = (int)Result.UnknownError
|
||||
};
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern BfpSpawn* BfpSpawn_Create(char8* targetPath, char8* args, char8* workingDir, char8* env, BfpSpawnFlags flags, BfpSpawnResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
|
@ -205,6 +300,47 @@ namespace System
|
|||
public static extern bool BfpCritSect_TryEnter(BfpCritSect* critSect, int32 waitMS);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpCritSect_Leave(BfpCritSect* critSect);
|
||||
#else
|
||||
|
||||
public static BfpSpawn* BfpSpawn_Create(char8* targetPath, char8* args, char8* workingDir, char8* env, BfpSpawnFlags flags, BfpSpawnResult* outResult)
|
||||
{
|
||||
*outResult = .UnknownError;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void BfpSpawn_Release(BfpSpawn* spawn) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpSpawn_Kill(BfpSpawn* spawn, int32 exitCode, BfpKillFlags killFlags, BfpSpawnResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static bool BfpSpawn_WaitFor(BfpSpawn* spawn, int waitMS, int* outExitCode, BfpSpawnResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpSpawn_GetStdHandles(BfpSpawn* spawn, BfpFile** outStdIn, BfpFile** outStdOut, BfpFile** outStdErr) => Runtime.NotImplemented();
|
||||
|
||||
|
||||
public static int BfpProcess_GetCurrentId() => Runtime.NotImplemented();
|
||||
|
||||
public static BfpCritSect* BfpCritSect_Create() => new BfpCritSect();
|
||||
|
||||
public static void BfpCritSect_Release(BfpCritSect* critSect)
|
||||
{
|
||||
delete critSect;
|
||||
}
|
||||
|
||||
public static void BfpCritSect_Enter(BfpCritSect* critSect)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static bool BfpCritSect_TryEnter(BfpCritSect* critSect, int32 waitMS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void BfpCritSect_Leave(BfpCritSect* critSect)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
public enum BfpEventFlags : int32
|
||||
{
|
||||
|
@ -221,6 +357,7 @@ namespace System
|
|||
BfpEventResult_NotSupported = (int)Result.NotSupported
|
||||
};
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern BfpEvent* BfpEvent_Create(BfpEventFlags flags);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
|
@ -231,6 +368,46 @@ namespace System
|
|||
public static extern void BfpEvent_Reset(BfpEvent* event, BfpEventResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern bool BfpEvent_WaitFor(BfpEvent* event, int32 waitMS);
|
||||
#else
|
||||
|
||||
public static BfpEvent* BfpEvent_Create(BfpEventFlags flags)
|
||||
{
|
||||
var result = new BfpEvent();
|
||||
result.mSet = flags.HasFlag(.InitiallySet_Auto) | flags.HasFlag(.InitiallySet_Manual);
|
||||
result.mAuto = flags.HasFlag(.InitiallySet_Auto);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void BfpEvent_Release(BfpEvent* event)
|
||||
{
|
||||
delete event;
|
||||
}
|
||||
|
||||
public static void BfpEvent_Set(BfpEvent* event, bool requireManualReset)
|
||||
{
|
||||
event.mSet = true;
|
||||
event.mAuto = !requireManualReset;
|
||||
}
|
||||
|
||||
public static void BfpEvent_Reset(BfpEvent* event, BfpEventResult* outResult)
|
||||
{
|
||||
event.mSet = false;
|
||||
event.mAuto = false;
|
||||
*outResult = .BfpEventResult_Ok;
|
||||
}
|
||||
|
||||
public static bool BfpEvent_WaitFor(BfpEvent* event, int32 waitMS)
|
||||
{
|
||||
if (!event.mSet)
|
||||
return false;
|
||||
if (event.mAuto)
|
||||
{
|
||||
event.mSet = false;
|
||||
event.mAuto = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
public enum BfpLibResult : int32
|
||||
{
|
||||
|
@ -239,6 +416,7 @@ namespace System
|
|||
InsufficientBuffer = (int)Result.InsufficientBuffer
|
||||
};
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern BfpDynLib* BfpDynLib_Load(char8* fileName);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
|
@ -247,6 +425,16 @@ namespace System
|
|||
public static extern void BfpDynLib_GetFilePath(BfpDynLib* lib, char8* outPath, int32* inOutPathSize, BfpLibResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void* BfpDynLib_GetProcAddress(BfpDynLib* lib, char8* name);
|
||||
#else
|
||||
|
||||
public static BfpDynLib* BfpDynLib_Load(char8* fileName) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpDynLib_Release(BfpDynLib* lib) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpDynLib_GetFilePath(BfpDynLib* lib, char8* outPath, int32* inOutPathSize, BfpLibResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void* BfpDynLib_GetProcAddress(BfpDynLib* lib, char8* name) => Runtime.NotImplemented();
|
||||
#endif
|
||||
|
||||
public enum BfpFileResult : int32
|
||||
{
|
||||
|
@ -265,6 +453,7 @@ namespace System
|
|||
NotEmpty = (int)Result.NotEmpty,
|
||||
};
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpDirectory_Create(char8* name, BfpFileResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
|
@ -279,6 +468,22 @@ namespace System
|
|||
public static extern bool BfpDirectory_Exists(char8* path);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpDirectory_GetSysDirectory(BfpSysDirectoryKind sysDirKind, char8* outPath, int32* inOutPathLen, BfpFileResult* outResult);
|
||||
#else
|
||||
|
||||
public static void BfpDirectory_Create(char8* name, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpDirectory_Rename(char8* oldName, char8* newName, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpDirectory_Delete(char8* name, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpDirectory_GetCurrent(char8* outPath, int32* inOutPathSize, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpDirectory_SetCurrent(char8* path, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static bool BfpDirectory_Exists(char8* path) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpDirectory_GetSysDirectory(BfpSysDirectoryKind sysDirKind, char8* outPath, int32* inOutPathLen, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
#endif
|
||||
|
||||
public enum BfpFileCreateKind : int32
|
||||
{
|
||||
|
@ -347,6 +552,7 @@ namespace System
|
|||
In
|
||||
}
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern BfpFile* BfpFile_Create(char8* name, BfpFileCreateKind createKind, BfpFileCreateFlags createFlags, BfpFileAttributes createdFileAttrs, BfpFileResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
|
@ -389,6 +595,50 @@ namespace System
|
|||
public static extern void BfpFile_GetFullPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpFile_GetActualPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
|
||||
#else
|
||||
|
||||
public static BfpFile* BfpFile_Create(char8* name, BfpFileCreateKind createKind, BfpFileCreateFlags createFlags, BfpFileAttributes createdFileAttrs, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static BfpFile* BfpFile_GetStd(BfpFileStdKind kind, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static int BfpFile_GetSystemHandle(BfpFile* file) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_Release(BfpFile* file) => Runtime.NotImplemented();
|
||||
|
||||
public static int BfpFile_Write(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static int BfpFile_Read(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_Flush(BfpFile* file) => Runtime.NotImplemented();
|
||||
|
||||
public static int64 BfpFile_GetFileSize(BfpFile* file) => Runtime.NotImplemented();
|
||||
|
||||
public static int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path) => Runtime.NotImplemented();
|
||||
|
||||
public static BfpFileAttributes BfpFile_GetAttributes(char8* path, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_SetAttributes(char8* path, BfpFileAttributes attribs, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_Copy(char8* oldPath, char8* newPath, BfpFileCopyKind copyKind, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_Rename(char8* oldPath, char8* newPath, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_Delete(char8* path, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static bool BfpFile_Exists(char8* path) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_GetTempPath(char8* outPath, int32* inOutPathSize, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_GetTempFileName(char8* outName, int32* inOutNameSize, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_GetFullPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFile_GetActualPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
#endif
|
||||
|
||||
public enum BfpFindFileFlags : int32
|
||||
{
|
||||
|
@ -397,6 +647,7 @@ namespace System
|
|||
Directories = 2,
|
||||
};
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern BfpFindFileData* BfpFindFileData_FindFirstFile(char8* path, BfpFindFileFlags flags, BfpFileResult* outResult);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
|
@ -415,6 +666,26 @@ namespace System
|
|||
public static extern int64 BfpFindFileData_GetFileSize(BfpFindFileData* findData);
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
public static extern void BfpFindFileData_Release(BfpFindFileData* findData);
|
||||
#else
|
||||
|
||||
public static BfpFindFileData* BfpFindFileData_FindFirstFile(char8* path, BfpFindFileFlags flags, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static bool BfpFindFileData_FindNextFile(BfpFindFileData* findData) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFindFileData_GetFileName(BfpFindFileData* findData, char8* outName, int32* inOutNameSize, BfpFileResult* outResult) => Runtime.NotImplemented();
|
||||
|
||||
public static BfpTimeStamp BfpFindFileData_GetTime_LastWrite(BfpFindFileData* findData) => Runtime.NotImplemented();
|
||||
|
||||
public static BfpTimeStamp BfpFindFileData_GetTime_Created(BfpFindFileData* findData) => Runtime.NotImplemented();
|
||||
|
||||
public static BfpTimeStamp BfpFindFileData_GetTime_Access(BfpFindFileData* findData) => Runtime.NotImplemented();
|
||||
|
||||
public static BfpFileAttributes BfpFindFileData_GetFileAttributes(BfpFindFileData* findData) => Runtime.NotImplemented();
|
||||
|
||||
public static int64 BfpFindFileData_GetFileSize(BfpFindFileData* findData) => Runtime.NotImplemented();
|
||||
|
||||
public static void BfpFindFileData_Release(BfpFindFileData* findData) => Runtime.NotImplemented();
|
||||
#endif
|
||||
|
||||
public enum BfpSysDirectoryKind : int32
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace System
|
|||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
strBuffer.AppendF("0x{0:A}", (uint)(void*)mVal);
|
||||
strBuffer.AppendF("0x{0:A}", (UInt.Simple)(uint)(void*)mVal);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,8 @@ namespace System
|
|||
public override void ToString(String strBuffer)
|
||||
{
|
||||
strBuffer.Append("(");
|
||||
typeof(T).GetFullName(strBuffer);
|
||||
strBuffer.AppendF("*)0x{0:A}", (uint)(void*)mVal);
|
||||
typeof(T).ToString(strBuffer);
|
||||
strBuffer.AppendF("*)0x{0:A}", (UInt.Simple)(uint)(void*)mVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
using System.Threading;
|
||||
using System.Collections;
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS || BF_DEBUG_ALLOC
|
||||
#if (BF_ENABLE_OBJECT_DEBUG_FLAGS || BF_DEBUG_ALLOC) && !BF_RUNTIME_DISABLE
|
||||
#define BF_DBG_RUNTIME
|
||||
#endif
|
||||
|
||||
using internal System.Threading.Thread;
|
||||
|
||||
namespace System
|
||||
{
|
||||
struct RuntimeFeatures
|
||||
|
@ -17,7 +19,7 @@ namespace System
|
|||
{
|
||||
const int32 cVersion = 10;
|
||||
|
||||
[CRepr, AlwaysInclude]
|
||||
[CRepr]
|
||||
struct BfDebugMessageData
|
||||
{
|
||||
enum MessageType : int32
|
||||
|
@ -104,7 +106,7 @@ namespace System
|
|||
|
||||
struct BfRtCallbacks
|
||||
{
|
||||
public static BfRtCallbacks sCallbacks = .();
|
||||
public static BfRtCallbacks sCallbacks;
|
||||
|
||||
function void* (int size) mAlloc;
|
||||
function void (void* ptr) mFree;
|
||||
|
@ -115,7 +117,7 @@ namespace System
|
|||
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 StringView (String str) mString_ToStringView;
|
||||
function Object () mThread_Alloc;
|
||||
function Object () mThread_GetMainThread;
|
||||
function void (Object thread) mThread_ThreadProc;
|
||||
|
@ -178,7 +180,7 @@ namespace System
|
|||
static void Type_GetFullName(Type type, String str)
|
||||
{
|
||||
#if BF_DBG_RUNTIME
|
||||
type.GetFullName(str);
|
||||
type.ToString(str);
|
||||
#else
|
||||
//
|
||||
#endif
|
||||
|
@ -189,9 +191,9 @@ namespace System
|
|||
return new String();
|
||||
}
|
||||
|
||||
static char8* String_ToCStr(String str)
|
||||
static StringView String_ToStringView(String str)
|
||||
{
|
||||
return str.CStr();
|
||||
return str;
|
||||
}
|
||||
|
||||
static void GC_MarkAllStaticMembers()
|
||||
|
@ -219,39 +221,37 @@ namespace System
|
|||
|
||||
static void DebugMessageData_SetupError(char8* str, int32 stackWindbackCount)
|
||||
{
|
||||
#if !BF_RUNTIME_REDUCED
|
||||
BfDebugMessageData.gBfDebugMessageData.SetupError(str, stackWindbackCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void DebugMessageData_SetupProfilerCmd(char8* str)
|
||||
{
|
||||
#if !BF_RUNTIME_REDUCED
|
||||
BfDebugMessageData.gBfDebugMessageData.SetupProfilerCmd(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void DebugMessageData_Fatal()
|
||||
{
|
||||
#if !BF_RUNTIME_REDUCED
|
||||
BfDebugMessageData.gBfDebugMessageData.Fatal();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void DebugMessageData_Clear()
|
||||
{
|
||||
#if !BF_RUNTIME_REDUCED
|
||||
BfDebugMessageData.gBfDebugMessageData.Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int32 CheckErrorHandler(char8* kind, char8* arg1, char8* arg2, int arg3)
|
||||
static int32 CheckErrorHandle(char8* kind, char8* arg1, char8* arg2, int arg3)
|
||||
{
|
||||
Error error = null;
|
||||
switch (StringView(kind))
|
||||
{
|
||||
case "FatalError":
|
||||
error = scope:: FatalError() { mError = new .(arg1) };
|
||||
case "LoadSharedLibrary":
|
||||
error = scope:: LoadSharedLibraryError() { mPath = new .(arg1) };
|
||||
case "GetSharedProcAddress":
|
||||
error = scope:: GetSharedProcAddressError() { mPath = new .(arg1), mProcName = new .(arg2) };
|
||||
}
|
||||
if (error == null)
|
||||
if (Runtime.CheckErrorHandler != null)
|
||||
return Runtime.CheckErrorHandler(kind, arg1, arg2, arg3);
|
||||
return 0;
|
||||
return (int32)Runtime.CheckErrorHandlers(error);
|
||||
}
|
||||
|
||||
public void Init() mut
|
||||
|
@ -264,7 +264,7 @@ namespace System
|
|||
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;
|
||||
mType_GetFullName = => Type_GetFullName;
|
||||
mString_Alloc = => String_Alloc;
|
||||
mString_ToCStr = => String_ToCStr;
|
||||
mString_ToStringView = => String_ToStringView;
|
||||
mGC_MarkAllStaticMembers = => GC_MarkAllStaticMembers;
|
||||
mGC_CallRootCallbacks = => GC_CallRootCallbacks;
|
||||
mGC_Shutdown = => GC_Shutdown;
|
||||
|
@ -277,12 +277,23 @@ namespace System
|
|||
}
|
||||
};
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
private static extern void Init(int32 version, int32 flags, BfRtCallbacks* callbacks);
|
||||
private static extern void InitCrashCatcher(int32 flags);
|
||||
private static extern void ShutdownCrashCatcher();
|
||||
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);
|
||||
#else
|
||||
private static void Init(int32 version, int32 flags, BfRtCallbacks* callbacks) {}
|
||||
private static void AddCrashInfoFunc(void* func) {}
|
||||
private static void Dbg_Init(int32 version, int32 flags, BfRtCallbacks* callbacks) {}
|
||||
private static void SetErrorString(char8* error) {}
|
||||
private static void* Dbg_GetCrashInfoFunc() => null;
|
||||
public static void SetCrashReportKind(RtCrashReportKind crashReportKind) {}
|
||||
#endif
|
||||
|
||||
public enum RtCrashReportKind : int32
|
||||
{
|
||||
|
@ -359,18 +370,23 @@ namespace System
|
|||
Fail
|
||||
}
|
||||
|
||||
static struct ErrorHandlerData
|
||||
{
|
||||
public delegate ErrorHandlerResult ErrorHandler(ErrorStage stage, Error error);
|
||||
public static AllocWrapper<Monitor> sMonitor ~ _.Dispose();
|
||||
public static List<ErrorHandler> sErrorHandlers ~ DeleteContainerAndItems!(_);
|
||||
public static bool sInsideErrorHandler;
|
||||
}
|
||||
|
||||
static RtFlags sExtraFlags;
|
||||
static AllocWrapper<Monitor> sMonitor ~ _.Dispose();
|
||||
static List<ErrorHandler> sErrorHandlers ~ DeleteContainerAndItems!(_);
|
||||
static bool sInsideErrorHandler;
|
||||
|
||||
static bool sQueriedFeatures = false;
|
||||
static RuntimeFeatures sFeatures;
|
||||
|
||||
static function void() sThreadInit;
|
||||
|
||||
public static this()
|
||||
{
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
BfRtCallbacks.sCallbacks.Init();
|
||||
|
||||
RtFlags flags = sExtraFlags;
|
||||
|
@ -384,23 +400,36 @@ namespace System
|
|||
flags |= .DebugAlloc;
|
||||
#endif
|
||||
Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks);
|
||||
#if !BF_RUNTIME_REDUCED && BF_PLATFORM_WINDOWS
|
||||
InitCrashCatcher((int32)flags);
|
||||
#endif
|
||||
#if BF_DBG_RUNTIME
|
||||
Dbg_Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks);
|
||||
#endif
|
||||
Thread.[Friend]Init();
|
||||
if (sThreadInit != null)
|
||||
sThreadInit();
|
||||
#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);
|
||||
#if !BF_RUNTIME_REDUCED
|
||||
String failStr = scope .()..Append(msg, " at line ");
|
||||
line.ToString(failStr);
|
||||
failStr.Append(" in ", filePath);
|
||||
Internal.FatalError(failStr, 1);
|
||||
#else
|
||||
Internal.FatalError("Fatal error", 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
[NoReturn]
|
||||
public static void NotImplemented(String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
|
||||
{
|
||||
String failStr = scope .()..AppendF("Not Implemented at line {} in {}", line, filePath);
|
||||
String failStr = scope .()..Append("Not implemented at line ");
|
||||
line.ToString(failStr);
|
||||
failStr.Append(" in ", filePath);
|
||||
Internal.FatalError(failStr, 1);
|
||||
}
|
||||
|
||||
|
@ -408,60 +437,97 @@ namespace System
|
|||
{
|
||||
if (!condition)
|
||||
{
|
||||
if (Runtime.CheckErrorHandlers(scope Runtime.AssertError(.Runtime, error, filePath, line)) == .Ignore)
|
||||
if ((Runtime.CheckAssertError != null) && (Runtime.CheckAssertError(.Runtime, error, filePath, line) == .Ignore))
|
||||
return;
|
||||
String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath);
|
||||
#if !BF_RUNTIME_REDUCED
|
||||
String failStr = scope .()..Append("Assert failed: ", error, " at line ");
|
||||
line.ToString(failStr);
|
||||
failStr.Append(" in ", filePath);
|
||||
Internal.FatalError(failStr, 1);
|
||||
#else
|
||||
Internal.FatalError("Assert failed", 1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddErrorHandler(ErrorHandler handler)
|
||||
public static void AddErrorHandler(ErrorHandlerData.ErrorHandler handler)
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
return;
|
||||
|
||||
using (sMonitor.Val.Enter())
|
||||
using (ErrorHandlerData.sMonitor.Val.Enter())
|
||||
{
|
||||
if (sErrorHandlers == null)
|
||||
sErrorHandlers = new .();
|
||||
sErrorHandlers.Add(handler);
|
||||
if (CheckAssertError == null)
|
||||
{
|
||||
CheckAssertError = => CheckAssertError_Impl;
|
||||
CheckErrorHandler = => CheckErrorHandler_Impl;
|
||||
}
|
||||
|
||||
if (ErrorHandlerData.sErrorHandlers == null)
|
||||
ErrorHandlerData.sErrorHandlers = new .();
|
||||
ErrorHandlerData.sErrorHandlers.Add(handler);
|
||||
}
|
||||
}
|
||||
|
||||
public static Result<void> RemoveErrorHandler(ErrorHandler handler)
|
||||
public static Result<void> RemoveErrorHandler(ErrorHandlerData.ErrorHandler handler)
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
return .Ok;
|
||||
|
||||
using (sMonitor.Val.Enter())
|
||||
using (ErrorHandlerData.sMonitor.Val.Enter())
|
||||
{
|
||||
if (sErrorHandlers.RemoveStrict(handler))
|
||||
if (ErrorHandlerData.sErrorHandlers.RemoveStrict(handler))
|
||||
return .Ok;
|
||||
}
|
||||
return .Err;
|
||||
}
|
||||
|
||||
public static ErrorHandlerResult CheckErrorHandlers(Error error)
|
||||
public static function ErrorHandlerResult(AssertError.Kind kind, String error, String filePath, int lineNum) CheckAssertError;
|
||||
public static function int32(char8* kind, char8* arg1, char8* arg2, int arg3) CheckErrorHandler;
|
||||
|
||||
static ErrorHandlerResult CheckAssertError_Impl(AssertError.Kind kind, String error, String filePath, int lineNum)
|
||||
{
|
||||
return CheckErrorHandlers(scope AssertError(kind, error, filePath, lineNum));
|
||||
}
|
||||
|
||||
static int32 CheckErrorHandler_Impl(char8* kind, char8* arg1, char8* arg2, int arg3)
|
||||
{
|
||||
Error error = null;
|
||||
switch (StringView(kind))
|
||||
{
|
||||
case "FatalError":
|
||||
error = scope:: FatalError() { mError = new .(arg1) };
|
||||
case "LoadSharedLibrary":
|
||||
error = scope:: LoadSharedLibraryError() { mPath = new .(arg1) };
|
||||
case "GetSharedProcAddress":
|
||||
error = scope:: GetSharedProcAddressError() { mPath = new .(arg1), mProcName = new .(arg2) };
|
||||
}
|
||||
if (error == null)
|
||||
return 0;
|
||||
return (int32)CheckErrorHandlers(error);
|
||||
}
|
||||
|
||||
static ErrorHandlerResult CheckErrorHandlers(Error error)
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
return .ContinueFailure;
|
||||
|
||||
using (sMonitor.Val.Enter())
|
||||
using (ErrorHandlerData.sMonitor.Val.Enter())
|
||||
{
|
||||
if (sInsideErrorHandler)
|
||||
if (ErrorHandlerData.sInsideErrorHandler)
|
||||
return .ContinueFailure;
|
||||
|
||||
sInsideErrorHandler = true;
|
||||
defer { sInsideErrorHandler = false; }
|
||||
ErrorHandlerData.sInsideErrorHandler = true;
|
||||
defer { ErrorHandlerData.sInsideErrorHandler = false; }
|
||||
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
{
|
||||
int idx = (sErrorHandlers?.Count).GetValueOrDefault() - 1;
|
||||
int idx = (ErrorHandlerData.sErrorHandlers?.Count).GetValueOrDefault() - 1;
|
||||
while (idx >= 0)
|
||||
{
|
||||
if (idx < sErrorHandlers.Count)
|
||||
if (idx < ErrorHandlerData.sErrorHandlers.Count)
|
||||
{
|
||||
var handler = sErrorHandlers[idx];
|
||||
var handler = ErrorHandlerData.sErrorHandlers[idx];
|
||||
var result = handler((pass == 0) ? .PreFail : .Fail, error);
|
||||
if (result == .Ignore)
|
||||
{
|
||||
|
@ -562,5 +628,122 @@ namespace System
|
|||
[Intrinsic("xgetbv")]
|
||||
private static extern uint64 xgetbv(uint32 xcr);
|
||||
#endif
|
||||
|
||||
public static void Shutdown()
|
||||
{
|
||||
#if !BF_RUNTIME_REDUCED && BF_PLATFORM_WINDOWS
|
||||
ShutdownCrashCatcher();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if BF_RUNTIME_DISABLE
|
||||
namespace System
|
||||
{
|
||||
[AlwaysInclude, StaticInitPriority(1000)]
|
||||
static class MinRuntime
|
||||
{
|
||||
static function void*(int) sMallocFunc;
|
||||
static function void(void*) sFreeFunc;
|
||||
|
||||
static this()
|
||||
{
|
||||
var lib = Windows.LoadLibraryA("msvcrt.dll");
|
||||
sMallocFunc = (.)Windows.GetProcAddress(lib, "malloc");
|
||||
sFreeFunc = (.)Windows.GetProcAddress(lib, "free");
|
||||
}
|
||||
|
||||
/*[LinkName(.C), AlwaysInclude]
|
||||
static void __chkstk()
|
||||
{
|
||||
|
||||
}*/
|
||||
|
||||
[LinkName(.C), AlwaysInclude]
|
||||
static void* malloc(int size)
|
||||
{
|
||||
return sMallocFunc(size);
|
||||
}
|
||||
|
||||
[LinkName(.C), AlwaysInclude]
|
||||
static void free(void* ptr)
|
||||
{
|
||||
sFreeFunc(ptr);
|
||||
}
|
||||
|
||||
[LinkName(.C), AlwaysInclude]
|
||||
static void memset(void* dest, uint8 val, int size)
|
||||
{
|
||||
uint8* outPtr = (.)dest;
|
||||
for (int i < size)
|
||||
*(outPtr++) = val;
|
||||
}
|
||||
|
||||
[LinkName(.C), AlwaysInclude]
|
||||
static void memcpy(void* dest, void* src, int size)
|
||||
{
|
||||
uint8* destPtr = (.)dest;
|
||||
uint8* srcPtr = (.)src;
|
||||
|
||||
if (destPtr < srcPtr)
|
||||
{
|
||||
for (int i < size)
|
||||
*(destPtr++) = *(srcPtr++);
|
||||
}
|
||||
else
|
||||
{
|
||||
destPtr += size;
|
||||
srcPtr += size;
|
||||
for (int i < size)
|
||||
*(--destPtr) = *(--srcPtr);
|
||||
}
|
||||
}
|
||||
|
||||
[LinkName(.C), AlwaysInclude]
|
||||
static void memmove(void* dest, void* src, int size)
|
||||
{
|
||||
uint8* destPtr = (.)dest;
|
||||
uint8* srcPtr = (.)src;
|
||||
|
||||
if (destPtr < srcPtr)
|
||||
{
|
||||
for (int i < size)
|
||||
*(destPtr++) = *(srcPtr++);
|
||||
}
|
||||
else
|
||||
{
|
||||
destPtr += size;
|
||||
srcPtr += size;
|
||||
for (int i < size)
|
||||
*(--destPtr) = *(--srcPtr);
|
||||
}
|
||||
}
|
||||
|
||||
[LinkName(.C), AlwaysInclude]
|
||||
static double strtod(char8* str, char8** endPtr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
[LinkName(.C), AlwaysInclude]
|
||||
static extern void WinMain(void* module, void* prevModule, char8* args, int32 showCmd);
|
||||
|
||||
[LinkName(.C), AlwaysInclude]
|
||||
static extern int32 main(int argc, char8** argv);
|
||||
|
||||
[LinkName(.C), AlwaysInclude]
|
||||
static void mainCRTStartup()
|
||||
{
|
||||
//WinMain(null, null, "hi", 1);
|
||||
main(0, null);
|
||||
}
|
||||
|
||||
[LinkName(.C), Export]
|
||||
static int32 _tls_index;
|
||||
|
||||
[LinkName(.C), Export]
|
||||
static bool _fltused;
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -330,7 +330,7 @@ namespace System
|
|||
public override void ToString(String strBuffer)
|
||||
{
|
||||
strBuffer.Append("(");
|
||||
typeof(T).GetFullName(strBuffer);
|
||||
typeof(T).ToString(strBuffer);
|
||||
strBuffer.AppendF("*)0x{0:A}[{1}]", (uint)(void*)mPtr, mLength);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ using System.Threading;
|
|||
using System.Interop;
|
||||
using System;
|
||||
|
||||
using internal System.String;
|
||||
|
||||
namespace System
|
||||
{
|
||||
// String size type
|
||||
|
@ -46,6 +48,13 @@ namespace System
|
|||
NullTerminate = 1
|
||||
}
|
||||
|
||||
internal struct Interns
|
||||
{
|
||||
public static Monitor sMonitor = new Monitor() ~ delete _;
|
||||
public static HashSet<String> sInterns = new .() ~ delete _;
|
||||
public static List<String> sOwnedInterns = new .() ~ DeleteContainerAndItems!(_);
|
||||
}
|
||||
|
||||
int_strsize mLength;
|
||||
uint_strsize mAllocSizeAndFlags;
|
||||
char8* mPtrOrBuffer = null;
|
||||
|
@ -53,9 +62,6 @@ namespace System
|
|||
extern const String* sStringLiterals;
|
||||
extern const String* sIdStringLiterals;
|
||||
static String* sPrevInternLinkPtr; // For detecting changes to sStringLiterals for hot loads
|
||||
static Monitor sMonitor = new Monitor() ~ delete _;
|
||||
static HashSet<String> sInterns = new .() ~ delete _;
|
||||
static List<String> sOwnedInterns = new .() ~ DeleteContainerAndItems!(_);
|
||||
public const String Empty = "";
|
||||
|
||||
#if BF_LARGE_STRINGS
|
||||
|
@ -619,7 +625,6 @@ namespace System
|
|||
String.Quote(Ptr, mLength, outString);
|
||||
}
|
||||
|
||||
[AlwaysInclude]
|
||||
public char8* CStr()
|
||||
{
|
||||
EnsureNullTerminator();
|
||||
|
@ -2846,15 +2851,15 @@ namespace System
|
|||
String str = *(ptr++);
|
||||
if (str == null)
|
||||
break;
|
||||
sInterns.Add(str);
|
||||
Interns.sInterns.Add(str);
|
||||
}
|
||||
}
|
||||
|
||||
public String Intern()
|
||||
{
|
||||
using (sMonitor.Enter())
|
||||
using (Interns.sMonitor.Enter())
|
||||
{
|
||||
bool needsLiteralPass = sInterns.Count == 0;
|
||||
bool needsLiteralPass = Interns.sInterns.Count == 0;
|
||||
String* internalLinkPtr = *((String**)(sStringLiterals));
|
||||
if (internalLinkPtr != sPrevInternLinkPtr)
|
||||
{
|
||||
|
@ -2865,13 +2870,13 @@ namespace System
|
|||
CheckLiterals(sStringLiterals);
|
||||
|
||||
String* entryPtr;
|
||||
if (sInterns.TryAdd(this, out entryPtr))
|
||||
if (Interns.sInterns.TryAdd(this, out entryPtr))
|
||||
{
|
||||
String result = new String(mLength + 1);
|
||||
result.Append(this);
|
||||
result.EnsureNullTerminator();
|
||||
*entryPtr = result;
|
||||
sOwnedInterns.Add(result);
|
||||
Interns.sOwnedInterns.Add(result);
|
||||
return result;
|
||||
}
|
||||
return *entryPtr;
|
||||
|
@ -4256,9 +4261,9 @@ namespace System
|
|||
|
||||
public String Intern()
|
||||
{
|
||||
using (String.[Friend]sMonitor.Enter())
|
||||
using (String.Interns.sMonitor.Enter())
|
||||
{
|
||||
bool needsLiteralPass = String.[Friend]sInterns.Count == 0;
|
||||
bool needsLiteralPass = String.Interns.sInterns.Count == 0;
|
||||
String* internalLinkPtr = *((String**)(String.[Friend]sStringLiterals));
|
||||
if (internalLinkPtr != String.[Friend]sPrevInternLinkPtr)
|
||||
{
|
||||
|
@ -4269,13 +4274,13 @@ namespace System
|
|||
String.[Friend]CheckLiterals(String.[Friend]sStringLiterals);
|
||||
|
||||
String* entryPtr;
|
||||
if (String.[Friend]sInterns.TryAddAlt(this, out entryPtr))
|
||||
if (String.Interns.sInterns.TryAddAlt(this, out entryPtr))
|
||||
{
|
||||
String result = new String(mLength + 1);
|
||||
result.Append(this);
|
||||
result.EnsureNullTerminator();
|
||||
*entryPtr = result;
|
||||
String.[Friend]sOwnedInterns.Add(result);
|
||||
String.Interns.sOwnedInterns.Add(result);
|
||||
return result;
|
||||
}
|
||||
return *entryPtr;
|
||||
|
@ -4367,7 +4372,7 @@ namespace System
|
|||
}
|
||||
|
||||
#if TEST
|
||||
extension String
|
||||
class StringTest
|
||||
{
|
||||
[Test]
|
||||
public static void Test_Intern()
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace System
|
|||
{
|
||||
if (!condition)
|
||||
{
|
||||
if (Runtime.CheckErrorHandlers(scope Runtime.AssertError(.Test, error, filePath, line)) == .Ignore)
|
||||
if ((Runtime.CheckAssertError != null) && (Runtime.CheckAssertError(.Test, error, filePath, line) == .Ignore))
|
||||
return;
|
||||
String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath);
|
||||
Internal.[Friend]Test_Error(failStr);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
namespace System.Text
|
||||
{
|
||||
[StaticInitPriority(100)]
|
||||
|
@ -15,11 +16,39 @@ namespace System.Text
|
|||
case PartialEncode(int inChars, int encodedBytes);
|
||||
}
|
||||
|
||||
public static readonly ASCIIEncoding ASCII = new ASCIIEncoding() ~ delete _;
|
||||
public static readonly UTF8Encoding UTF8 = new UTF8Encoding() ~ delete _;
|
||||
public static readonly UTF8EncodingWithBOM UTF8WithBOM = new UTF8EncodingWithBOM() ~ delete _;
|
||||
public static readonly UTF16Encoding UTF16 = new UTF16Encoding() ~ delete _;
|
||||
public static readonly UTF16EncodingWithBOM UTF16WithBOM = new UTF16EncodingWithBOM() ~ delete _;
|
||||
static Encoding sASCII ~ delete _;
|
||||
static Encoding sUTF8 ~ delete _;
|
||||
static Encoding sUTF8WithBOM ~ delete _;
|
||||
static Encoding sUTF16 ~ delete _;
|
||||
static Encoding sUTF16WithBOM ~ delete _;
|
||||
|
||||
static T GetEncoding<T>(ref Encoding encoding) where T : Encoding, new, delete
|
||||
{
|
||||
if (encoding != null)
|
||||
return (.)encoding;
|
||||
|
||||
var newEncoding = new T();
|
||||
if (Compiler.IsComptime)
|
||||
{
|
||||
encoding = newEncoding;
|
||||
return newEncoding;
|
||||
}
|
||||
|
||||
let prevValue = Interlocked.CompareExchange(ref encoding, null, newEncoding);
|
||||
if (prevValue != null)
|
||||
{
|
||||
// This was already set - race condition
|
||||
delete newEncoding;
|
||||
return (.)prevValue;
|
||||
}
|
||||
return newEncoding;
|
||||
}
|
||||
|
||||
public static ASCIIEncoding ASCII => GetEncoding<ASCIIEncoding>(ref sASCII);
|
||||
public static UTF8Encoding UTF8 => GetEncoding<UTF8Encoding>(ref sUTF8);
|
||||
public static UTF8EncodingWithBOM UTF8WithBOM => GetEncoding<UTF8EncodingWithBOM>(ref sUTF8WithBOM);
|
||||
public static UTF16Encoding UTF16 => GetEncoding<UTF16Encoding>(ref sUTF16);
|
||||
public static UTF16EncodingWithBOM UTF16WithBOM => GetEncoding<UTF16EncodingWithBOM>(ref sUTF16WithBOM);
|
||||
|
||||
public abstract int GetCharUnitSize();
|
||||
public abstract int GetEncodedLength(char32 c);
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace System.Threading
|
|||
static Event<delegate void()> sOnExit ~ _.Dispose();
|
||||
Event<delegate void()> mOnExit ~ _.Dispose();
|
||||
|
||||
public static Thread sMainThread = new Thread() ~ delete _;
|
||||
public static Thread sMainThread ~ delete _;
|
||||
|
||||
[StaticInitPriority(102)]
|
||||
struct RuntimeThreadInit
|
||||
|
@ -48,8 +48,10 @@ namespace System.Threading
|
|||
|
||||
static void Thread_SetInternalThread(Object thread, void* internalThread)
|
||||
{
|
||||
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||
if (internalThread != null)
|
||||
GC.[Friend]AddPendingThread(internalThread);
|
||||
#endif
|
||||
((Thread)thread).[Friend]mInternalThread = (int)internalThread;
|
||||
}
|
||||
|
||||
|
@ -118,7 +120,18 @@ namespace System.Threading
|
|||
cb.[Friend]mThread_AutoDelete = => Thread_AutoDelete;
|
||||
cb.[Friend]mThread_GetMaxStackSize = => Thread_GetMaxStackSize;
|
||||
cb.[Friend]mThread_Exiting = => Thread_Exiting;
|
||||
|
||||
Runtime.[Friend, NoStaticCtor]sThreadInit = => Thread.Init;
|
||||
}
|
||||
|
||||
public static void Check()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static this()
|
||||
{
|
||||
RuntimeThreadInit.Check();
|
||||
}
|
||||
|
||||
private this()
|
||||
|
@ -170,6 +183,7 @@ namespace System.Threading
|
|||
{
|
||||
#unwarn
|
||||
RuntimeThreadInit runtimeThreadInitRef = ?;
|
||||
sMainThread = new Thread();
|
||||
sMainThread.ManualThreadInit();
|
||||
}
|
||||
|
||||
|
@ -225,11 +239,6 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
extern void ManualThreadInit();
|
||||
extern void StartInternal();
|
||||
extern void SetStackStart(void* ptr);
|
||||
extern void ThreadStarted();
|
||||
|
||||
public void Start(bool autoDelete = true)
|
||||
{
|
||||
mAutoDelete = autoDelete;
|
||||
|
@ -247,7 +256,7 @@ namespace System.Threading
|
|||
StartInternal();
|
||||
}
|
||||
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
#if BF_PLATFORM_WINDOWS && !BF_RUNTIME_DISABLE
|
||||
[CLink]
|
||||
static extern int32 _tls_index;
|
||||
#endif
|
||||
|
@ -256,7 +265,7 @@ namespace System.Threading
|
|||
{
|
||||
get
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
#if BF_PLATFORM_WINDOWS && !BF_RUNTIME_DISABLE
|
||||
return _tls_index;
|
||||
#else
|
||||
return 0;
|
||||
|
@ -264,10 +273,6 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
public static extern void RequestExitNotify();
|
||||
public extern void Suspend();
|
||||
public extern void Resume();
|
||||
|
||||
public ThreadPriority Priority
|
||||
{
|
||||
get
|
||||
|
@ -283,12 +288,7 @@ namespace System.Threading
|
|||
SetPriorityNative((int32)value);
|
||||
}
|
||||
}
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern int32 GetPriorityNative();
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern void SetPriorityNative(int32 priority);
|
||||
|
||||
extern bool GetIsAlive();
|
||||
public bool IsAlive
|
||||
{
|
||||
get
|
||||
|
@ -297,8 +297,7 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
[CallingConvention(.Cdecl)]
|
||||
extern bool GetIsThreadPoolThread();
|
||||
|
||||
public bool IsThreadPoolThread
|
||||
{
|
||||
get
|
||||
|
@ -307,8 +306,6 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
private extern bool JoinInternal(int32 millisecondsTimeout);
|
||||
|
||||
public void Join()
|
||||
{
|
||||
JoinInternal(Timeout.Infinite);
|
||||
|
@ -328,7 +325,6 @@ namespace System.Threading
|
|||
return Join((int32)tm);
|
||||
}
|
||||
|
||||
private static extern void SleepInternal(int32 millisecondsTimeout);
|
||||
public static void Sleep(int32 millisecondsTimeout)
|
||||
{
|
||||
SleepInternal(millisecondsTimeout);
|
||||
|
@ -342,15 +338,11 @@ namespace System.Threading
|
|||
Sleep((int32)tm);
|
||||
}
|
||||
|
||||
private static extern void SpinWaitInternal(int32 iterations);
|
||||
|
||||
public static void SpinWait(int iterations)
|
||||
{
|
||||
SpinWaitInternal((int32)iterations);
|
||||
}
|
||||
|
||||
private static extern bool YieldInternal();
|
||||
|
||||
public static bool Yield()
|
||||
{
|
||||
return YieldInternal();
|
||||
|
@ -364,9 +356,6 @@ namespace System.Threading
|
|||
}
|
||||
}
|
||||
|
||||
[CallingConvention(.Cdecl)]
|
||||
extern int GetThreadId();
|
||||
|
||||
public int Id
|
||||
{
|
||||
get
|
||||
|
@ -377,9 +366,6 @@ namespace System.Threading
|
|||
|
||||
public static int CurrentThreadId => Platform.BfpThread_GetCurrentId();
|
||||
|
||||
[CallingConvention(.Cdecl)]
|
||||
private static extern Thread GetCurrentThreadNative();
|
||||
|
||||
void SetStart(Delegate ownStartDelegate, int32 maxStackSize)
|
||||
{
|
||||
mDelegate = ownStartDelegate;
|
||||
|
@ -405,18 +391,11 @@ namespace System.Threading
|
|||
delete mDelegate;
|
||||
}
|
||||
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern void InternalFinalize();
|
||||
|
||||
public bool IsBackground
|
||||
{
|
||||
get { return IsBackgroundNative(); }
|
||||
set { SetBackgroundNative(value); }
|
||||
}
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern bool IsBackgroundNative();
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern void SetBackgroundNative(bool isBackground);
|
||||
|
||||
public void SetJoinOnDelete(bool joinOnDelete)
|
||||
{
|
||||
|
@ -427,8 +406,6 @@ namespace System.Threading
|
|||
{
|
||||
get { return (ThreadState)GetThreadStateNative(); }
|
||||
}
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern int32 GetThreadStateNative();
|
||||
|
||||
public void SetName(String name)
|
||||
{
|
||||
|
@ -450,7 +427,63 @@ namespace System.Threading
|
|||
if (mName != null)
|
||||
outName.Append(mName);
|
||||
}
|
||||
|
||||
#if !BF_RUNTIME_DISABLE
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern void InformThreadNameChange(String name);
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern bool IsBackgroundNative();
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern void SetBackgroundNative(bool isBackground);
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern void InternalFinalize();
|
||||
[CallingConvention(.Cdecl)]
|
||||
private static extern Thread GetCurrentThreadNative();
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern int32 GetPriorityNative();
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern void SetPriorityNative(int32 priority);
|
||||
[CallingConvention(.Cdecl)]
|
||||
extern bool GetIsThreadPoolThread();
|
||||
[CallingConvention(.Cdecl)]
|
||||
extern int GetThreadId();
|
||||
[CallingConvention(.Cdecl)]
|
||||
private extern int32 GetThreadStateNative();
|
||||
private static extern void SpinWaitInternal(int32 iterations);
|
||||
private static extern void SleepInternal(int32 millisecondsTimeout);
|
||||
private extern bool JoinInternal(int32 millisecondsTimeout);
|
||||
private static extern bool YieldInternal();
|
||||
extern void ManualThreadInit();
|
||||
extern void StartInternal();
|
||||
extern void SetStackStart(void* ptr);
|
||||
extern void ThreadStarted();
|
||||
public static extern void RequestExitNotify();
|
||||
public extern void Suspend();
|
||||
public extern void Resume();
|
||||
extern bool GetIsAlive();
|
||||
#else
|
||||
private void InformThreadNameChange(String name) {}
|
||||
private bool IsBackgroundNative() => false;
|
||||
private void SetBackgroundNative(bool isBackground) {}
|
||||
private void InternalFinalize() {}
|
||||
private static Thread GetCurrentThreadNative() => null;
|
||||
private int32 GetPriorityNative() => 0;
|
||||
private void SetPriorityNative(int32 priority) {}
|
||||
bool GetIsThreadPoolThread() => false;
|
||||
int GetThreadId() => 0;
|
||||
private int32 GetThreadStateNative() => 0;
|
||||
private static void SpinWaitInternal(int32 iterations) {}
|
||||
private static void SleepInternal(int32 millisecondsTimeout) {}
|
||||
private bool JoinInternal(int32 millisecondsTimeout) => false;
|
||||
private static bool YieldInternal() => false;
|
||||
void ManualThreadInit() {}
|
||||
void StartInternal() {}
|
||||
void SetStackStart(void* ptr) {}
|
||||
void ThreadStarted() {}
|
||||
public static void RequestExitNotify() {}
|
||||
public void Suspend() {}
|
||||
public void Resume() {}
|
||||
bool GetIsAlive() => false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,15 @@ namespace System
|
|||
{
|
||||
struct ClassVData
|
||||
{
|
||||
public Type mType;
|
||||
public int mType;
|
||||
#if BF_32_BIT
|
||||
public int mType2;
|
||||
#endif
|
||||
// The rest of this structured is generated by the compiler,
|
||||
// including the vtable and interface slots
|
||||
}
|
||||
|
||||
[Ordered, AlwaysInclude(AssumeInstantiated=true)]
|
||||
[Ordered, AlwaysInclude, Reflect(.Type)]
|
||||
public class Type
|
||||
{
|
||||
extern const Type* sTypes;
|
||||
|
@ -746,7 +749,12 @@ namespace System
|
|||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
#if !BF_REFLECT_MINIMAL
|
||||
GetFullName(strBuffer);
|
||||
#else
|
||||
strBuffer.Append("Type#");
|
||||
mTypeId.ToString(strBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
public struct Enumerator : IEnumerator<Type>
|
||||
|
@ -890,6 +898,7 @@ namespace System.Reflection
|
|||
public int32 mCustomAttributesIdx;
|
||||
}
|
||||
|
||||
[CRepr, AlwaysInclude]
|
||||
public struct InterfaceData
|
||||
{
|
||||
public TypeId mInterfaceType;
|
||||
|
@ -1272,7 +1281,7 @@ namespace System.Reflection
|
|||
if (size == -1)
|
||||
strBuffer.Append("[?]");
|
||||
else
|
||||
strBuffer.AppendF($"[{size}]");
|
||||
strBuffer.AppendF($"[{(Int.Simple)size}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,14 @@ namespace System
|
|||
case InvalidChar(uint partialResult);
|
||||
}
|
||||
|
||||
public struct Simple : uint
|
||||
{
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
((uint)this).ToString(strBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public const uint MaxValue = (sizeof(uint) == 8) ? 0xFFFFFFFFFFFFFFFFUL : 0xFFFFFFFFL;
|
||||
public const uint MinValue = 0;
|
||||
|
||||
|
|
|
@ -58,8 +58,6 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
static String sHexUpperChars = "0123456789ABCDEF";
|
||||
static String sHexLowerChars = "0123456789abcdef";
|
||||
public void ToString(String outString, String format, IFormatProvider formatProvider)
|
||||
{
|
||||
if(format == null || format.IsEmpty)
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace bf
|
|||
bf::System::Object* (*Object_DynamicCastToTypeId)(bf::System::Object* obj, int typeId);
|
||||
void(*Type_GetFullName)(System::Type* type, bf::System::String* str);
|
||||
bf::System::String* (*String_Alloc)();
|
||||
const char* (*String_ToCStr)(bf::System::String* str);
|
||||
Beefy::StringView (*String_ToStringView)(bf::System::String* str);
|
||||
bf::System::Threading::Thread* (*Thread_Alloc)();
|
||||
bf::System::Threading::Thread* (*Thread_GetMainThread)();
|
||||
void(*Thread_ThreadProc)(bf::System::Threading::Thread* thread);
|
||||
|
@ -116,6 +116,8 @@ namespace bf
|
|||
|
||||
private:
|
||||
BFRT_EXPORT static void Init(int version, int flags, BfRtCallbacks* callbacks);
|
||||
BFRT_EXPORT static void InitCrashCatcher(int flags);
|
||||
BFRT_EXPORT static void ShutdownCrashCatcher();
|
||||
BFRT_EXPORT static void AddCrashInfoFunc(void* func);
|
||||
BFRT_EXPORT static void SetErrorString(char* errorStr);
|
||||
BFRT_EXPORT static void Dbg_Init(int version, int flags, BfRtCallbacks* callbacks);
|
||||
|
@ -252,9 +254,9 @@ namespace bf
|
|||
uint mAllocSizeAndFlags;
|
||||
char* mPtr;
|
||||
|
||||
const char* CStr()
|
||||
Beefy::StringView ToStringView()
|
||||
{
|
||||
return BFRTCALLBACKS.String_ToCStr(this);
|
||||
return BFRTCALLBACKS.String_ToStringView(this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
USING_NS_BF;
|
||||
|
||||
static Beefy::StringT<0> gCmdLineString;
|
||||
bool gCmdLineStringHandled;
|
||||
bf::System::Runtime::BfRtCallbacks gBfRtCallbacks;
|
||||
BfRtFlags gBfRtFlags = (BfRtFlags)0;
|
||||
|
||||
|
@ -65,7 +66,10 @@ static int gTestMethodIdx = -1;
|
|||
static uint32 gTestStartTick = 0;
|
||||
static bool gTestBreakOnFailure = false;
|
||||
|
||||
typedef void(*ClientPipeErrorFunc)(const Beefy::StringView& error, int stackOffset);
|
||||
|
||||
static BfpFile* gClientPipe = NULL;
|
||||
static ClientPipeErrorFunc gClientPipeErrorFunc;
|
||||
static Beefy::String gTestInBuffer;
|
||||
|
||||
namespace bf
|
||||
|
@ -85,7 +89,7 @@ namespace bf
|
|||
|
||||
BFRT_EXPORT static void BfStaticCtor();
|
||||
BFRT_EXPORT static void BfStaticDtor();
|
||||
BFRT_EXPORT static void Shutdown();
|
||||
BFRT_EXPORT static void Shutdown_Internal();
|
||||
public:
|
||||
BFRT_EXPORT static Object* UnsafeCastToObject(void* inPtr);
|
||||
BFRT_EXPORT static void* UnsafeCastToPtr(Object* obj);
|
||||
|
@ -224,18 +228,8 @@ static void Internal_FatalError(const char* error)
|
|||
if (gBfRtCallbacks.CheckErrorHandler != NULL)
|
||||
gBfRtCallbacks.CheckErrorHandler("FatalError", error, NULL, 0);
|
||||
|
||||
if ((gClientPipe != NULL) && (!gTestBreakOnFailure))
|
||||
{
|
||||
Beefy::String str = ":TestFatal\t";
|
||||
str += error;
|
||||
str.Replace('\n', '\r');
|
||||
str += "\n";
|
||||
TestString(str);
|
||||
|
||||
Beefy::String result;
|
||||
TestReadCmd(result);
|
||||
exit(1);
|
||||
}
|
||||
if (gClientPipeErrorFunc != NULL)
|
||||
gClientPipeErrorFunc(error, 0);
|
||||
else
|
||||
BfpSystem_FatalError(error, "BEEF FATAL ERROR");
|
||||
}
|
||||
|
@ -304,57 +298,22 @@ void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
|
|||
if ((flags & 4) != 0)
|
||||
sysInitFlags = (BfpSystemInitFlags)(sysInitFlags | BfpSystemInitFlag_SilentCrash);
|
||||
BfpSystem_Init(BFP_VERSION, sysInitFlags);
|
||||
BfpSystem_AddCrashInfoFunc(GetCrashInfo);
|
||||
|
||||
if (gBfRtCallbacks.Alloc != NULL)
|
||||
{
|
||||
Internal_FatalError(StrFormat("BeefRT already initialized. Multiple executable modules in the same process cannot dynamically link to the Beef runtime.").c_str());
|
||||
Internal_FatalError("BeefRT already initialized. Multiple executable modules in the same process cannot dynamically link to the Beef runtime.");
|
||||
}
|
||||
|
||||
if (version != BFRT_VERSION)
|
||||
{
|
||||
BfpSystem_FatalError(StrFormat("BeefRT build version '%d' does not match requested version '%d'", BFRT_VERSION, version).c_str(), "BEEF FATAL ERROR");
|
||||
char error[256];
|
||||
sprintf(error, "BeefRT build version '%d' does not match requested version '%d'", BFRT_VERSION, version);
|
||||
BfpSystem_FatalError(error, "BEEF FATAL ERROR");
|
||||
}
|
||||
|
||||
gBfRtCallbacks = *callbacks;
|
||||
gBfRtFlags = (BfRtFlags)flags;
|
||||
|
||||
Beefy::String cmdLine;
|
||||
|
||||
BfpSystemResult result;
|
||||
BFP_GETSTR_HELPER(cmdLine, result, BfpSystem_GetCommandLine(__STR, __STRLEN, &result));
|
||||
|
||||
char* cmdLineStr = (char*)cmdLine.c_str();
|
||||
|
||||
//::MessageBoxA(NULL, cmdLineStr, "BFRT", 0);
|
||||
|
||||
char* useCmdLineStr = cmdLineStr;
|
||||
|
||||
if (cmdLineStr[0] != 0)
|
||||
{
|
||||
bool nameQuoted = cmdLineStr[0] == '\"';
|
||||
|
||||
Beefy::String passedName;
|
||||
int i;
|
||||
for (i = (nameQuoted ? 1 : 0); cmdLineStr[i] != 0; i++)
|
||||
{
|
||||
wchar_t c = cmdLineStr[i];
|
||||
|
||||
if (((nameQuoted) && (c == '"')) ||
|
||||
((!nameQuoted) && (c == ' ')))
|
||||
{
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
passedName += cmdLineStr[i];
|
||||
}
|
||||
|
||||
useCmdLineStr += i;
|
||||
while (*useCmdLineStr == L' ')
|
||||
useCmdLineStr++;
|
||||
}
|
||||
gCmdLineString = useCmdLineStr;
|
||||
|
||||
#ifdef BF_PLATFORM_WINDOWS
|
||||
gBfTLSKey = FlsAlloc(TlsFreeFunc);
|
||||
#else
|
||||
|
@ -362,6 +321,20 @@ void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
|
|||
#endif
|
||||
}
|
||||
|
||||
void bf::System::Runtime::InitCrashCatcher(int flags)
|
||||
{
|
||||
BfpSystemInitFlags sysInitFlags = BfpSystemInitFlag_InstallCrashCatcher;
|
||||
if ((flags & 4) != 0)
|
||||
sysInitFlags = (BfpSystemInitFlags)(sysInitFlags | BfpSystemInitFlag_SilentCrash);
|
||||
BfpSystem_InitCrashCatcher(sysInitFlags);
|
||||
BfpSystem_AddCrashInfoFunc(GetCrashInfo);
|
||||
}
|
||||
|
||||
void bf::System::Runtime::ShutdownCrashCatcher()
|
||||
{
|
||||
BfpSystem_ShutdownCrashCatcher();
|
||||
}
|
||||
|
||||
void bf::System::Runtime::SetErrorString(char* errorStr)
|
||||
{
|
||||
::SetErrorString(errorStr);
|
||||
|
@ -379,7 +352,7 @@ void bf::System::Runtime::SetCrashReportKind(bf::System::Runtime::RtCrashReportK
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Internal::Shutdown()
|
||||
void Internal::Shutdown_Internal()
|
||||
{
|
||||
BfInternalThread::WaitForAllDone();
|
||||
if (gBfRtCallbacks.GC_Shutdown != NULL)
|
||||
|
@ -419,20 +392,9 @@ void* Internal::UnsafeCastToPtr(Object* obj)
|
|||
|
||||
void Internal::ThrowIndexOutOfRange(intptr stackOffset)
|
||||
{
|
||||
if (gClientPipe != NULL)
|
||||
{
|
||||
if (gTestBreakOnFailure)
|
||||
{
|
||||
SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
|
||||
BF_DEBUG_BREAK();
|
||||
}
|
||||
|
||||
Beefy::String str = ":TestFail\tIndex out of range\n";
|
||||
TestString(str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((stackOffset != -1) && (::IsDebuggerPresent()))
|
||||
if (gClientPipeErrorFunc != NULL)
|
||||
gClientPipeErrorFunc("Index out of range", 0);
|
||||
else if ((stackOffset != -1) && (::IsDebuggerPresent()))
|
||||
{
|
||||
SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
|
||||
BF_DEBUG_BREAK();
|
||||
|
@ -443,20 +405,9 @@ void Internal::ThrowIndexOutOfRange(intptr stackOffset)
|
|||
|
||||
void Internal::ThrowObjectNotInitialized(intptr stackOffset)
|
||||
{
|
||||
if (gClientPipe != NULL)
|
||||
{
|
||||
if (gTestBreakOnFailure)
|
||||
{
|
||||
SETUP_ERROR("Object not initialized", (int)(2 + stackOffset));
|
||||
BF_DEBUG_BREAK();
|
||||
}
|
||||
|
||||
Beefy::String str = ":TestFail\tObject not initialized\n";
|
||||
TestString(str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((stackOffset != -1) && (::IsDebuggerPresent()))
|
||||
if (gClientPipeErrorFunc != NULL)
|
||||
gClientPipeErrorFunc("Object not initialized", 0);
|
||||
else if ((stackOffset != -1) && (::IsDebuggerPresent()))
|
||||
{
|
||||
SETUP_ERROR("Object not initialized", (int)(2 + stackOffset));
|
||||
BF_DEBUG_BREAK();
|
||||
|
@ -467,29 +418,17 @@ void Internal::ThrowObjectNotInitialized(intptr stackOffset)
|
|||
|
||||
void Internal::FatalError(bf::System::String* error, intptr stackOffset)
|
||||
{
|
||||
if (gClientPipe != NULL)
|
||||
{
|
||||
if (gTestBreakOnFailure)
|
||||
{
|
||||
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
|
||||
BF_DEBUG_BREAK();
|
||||
}
|
||||
|
||||
Beefy::String str = ":TestFail\t";
|
||||
str += error->CStr();
|
||||
str.Replace('\n', '\r');
|
||||
str += "\n";
|
||||
TestString(str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Beefy::StringView errorStringView = error->ToStringView();
|
||||
Beefy::StringSimple errorString = errorStringView;
|
||||
if (gClientPipeErrorFunc != NULL)
|
||||
gClientPipeErrorFunc(errorStringView, 0);
|
||||
if ((stackOffset != -1) && (::IsDebuggerPresent()))
|
||||
{
|
||||
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
|
||||
SETUP_ERROR(errorString.c_str(), (int)(2 + stackOffset));
|
||||
BF_DEBUG_BREAK();
|
||||
}
|
||||
|
||||
Internal_FatalError(error->CStr());
|
||||
Internal_FatalError(errorString.c_str());
|
||||
}
|
||||
|
||||
void Internal::MemCpy(void* dest, void* src, intptr length)
|
||||
|
@ -630,6 +569,46 @@ void Internal::GetSharedProcAddressInto(void* libHandle, char* procName, void**
|
|||
|
||||
char* Internal::GetCommandLineArgs()
|
||||
{
|
||||
if (!gCmdLineStringHandled)
|
||||
{
|
||||
Beefy::String cmdLine;
|
||||
|
||||
BfpSystemResult result;
|
||||
BFP_GETSTR_HELPER(cmdLine, result, BfpSystem_GetCommandLine(__STR, __STRLEN, &result));
|
||||
|
||||
char* cmdLineStr = (char*)cmdLine.c_str();
|
||||
|
||||
//::MessageBoxA(NULL, cmdLineStr, "BFRT", 0);
|
||||
|
||||
char* useCmdLineStr = cmdLineStr;
|
||||
|
||||
if (cmdLineStr[0] != 0)
|
||||
{
|
||||
bool nameQuoted = cmdLineStr[0] == '\"';
|
||||
|
||||
Beefy::String passedName;
|
||||
int i;
|
||||
for (i = (nameQuoted ? 1 : 0); cmdLineStr[i] != 0; i++)
|
||||
{
|
||||
wchar_t c = cmdLineStr[i];
|
||||
|
||||
if (((nameQuoted) && (c == '"')) ||
|
||||
((!nameQuoted) && (c == ' ')))
|
||||
{
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
passedName += cmdLineStr[i];
|
||||
}
|
||||
|
||||
useCmdLineStr += i;
|
||||
while (*useCmdLineStr == L' ')
|
||||
useCmdLineStr++;
|
||||
}
|
||||
gCmdLineString = useCmdLineStr;
|
||||
gCmdLineStringHandled = true;
|
||||
}
|
||||
|
||||
return (char*)gCmdLineString.c_str();
|
||||
}
|
||||
|
||||
|
@ -697,6 +676,27 @@ static void TestReadCmd(Beefy::String& str)
|
|||
}
|
||||
}
|
||||
|
||||
void TestFailed(const Beefy::StringView& error, int stackOffset)
|
||||
{
|
||||
if (gClientPipe != NULL)
|
||||
{
|
||||
Beefy::String errorString = error;
|
||||
|
||||
if (gTestBreakOnFailure)
|
||||
{
|
||||
SETUP_ERROR(errorString.c_str(), (int)(2 + stackOffset));
|
||||
BF_DEBUG_BREAK();
|
||||
}
|
||||
|
||||
Beefy::String str = ":TestFail\t";
|
||||
str += errorString.c_str();
|
||||
str.Replace('\n', '\r');
|
||||
str += "\n";
|
||||
TestString(str);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void Internal::Test_Init(char* testData)
|
||||
{
|
||||
BfpSystem_SetCrashReportKind(BfpCrashReportKind_None);
|
||||
|
@ -708,6 +708,8 @@ void Internal::Test_Init(char* testData)
|
|||
if (fileResult != BfpFileResult_Ok)
|
||||
BF_FATAL("Test_Init failed to create pipe to test manager");
|
||||
|
||||
gClientPipeErrorFunc = TestFailed;
|
||||
|
||||
Beefy::String outStr;
|
||||
outStr += ":TestInit\n";
|
||||
outStr += testData;
|
||||
|
@ -853,7 +855,6 @@ void Internal::ObjectDynCheck(bf::System::Object* object, int typeId, bool allow
|
|||
if (result == NULL)
|
||||
{
|
||||
Beefy::String errorStr = "Attempting invalid cast on object";
|
||||
//errorStr += StrFormat("\x1LEAK\t0x%@\n (%s)0x%@\n", object, object->GetTypeName().c_str(), object);
|
||||
errorStr += StrFormat("\x1LEAK\t0x%@\n (%s)0x%@\n", object, "System.Object", object);
|
||||
SETUP_ERROR(errorStr.c_str(), 2);
|
||||
BF_DEBUG_BREAK();
|
||||
|
|
|
@ -7,7 +7,7 @@ Beefy::String bf::System::Object::GetTypeName()
|
|||
String* strObj = BFRTCALLBACKS.String_Alloc();
|
||||
Type* type = _GetType();
|
||||
BFRTCALLBACKS.Type_GetFullName(type, strObj);
|
||||
Beefy::String str = strObj->CStr();
|
||||
Beefy::String str = strObj->ToStringView();
|
||||
BFRTCALLBACKS.Object_Delete(strObj);
|
||||
return str;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ Beefy::String bf::System::Type::GetFullName()
|
|||
{
|
||||
String* strObj = BFRTCALLBACKS.String_Alloc();
|
||||
BFRTCALLBACKS.Type_GetFullName(this, strObj);
|
||||
Beefy::String str = strObj->CStr();
|
||||
Beefy::String str = strObj->ToStringView();
|
||||
BFRTCALLBACKS.Object_Delete(strObj);
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -318,7 +318,10 @@ int Thread::GetThreadStateNative()
|
|||
|
||||
void Thread::InformThreadNameChange(String* name)
|
||||
{
|
||||
BfpThread_SetName(GetInternalThread()->mThreadHandle, (name != NULL) ? name->CStr() : "", NULL);
|
||||
Beefy::String nameStr;
|
||||
if (name != NULL)
|
||||
nameStr = name->ToStringView();
|
||||
BfpThread_SetName(GetInternalThread()->mThreadHandle, nameStr.c_str(), NULL);
|
||||
}
|
||||
|
||||
void Thread::MemoryBarrier()
|
||||
|
|
|
@ -100,12 +100,14 @@ enum BfpCrashReportKind
|
|||
};
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flags);
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_InitCrashCatcher(BfpSystemInitFlags flags);
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCommandLine(int argc, char** argv);
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashReportKind(BfpCrashReportKind crashReportKind);
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfoFunc(BfpCrashInfoFunc crashInfoFunc);
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfo(const char* str); // Can do at any time, or during CrashInfoFunc callbacks
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashRelaunchCmd(const char* str);
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_Shutdown();
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_ShutdownCrashCatcher();
|
||||
BFP_EXPORT uint32 BFP_CALLTYPE BfpSystem_TickCount();
|
||||
BFP_EXPORT BfpTimeStamp BFP_CALLTYPE BfpSystem_GetTimeStamp();
|
||||
BFP_EXPORT uint16 BFP_CALLTYPE BfpSystem_EndianSwap16(uint16 val);
|
||||
|
|
|
@ -52,7 +52,6 @@ static SYMGETMODULEBASEPROC gSymGetModuleBase = NULL;
|
|||
static SYMGETSYMFROMADDRPROC gSymGetSymFromAddr = NULL;
|
||||
static SYMGETLINEFROMADDR gSymGetLineFromAddr = NULL;
|
||||
|
||||
|
||||
static bool CreateMiniDump(EXCEPTION_POINTERS* pep, const StringImpl& filePath);
|
||||
|
||||
static bool LoadImageHelp()
|
||||
|
@ -117,47 +116,6 @@ static bool LoadImageHelp()
|
|||
return true;
|
||||
}
|
||||
|
||||
struct
|
||||
{
|
||||
DWORD dwExceptionCode;
|
||||
char *szMessage;
|
||||
} gMsgTable[] = {
|
||||
{ STATUS_SEGMENT_NOTIFICATION, "Segment Notification" },
|
||||
{ STATUS_BREAKPOINT, "Breakpoint" },
|
||||
{ STATUS_SINGLE_STEP, "Single step" },
|
||||
{ STATUS_WAIT_0, "Wait 0" },
|
||||
{ STATUS_ABANDONED_WAIT_0, "Abandoned Wait 0" },
|
||||
{ STATUS_USER_APC, "User APC" },
|
||||
{ STATUS_TIMEOUT, "Timeout" },
|
||||
{ STATUS_PENDING, "Pending" },
|
||||
{ STATUS_GUARD_PAGE_VIOLATION, "Guard Page Violation" },
|
||||
{ STATUS_DATATYPE_MISALIGNMENT, "Data Type Misalignment" },
|
||||
{ STATUS_ACCESS_VIOLATION, "Access Violation" },
|
||||
{ STATUS_IN_PAGE_ERROR, "In Page Error" },
|
||||
{ STATUS_NO_MEMORY, "No Memory" },
|
||||
{ STATUS_ILLEGAL_INSTRUCTION, "Illegal Instruction" },
|
||||
{ STATUS_NONCONTINUABLE_EXCEPTION, "Noncontinuable Exception" },
|
||||
{ STATUS_INVALID_DISPOSITION, "Invalid Disposition" },
|
||||
{ STATUS_ARRAY_BOUNDS_EXCEEDED, "Array Bounds Exceeded" },
|
||||
{ STATUS_FLOAT_DENORMAL_OPERAND, "Float Denormal Operand" },
|
||||
{ STATUS_FLOAT_DIVIDE_BY_ZERO, "Divide by Zero" },
|
||||
{ STATUS_FLOAT_INEXACT_RESULT, "Float Inexact Result" },
|
||||
{ STATUS_FLOAT_INVALID_OPERATION, "Float Invalid Operation" },
|
||||
{ STATUS_FLOAT_OVERFLOW, "Float Overflow" },
|
||||
{ STATUS_FLOAT_STACK_CHECK, "Float Stack Check" },
|
||||
{ STATUS_FLOAT_UNDERFLOW, "Float Underflow" },
|
||||
{ STATUS_INTEGER_DIVIDE_BY_ZERO, "Integer Divide by Zero" },
|
||||
{ STATUS_INTEGER_OVERFLOW, "Integer Overflow" },
|
||||
{ STATUS_PRIVILEGED_INSTRUCTION, "Privileged Instruction" },
|
||||
{ STATUS_STACK_OVERFLOW, "Stack Overflow" },
|
||||
{ STATUS_CONTROL_C_EXIT, "Ctrl+C Exit" },
|
||||
{ 0xFFFFFFFF, "" }
|
||||
};
|
||||
|
||||
static HFONT gDialogFont;
|
||||
static HFONT gBoldFont;
|
||||
static String gErrorTitle;
|
||||
static String gErrorText;
|
||||
static HWND gDebugButtonWindow = NULL;
|
||||
static HWND gYesButtonWindow = NULL;
|
||||
static HWND gNoButtonWindow = NULL;
|
||||
|
@ -265,19 +223,19 @@ static void ShowErrorDialog(const StringImpl& errorTitle, const StringImpl& erro
|
|||
gUseDefaultFonts = aVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT;
|
||||
|
||||
int aHeight = -MulDiv(8, 96, 72);
|
||||
gDialogFont = ::CreateFontA(aHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
|
||||
HFONT gDialogFont = ::CreateFontA(aHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
|
||||
false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
||||
DEFAULT_PITCH | FF_DONTCARE, "Tahoma");
|
||||
|
||||
aHeight = -MulDiv(10, 96, 72);
|
||||
gBoldFont = ::CreateFontA(aHeight, 0, 0, 0, FW_BOLD, FALSE, FALSE,
|
||||
HFONT gBoldFont = ::CreateFontA(aHeight, 0, 0, 0, FW_BOLD, FALSE, FALSE,
|
||||
false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
||||
DEFAULT_PITCH | FF_DONTCARE, "Tahoma");
|
||||
|
||||
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
|
||||
|
||||
gErrorTitle = errorTitle;
|
||||
gErrorText = errorText;
|
||||
String gErrorTitle = errorTitle;
|
||||
String gErrorText = errorText;
|
||||
|
||||
WNDCLASSW wc;
|
||||
wc.style = 0;
|
||||
|
@ -935,6 +893,44 @@ static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
|
|||
|
||||
///////////////////////////
|
||||
// first name the exception
|
||||
|
||||
struct
|
||||
{
|
||||
DWORD dwExceptionCode;
|
||||
char* szMessage;
|
||||
} gMsgTable[] = {
|
||||
{ STATUS_SEGMENT_NOTIFICATION, "Segment Notification" },
|
||||
{ STATUS_BREAKPOINT, "Breakpoint" },
|
||||
{ STATUS_SINGLE_STEP, "Single step" },
|
||||
{ STATUS_WAIT_0, "Wait 0" },
|
||||
{ STATUS_ABANDONED_WAIT_0, "Abandoned Wait 0" },
|
||||
{ STATUS_USER_APC, "User APC" },
|
||||
{ STATUS_TIMEOUT, "Timeout" },
|
||||
{ STATUS_PENDING, "Pending" },
|
||||
{ STATUS_GUARD_PAGE_VIOLATION, "Guard Page Violation" },
|
||||
{ STATUS_DATATYPE_MISALIGNMENT, "Data Type Misalignment" },
|
||||
{ STATUS_ACCESS_VIOLATION, "Access Violation" },
|
||||
{ STATUS_IN_PAGE_ERROR, "In Page Error" },
|
||||
{ STATUS_NO_MEMORY, "No Memory" },
|
||||
{ STATUS_ILLEGAL_INSTRUCTION, "Illegal Instruction" },
|
||||
{ STATUS_NONCONTINUABLE_EXCEPTION, "Noncontinuable Exception" },
|
||||
{ STATUS_INVALID_DISPOSITION, "Invalid Disposition" },
|
||||
{ STATUS_ARRAY_BOUNDS_EXCEEDED, "Array Bounds Exceeded" },
|
||||
{ STATUS_FLOAT_DENORMAL_OPERAND, "Float Denormal Operand" },
|
||||
{ STATUS_FLOAT_DIVIDE_BY_ZERO, "Divide by Zero" },
|
||||
{ STATUS_FLOAT_INEXACT_RESULT, "Float Inexact Result" },
|
||||
{ STATUS_FLOAT_INVALID_OPERATION, "Float Invalid Operation" },
|
||||
{ STATUS_FLOAT_OVERFLOW, "Float Overflow" },
|
||||
{ STATUS_FLOAT_STACK_CHECK, "Float Stack Check" },
|
||||
{ STATUS_FLOAT_UNDERFLOW, "Float Underflow" },
|
||||
{ STATUS_INTEGER_DIVIDE_BY_ZERO, "Integer Divide by Zero" },
|
||||
{ STATUS_INTEGER_OVERFLOW, "Integer Overflow" },
|
||||
{ STATUS_PRIVILEGED_INSTRUCTION, "Privileged Instruction" },
|
||||
{ STATUS_STACK_OVERFLOW, "Stack Overflow" },
|
||||
{ STATUS_CONTROL_C_EXIT, "Ctrl+C Exit" },
|
||||
{ 0xFFFFFFFF, "" }
|
||||
};
|
||||
|
||||
char *szName = NULL;
|
||||
for (int i = 0; gMsgTable[i].dwExceptionCode != 0xFFFFFFFF; i++)
|
||||
{
|
||||
|
|
|
@ -39,9 +39,14 @@
|
|||
|
||||
USING_NS_BF;
|
||||
|
||||
static void Crash_Error(const char* msg);
|
||||
|
||||
typedef void(*BfpCrashErrorFunc)(const char* str);
|
||||
|
||||
static bool gTimerInitialized = false;
|
||||
static int gTimerDivisor = 0;
|
||||
CritSect gBfpCritSect;
|
||||
BfpCrashErrorFunc gCrashErrorFunc = Crash_Error;
|
||||
|
||||
struct WindowsSharedInfo
|
||||
{
|
||||
|
@ -415,8 +420,9 @@ void Beefy::BFFatalError(const StringImpl& message, const StringImpl& file, int
|
|||
gBFApp->mSysDialogCnt++;
|
||||
#endif
|
||||
|
||||
String failMsg = StrFormat("%s in %s:%d", message.c_str(), file.c_str(), line);
|
||||
BfpSystem_FatalError(failMsg.c_str(), "FATAL ERROR");
|
||||
char* failMsg = new char[message.length() + file.length() + 64];
|
||||
sprintf(failMsg, "%s in %s:%d", message.c_str(), file.c_str(), line);
|
||||
BfpSystem_FatalError(failMsg, "FATAL ERROR");
|
||||
|
||||
#ifndef BF_NO_BFAPP
|
||||
if (gBFApp != NULL)
|
||||
|
@ -906,6 +912,7 @@ static void __cdecl AbortHandler(int)
|
|||
static int64 gCPUFreq = -1;
|
||||
static int64 gStartCPUTick = -1;
|
||||
static int64 gStartQPF = -1;
|
||||
static void(*sOldSIGABRTHandler)(int signal) = nullptr;
|
||||
|
||||
static void InitCPUFreq()
|
||||
{
|
||||
|
@ -918,10 +925,31 @@ static void InitCPUFreq()
|
|||
}
|
||||
}
|
||||
|
||||
static void(*sOldSIGABRTHandler)(int signal) = nullptr;
|
||||
static void Crash_Error(const char* msg)
|
||||
{
|
||||
HMODULE hMod = GetModuleHandleA(NULL);
|
||||
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
|
||||
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((uint8*)hMod + pDosHdr->e_lfanew);
|
||||
bool isCLI = pNtHdr->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||
|
||||
if (isCLI)
|
||||
fprintf(stderr, "**** FATAL APPLICATION ERROR ****\n%s\n", msg);
|
||||
else
|
||||
::MessageBoxA(NULL, msg, "FATAL ERROR", MB_ICONSTOP);
|
||||
_set_purecall_handler(nullptr);
|
||||
_set_invalid_parameter_handler(nullptr);
|
||||
signal(SIGABRT, sOldSIGABRTHandler);
|
||||
abort();
|
||||
}
|
||||
|
||||
static void Crash_Error_CrashHandler(const char* msg)
|
||||
{
|
||||
CrashCatcher::Get()->Crash(msg);
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flags)
|
||||
{
|
||||
gCrashErrorFunc = Crash_Error;
|
||||
InitCPUFreq();
|
||||
|
||||
::_set_error_mode(_OUT_TO_STDERR);
|
||||
|
@ -935,7 +963,9 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flag
|
|||
|
||||
if (version != BFP_VERSION)
|
||||
{
|
||||
BfpSystem_FatalError(StrFormat("Bfp build version '%d' does not match requested version '%d'", BFP_VERSION, version).c_str(), "BFP FATAL ERROR");
|
||||
char msg[1024];
|
||||
sprintf(msg, "Bfp build version '%d' does not match requested version '%d'", BFP_VERSION, version);
|
||||
BfpSystem_FatalError(msg, "BFP FATAL ERROR");
|
||||
}
|
||||
|
||||
if ((flags & BfpSystemInitFlag_InstallCrashCatcher) != 0)
|
||||
|
@ -953,11 +983,15 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flag
|
|||
sOldSIGABRTHandler = signal(SIGABRT, &AbortHandler);
|
||||
if (sOldSIGABRTHandler == SIG_ERR)
|
||||
sOldSIGABRTHandler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_InitCrashCatcher(BfpSystemInitFlags flags)
|
||||
{
|
||||
CrashCatcher::Get()->Init();
|
||||
if ((flags & BfpSystemInitFlag_SilentCrash) != 0)
|
||||
CrashCatcher::Get()->SetCrashReportKind(BfpCrashReportKind_None);
|
||||
}
|
||||
gCrashErrorFunc = Crash_Error_CrashHandler;
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCommandLine(int argc, char** argv)
|
||||
|
@ -993,7 +1027,10 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_Shutdown()
|
|||
delete gManagerTail;
|
||||
gManagerTail = next;
|
||||
}
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_ShutdownCrashCatcher()
|
||||
{
|
||||
if (CrashCatcher::Shutdown())
|
||||
{
|
||||
_set_purecall_handler(nullptr);
|
||||
|
@ -1092,9 +1129,17 @@ BFP_EXPORT uint64 BFP_CALLTYPE BfpSystem_InterlockedCompareExchange64(uint64* pt
|
|||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_FatalError(const char* error, const char* title)
|
||||
{
|
||||
if (title != NULL)
|
||||
CrashCatcher::Get()->Crash(String(title) + "\n" + String(error));
|
||||
{
|
||||
int errorLen = (int)strlen(error);
|
||||
int titleLen = (int)strlen(title);
|
||||
char* str = new char[errorLen + 1 + titleLen + 1];
|
||||
strcpy(str, title);
|
||||
strcat(str, "\n");
|
||||
strcat(str, error);
|
||||
gCrashErrorFunc(str);
|
||||
}
|
||||
else
|
||||
CrashCatcher::Get()->Crash(error);
|
||||
gCrashErrorFunc(error);
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_GetCommandLine(char* outStr, int* inOutStrSize, BfpSystemResult* outResult)
|
||||
|
@ -2245,9 +2290,12 @@ static LOCATEXSTATEFEATURE pfnLocateXStateFeature = NULL;
|
|||
typedef BOOL(WINAPI* SETXSTATEFEATURESMASK)(PCONTEXT Context, DWORD64 FeatureMask);
|
||||
static SETXSTATEFEATURESMASK pfnSetXStateFeaturesMask = NULL;
|
||||
|
||||
static uint8 ContextBuffer[4096];
|
||||
static uint8* ContextBuffer;
|
||||
static CONTEXT* CaptureRegistersEx(HANDLE hThread, intptr*& curPtr)
|
||||
{
|
||||
if (ContextBuffer == NULL)
|
||||
ContextBuffer = new uint8[4096];
|
||||
|
||||
PCONTEXT Context;
|
||||
DWORD ContextSize;
|
||||
DWORD64 FeatureMask;
|
||||
|
|
|
@ -1217,6 +1217,41 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class StringSimple : public StringView
|
||||
{
|
||||
public:
|
||||
StringSimple()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
StringSimple(const StringView& sv)
|
||||
{
|
||||
this->mPtr = new char[sv.mLength + 1];
|
||||
this->mLength = sv.mLength;
|
||||
memcpy((char*)this->mPtr, sv.mPtr, this->mLength);
|
||||
((char*)this->mPtr)[this->mLength] = 0;
|
||||
}
|
||||
|
||||
StringSimple(const StringImpl& str)
|
||||
{
|
||||
this->mPtr = new char[str.mLength + 1];
|
||||
this->mLength = str.mLength;
|
||||
memcpy((char*)this->mPtr, str.GetPtr(), this->mLength);
|
||||
((char*)mPtr)[this->mLength] = 0;
|
||||
}
|
||||
|
||||
~StringSimple()
|
||||
{
|
||||
delete this->mPtr;
|
||||
}
|
||||
|
||||
const char* c_str()
|
||||
{
|
||||
return this->mPtr;
|
||||
}
|
||||
};
|
||||
|
||||
class UTF16String : public Array<uint16>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -24,7 +24,7 @@ OtherLinkFlags = ""
|
|||
TargetDirectory = "$(WorkspaceDir)/dist"
|
||||
TargetName = "BeefIDE_d"
|
||||
OtherLinkFlags = "$(LinkFlags) Comdlg32.lib kernel32.lib user32.lib advapi32.lib shell32.lib IDEHelper64_d.lib"
|
||||
DebugCommandArguments = "-proddir=\"$(WorkspaceDir)\\..\\IDE\""
|
||||
DebugCommandArguments = "-proddir=\"$(WorkspaceDir)\\..\\BeefBuild\""
|
||||
DebugWorkingDirectory = "$(WorkspaceDir)\\.."
|
||||
EnvironmentVars = ["_NO_DEBUG_HEAP=1"]
|
||||
|
||||
|
|
8
IDE/Tests/Tiny/BeefProj.toml
Normal file
8
IDE/Tests/Tiny/BeefProj.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
FileVersion = 1
|
||||
|
||||
[Project]
|
||||
Name = "Tiny"
|
||||
StartupObject = "Tiny.Program"
|
||||
|
||||
[Configs.Release.Win64]
|
||||
CLibType = "SystemMSVCRT"
|
26
IDE/Tests/Tiny/BeefSpace.toml
Normal file
26
IDE/Tests/Tiny/BeefSpace.toml
Normal file
|
@ -0,0 +1,26 @@
|
|||
FileVersion = 1
|
||||
Projects = {Tiny = {Path = "."}}
|
||||
Unlocked = ["corlib"]
|
||||
|
||||
[Workspace]
|
||||
StartupProject = "Tiny"
|
||||
|
||||
[Configs.Debug.Win64]
|
||||
AllocType = "CRT"
|
||||
RuntimeKind = "Reduced"
|
||||
ReflectKind = "Minimal"
|
||||
RuntimeChecks = false
|
||||
EmitDynamicCastCheck = false
|
||||
EnableObjectDebugFlags = false
|
||||
EmitObjectAccessCheck = false
|
||||
EnableRealtimeLeakCheck = false
|
||||
AllowHotSwapping = false
|
||||
IntermediateType = "ObjectAndIRCode"
|
||||
|
||||
[Configs.Debug.Win32]
|
||||
RuntimeKind = "Reduced"
|
||||
ReflectKind = "Minimal"
|
||||
|
||||
[Configs.Release.Win64]
|
||||
RuntimeKind = "Reduced"
|
||||
ReflectKind = "Minimal"
|
13
IDE/Tests/Tiny/src/Program.bf
Normal file
13
IDE/Tests/Tiny/src/Program.bf
Normal file
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Tiny;
|
||||
|
||||
class Program
|
||||
{
|
||||
public static int Main()
|
||||
{
|
||||
Console.WriteLine("Hello, World!");
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -420,6 +420,12 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(.MemberAccess)]
|
||||
public struct NoStaticCtorAttribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// The [Checked] attribute is used to mark a method or a method invocation as being "checked", meaning
|
||||
/// that the method applies extra runtime checks such as bounds checking or other parameter or state validation.
|
||||
[AttributeUsage(.Invocation | .Method | .Property)]
|
||||
|
|
|
@ -92,8 +92,15 @@ namespace System
|
|||
[CallingConvention(.Cdecl)]
|
||||
public static extern void Dbg_RawFree(void* ptr);
|
||||
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern void Shutdown_Internal();
|
||||
|
||||
[CallingConvention(.Cdecl), AlwaysInclude]
|
||||
static extern void Shutdown();
|
||||
static void Shutdown()
|
||||
{
|
||||
Shutdown_Internal();
|
||||
}
|
||||
|
||||
[CallingConvention(.Cdecl)]
|
||||
static extern void Test_Init(char8* testData);
|
||||
[CallingConvention(.Cdecl)]
|
||||
|
|
|
@ -62,46 +62,105 @@ namespace System
|
|||
#endif
|
||||
}
|
||||
|
||||
int IHashable.GetHashCode()
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
[NoShow]
|
||||
int32 GetFlags()
|
||||
{
|
||||
return (int)(void*)this;
|
||||
return (int32)mClassVData & 0xFF;
|
||||
}
|
||||
|
||||
[DisableObjectAccessChecks, NoShow]
|
||||
public bool IsDeleted()
|
||||
{
|
||||
return (int32)mClassVData & 0x80 != 0;
|
||||
}
|
||||
#else
|
||||
[SkipCall]
|
||||
public bool IsDeleted()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
extern Type Comptime_GetType();
|
||||
|
||||
public Type GetType()
|
||||
{
|
||||
Type type;
|
||||
if (Compiler.IsComptime)
|
||||
return Comptime_GetType();
|
||||
|
||||
ClassVData* classVData;
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
type = maskedVData.mType;
|
||||
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
#else
|
||||
type = mClassVData.mType;
|
||||
classVData = mClassVData;
|
||||
#endif
|
||||
|
||||
#if BF_32_BIT
|
||||
Type type = Type.[Friend]GetType_((.)(classVData.mType2));
|
||||
#else
|
||||
Type type = Type.[Friend]GetType_((.)(classVData.mType >> 32));
|
||||
#endif
|
||||
if ((type.[Friend]mTypeFlags & TypeFlags.Boxed) != 0)
|
||||
{
|
||||
//int32 underlyingType = (int32)((TypeInstance)type).mUnderlyingType;
|
||||
type = Type.[Friend]GetType(((TypeInstance)type).[Friend]mUnderlyingType);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
TypeId GetTypeId()
|
||||
{
|
||||
ClassVData* classVData;
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
#else
|
||||
classVData = mClassVData;
|
||||
#endif
|
||||
|
||||
#if BF_32_BIT
|
||||
return (.)classVData.mType2;
|
||||
#else
|
||||
return (.)(classVData.mType >> 32);
|
||||
#endif
|
||||
}
|
||||
|
||||
[NoShow]
|
||||
Type RawGetType()
|
||||
{
|
||||
Type type;
|
||||
if (Compiler.IsComptime)
|
||||
return Comptime_GetType();
|
||||
|
||||
ClassVData* classVData;
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
type = maskedVData.mType;
|
||||
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
#else
|
||||
type = mClassVData.mType;
|
||||
classVData = mClassVData;
|
||||
#endif
|
||||
|
||||
#if BF_32_BIT
|
||||
Type type = Type.[Friend]GetType_((.)(classVData.mType));
|
||||
#else
|
||||
Type type = Type.[Friend]GetType_((.)(classVData.mType & 0xFFFFFFFF));
|
||||
#endif
|
||||
return type;
|
||||
}
|
||||
|
||||
TypeId RawGetTypeId()
|
||||
{
|
||||
ClassVData* classVData;
|
||||
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
|
||||
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
|
||||
#else
|
||||
classVData = mClassVData;
|
||||
#endif
|
||||
|
||||
#if BF_32_BIT
|
||||
return (.)classVData.mType;
|
||||
#else
|
||||
return (.)(classVData.mType & 0xFFFFFFFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BF_DYNAMIC_CAST_CHECK || BF_ENABLE_REALTIME_LEAK_CHECK
|
||||
[NoShow]
|
||||
public virtual Object DynamicCastToTypeId(int32 typeId)
|
||||
{
|
||||
if (typeId == (int32)RawGetType().[Friend]mTypeId)
|
||||
if (typeId == (.)RawGetTypeId())
|
||||
return this;
|
||||
return null;
|
||||
}
|
||||
|
@ -113,10 +172,15 @@ namespace System
|
|||
}
|
||||
#endif
|
||||
|
||||
int IHashable.GetHashCode()
|
||||
{
|
||||
return (int)Internal.UnsafeCastToPtr(this);
|
||||
}
|
||||
|
||||
public virtual void ToString(String strBuffer)
|
||||
{
|
||||
//strBuffer.Set(stack string(GetType().mName));
|
||||
RawGetType().GetName(strBuffer);
|
||||
strBuffer.Append("Type#");
|
||||
GetTypeId().ToString(strBuffer);
|
||||
}
|
||||
|
||||
/*public virtual int GetHashCode()
|
||||
|
|
|
@ -7,7 +7,10 @@ namespace System
|
|||
{
|
||||
struct ClassVData
|
||||
{
|
||||
public Type mType;
|
||||
public int mType;
|
||||
#if BF_32_BIT
|
||||
public int mType2;
|
||||
#endif
|
||||
// The rest of this structured is generated by the compiler,
|
||||
// including the vtable and interface slots
|
||||
}
|
||||
|
@ -757,6 +760,7 @@ namespace System.Reflection
|
|||
public int32 mCustomAttributesIdx;
|
||||
}
|
||||
|
||||
[CRepr, AlwaysInclude]
|
||||
public struct InterfaceData
|
||||
{
|
||||
public TypeId mInterfaceType;
|
||||
|
|
|
@ -46,8 +46,8 @@ namespace Hey.Dude.Bro
|
|||
|
||||
|
||||
|
||||
[Import(@"C:\Beef\BeefTools\TestDLL\x64\Debug\TestDLL.dll"), LinkName("Test2")]
|
||||
public static extern void Test2(int32 a, int32 b, int32 c, int32 d, function Color(int32 a, int32 b) func);
|
||||
//[Import(@"C:\Beef\BeefTools\TestDLL\x64\Debug\TestDLL.dll"), LinkName("Test2")]
|
||||
//public static extern void Test2(int32 a, int32 b, int32 c, int32 d, function Color(int32 a, int32 b) func);
|
||||
|
||||
public static Color GetColor(int32 a, int32 b)
|
||||
{
|
||||
|
@ -61,7 +61,9 @@ namespace Hey.Dude.Bro
|
|||
|
||||
public static int Main(String[] args)
|
||||
{
|
||||
Test2(1, 2, 3, 4, => GetColor);
|
||||
Debug.WriteLine("Hey!");
|
||||
|
||||
//Test2(1, 2, 3, 4, => GetColor);
|
||||
|
||||
//Blurg.Hey();
|
||||
return 1;
|
||||
|
|
|
@ -764,6 +764,9 @@ namespace IDE
|
|||
|
||||
public static void GetRtLibNames(Workspace.PlatformType platformType, Workspace.Options workspaceOptions, Project.Options options, bool dynName, String outRt, String outDbg, String outAlloc)
|
||||
{
|
||||
if (workspaceOptions.mRuntimeKind == .Disabled)
|
||||
return;
|
||||
|
||||
if ((platformType == .Linux) || (platformType == .macOS) || (platformType == .iOS))
|
||||
{
|
||||
if (options.mBuildOptions.mBeefLibType == .DynamicDebug)
|
||||
|
@ -1059,10 +1062,13 @@ namespace IDE
|
|||
return false;
|
||||
}*/
|
||||
|
||||
switch (options.mBuildOptions.mCLibType)
|
||||
var clibType = options.mBuildOptions.mCLibType;
|
||||
if (workspaceOptions.mRuntimeKind == .Disabled)
|
||||
clibType = .None;
|
||||
switch (clibType)
|
||||
{
|
||||
case .None:
|
||||
linkLine.Append("-nodefaultlib ");
|
||||
linkLine.Append("-nodefaultlib chkstk.obj ");
|
||||
case .Dynamic:
|
||||
//linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:msvcprt " : "-defaultlib:msvcrt ");
|
||||
linkLine.Append("-defaultlib:msvcrt ");
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace IDE
|
|||
{
|
||||
class BuildOptions
|
||||
{
|
||||
[Reflect(.All)]
|
||||
public enum LTOType
|
||||
{
|
||||
case None;
|
||||
|
@ -18,6 +19,7 @@ namespace IDE
|
|||
}
|
||||
}
|
||||
|
||||
[Reflect(.All)]
|
||||
public enum EmitDebugInfo
|
||||
{
|
||||
No,
|
||||
|
@ -25,6 +27,7 @@ namespace IDE
|
|||
LinesOnly,
|
||||
}
|
||||
|
||||
[Reflect(.All)]
|
||||
public enum SIMDSetting
|
||||
{
|
||||
None,
|
||||
|
@ -38,6 +41,7 @@ namespace IDE
|
|||
AVX2,
|
||||
}
|
||||
|
||||
[Reflect]
|
||||
public enum BfOptimizationLevel
|
||||
{
|
||||
case O0;
|
||||
|
@ -53,6 +57,7 @@ namespace IDE
|
|||
}
|
||||
}
|
||||
|
||||
[Reflect]
|
||||
public enum RelocType
|
||||
{
|
||||
NotSet,
|
||||
|
@ -64,6 +69,7 @@ namespace IDE
|
|||
ROPI_RWPI
|
||||
}
|
||||
|
||||
[Reflect]
|
||||
public enum PICLevel
|
||||
{
|
||||
NotSet,
|
||||
|
@ -72,6 +78,7 @@ namespace IDE
|
|||
Big
|
||||
}
|
||||
|
||||
[Reflect]
|
||||
public enum AlwaysIncludeKind
|
||||
{
|
||||
NotSet,
|
||||
|
|
|
@ -739,9 +739,14 @@ namespace IDE.Compiler
|
|||
SetOpt(options.mAllowHotSwapping, .EnableHotSwapping);
|
||||
#endif
|
||||
|
||||
var allocType = options.mAllocType;
|
||||
|
||||
if ((options.mRuntimeKind == .Disabled) && (allocType == .Debug))
|
||||
allocType = .CRT;
|
||||
|
||||
String mallocLinkName;
|
||||
String freeLinkName;
|
||||
switch (options.mAllocType)
|
||||
switch (allocType)
|
||||
{
|
||||
case .CRT:
|
||||
mallocLinkName = "malloc";
|
||||
|
|
|
@ -366,6 +366,9 @@ namespace IDE.Debugger
|
|||
[CallingConvention(.Stdcall),CLink]
|
||||
static extern char8* Debugger_GetModulesInfo();
|
||||
|
||||
[CallingConvention(.Stdcall),CLink]
|
||||
static extern char8* Debugger_GetModuleInfo(char8* moduleName);
|
||||
|
||||
[CallingConvention(.Stdcall),CLink]
|
||||
static extern bool Debugger_HasPendingDebugLoads();
|
||||
|
||||
|
@ -1194,6 +1197,11 @@ namespace IDE.Debugger
|
|||
modulesInfo.Append(Debugger_GetModulesInfo());
|
||||
}
|
||||
|
||||
public void GetModuleInfo(StringView moduleName, String moduleInfo)
|
||||
{
|
||||
moduleInfo.Append(Debugger_GetModuleInfo(moduleName.ToScopeCStr!()));
|
||||
}
|
||||
|
||||
public int32 LoadDebugInfoForModule(String moduleName)
|
||||
{
|
||||
return Debugger_LoadDebugInfoForModule(moduleName);
|
||||
|
|
|
@ -8488,6 +8488,13 @@ namespace IDE
|
|||
macroList.Add("BF_LARGE_COLLECTIONS");
|
||||
}
|
||||
|
||||
if (workspaceOptions.mRuntimeKind == .Disabled)
|
||||
macroList.Add("BF_RUNTIME_DISABLE");
|
||||
if ((workspaceOptions.mRuntimeKind == .Reduced) || (workspaceOptions.mRuntimeKind == .Disabled))
|
||||
macroList.Add("BF_RUNTIME_REDUCED");
|
||||
if (workspaceOptions.mReflectKind == .Minimal)
|
||||
macroList.Add("BF_REFLECT_MINIMAL");
|
||||
|
||||
// Only supported on Windows at the moment
|
||||
bool hasLeakCheck = false;
|
||||
if (workspaceOptions.LeakCheckingEnabled)
|
||||
|
|
|
@ -94,6 +94,12 @@ namespace IDE
|
|||
BitcodeAndIRCode,
|
||||
}
|
||||
|
||||
public enum ReflectKind
|
||||
{
|
||||
Normal,
|
||||
Minimal
|
||||
}
|
||||
|
||||
public enum PlatformType
|
||||
{
|
||||
case Unknown;
|
||||
|
@ -263,6 +269,13 @@ namespace IDE
|
|||
Custom
|
||||
}
|
||||
|
||||
public enum RuntimeKind
|
||||
{
|
||||
Default,
|
||||
Reduced,
|
||||
Disabled
|
||||
}
|
||||
|
||||
public class BeefGlobalOptions
|
||||
{
|
||||
[Reflect]
|
||||
|
@ -305,6 +318,10 @@ namespace IDE
|
|||
[Reflect]
|
||||
public bool mLargeCollections;
|
||||
[Reflect]
|
||||
public RuntimeKind mRuntimeKind;
|
||||
[Reflect]
|
||||
public ReflectKind mReflectKind;
|
||||
[Reflect]
|
||||
public AllocType mAllocType = .CRT;
|
||||
[Reflect]
|
||||
public String mAllocMalloc = new String() ~ delete _;
|
||||
|
@ -352,7 +369,7 @@ namespace IDE
|
|||
get
|
||||
{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
return mEnableRealtimeLeakCheck && mEnableObjectDebugFlags && (mAllocType == .Debug);
|
||||
return mEnableRealtimeLeakCheck && mEnableObjectDebugFlags && (mAllocType == .Debug) && (mRuntimeKind != .Disabled);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
@ -376,6 +393,8 @@ namespace IDE
|
|||
mNoOmitFramePointers = prev.mNoOmitFramePointers;
|
||||
mLargeStrings = prev.mLargeStrings;
|
||||
mLargeCollections = prev.mLargeCollections;
|
||||
mRuntimeKind = prev.mRuntimeKind;
|
||||
mReflectKind = prev.mReflectKind;
|
||||
mAllocType = prev.mAllocType;
|
||||
mAllocMalloc.Set(prev.mAllocMalloc);
|
||||
mAllocFree.Set(prev.mAllocFree);
|
||||
|
@ -813,6 +832,8 @@ namespace IDE
|
|||
data.ConditionalAdd("NoOmitFramePointers", options.mNoOmitFramePointers, false);
|
||||
data.ConditionalAdd("LargeStrings", options.mLargeStrings, false);
|
||||
data.ConditionalAdd("LargeCollections", options.mLargeCollections, false);
|
||||
data.ConditionalAdd("RuntimeKind", options.mRuntimeKind);
|
||||
data.ConditionalAdd("ReflectKind", options.mReflectKind);
|
||||
data.ConditionalAdd("InitLocalVariables", options.mInitLocalVariables, false);
|
||||
data.ConditionalAdd("RuntimeChecks", options.mRuntimeChecks, !isRelease);
|
||||
data.ConditionalAdd("EmitDynamicCastCheck", options.mEmitDynamicCastCheck, !isRelease);
|
||||
|
@ -1004,6 +1025,8 @@ namespace IDE
|
|||
options.mNoOmitFramePointers = false;
|
||||
options.mLargeStrings = false;
|
||||
options.mLargeCollections = false;
|
||||
options.mRuntimeKind = .Default;
|
||||
options.mReflectKind = .Normal;
|
||||
options.mInitLocalVariables = false;
|
||||
options.mRuntimeChecks = !isRelease;
|
||||
options.mEmitDynamicCastCheck = !isRelease;
|
||||
|
@ -1113,6 +1136,8 @@ namespace IDE
|
|||
options.mNoOmitFramePointers = data.GetBool("NoOmitFramePointers", false);
|
||||
options.mLargeStrings = data.GetBool("LargeStrings", false);
|
||||
options.mLargeCollections = data.GetBool("LargeCollections", false);
|
||||
options.mRuntimeKind = data.GetEnum<RuntimeKind>("RuntimeKind");
|
||||
options.mReflectKind = data.GetEnum<ReflectKind>("ReflectKind");
|
||||
options.mInitLocalVariables = data.GetBool("InitLocalVariables", false);
|
||||
options.mRuntimeChecks = data.GetBool("RuntimeChecks", !isRelease);
|
||||
options.mEmitDynamicCastCheck = data.GetBool("EmitDynamicCastCheck", !isRelease);
|
||||
|
|
|
@ -158,6 +158,20 @@ namespace IDE.ui
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
anItem = menu.AddItem("Copy Info to Clipboard");
|
||||
anItem.mOnMenuItemSelected.Add(new (item) =>
|
||||
{
|
||||
String moduleInfo = scope .();
|
||||
listView.GetRoot().WithSelectedItems(scope (item) =>
|
||||
{
|
||||
if (!moduleInfo.IsEmpty)
|
||||
moduleInfo.Append("\n");
|
||||
gApp.mDebugger.GetModuleInfo(item.GetSubItem(1).Label, moduleInfo);
|
||||
});
|
||||
gApp.SetClipboardText(moduleInfo);
|
||||
});
|
||||
|
||||
MenuWidget menuWidget = ThemeFactory.mDefault.CreateMenuWidget(menu);
|
||||
menuWidget.Init(relWidget, x, y);
|
||||
}
|
||||
|
|
|
@ -797,6 +797,8 @@ namespace IDE.ui
|
|||
AddPropertiesItem(category, "No Omit Frame Pointers", "mNoOmitFramePointers");
|
||||
AddPropertiesItem(category, "Large Strings", "mLargeStrings");
|
||||
AddPropertiesItem(category, "Large Collections", "mLargeCollections");
|
||||
AddPropertiesItem(category, "Runtime", "mRuntimeKind");
|
||||
AddPropertiesItem(category, "Reflection", "mReflectKind");
|
||||
category.Open(true, true);
|
||||
|
||||
(category, propEntry) = AddPropertiesItem(root, "Debug");
|
||||
|
|
|
@ -509,7 +509,7 @@ addr_target COFF::GetSectionAddr(uint16 section, uint32 offset)
|
|||
return hiBase + offset;
|
||||
}
|
||||
|
||||
int rva = mSectionRVAs[section - 1];
|
||||
int rva = mSectionHeaders[section - 1].mVirtualAddress;
|
||||
if (rva == 0)
|
||||
return ADDR_FLAG_ABS + offset;
|
||||
|
||||
|
@ -5178,6 +5178,7 @@ bool COFF::CvParseDBI(int wantAge)
|
|||
contribEntry->mLength = curSize;
|
||||
contribEntry->mDbgModule = this;
|
||||
contribEntry->mCompileUnitId = contrib.mModule;
|
||||
contribEntry->mSection = contrib.mSection;
|
||||
mDebugTarget->mContribMap.Insert(contribEntry);
|
||||
}
|
||||
}
|
||||
|
@ -5288,7 +5289,7 @@ bool COFF::CvParseDBI(int wantAge)
|
|||
|
||||
void COFF::ParseSectionHeader(int sectionIdx)
|
||||
{
|
||||
bool fakeRVAS = mSectionRVAs.empty();
|
||||
bool fakeRVAS = mSectionHeaders.empty();
|
||||
|
||||
int sectionSize = 0;
|
||||
uint8* sectionData = CvReadStream(sectionIdx, §ionSize);
|
||||
|
@ -5300,12 +5301,15 @@ void COFF::ParseSectionHeader(int sectionIdx)
|
|||
auto& sectionHeader = GET(PESectionHeader);
|
||||
if (fakeRVAS)
|
||||
{
|
||||
mSectionRVAs.push_back(sectionHeader.mVirtualAddress);
|
||||
mSectionHeaders.push_back(sectionHeader);
|
||||
}
|
||||
}
|
||||
|
||||
if (fakeRVAS)
|
||||
mSectionRVAs.push_back(0);
|
||||
{
|
||||
PESectionHeader sectionHeader = { 0 };
|
||||
mSectionHeaders.push_back(sectionHeader);
|
||||
}
|
||||
|
||||
delete sectionData;
|
||||
}
|
||||
|
|
|
@ -1220,7 +1220,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
|
|||
|
||||
Array<BfType*> vdataTypeList;
|
||||
HashSet<BfModule*> usedModuleSet;
|
||||
HashSet<BfType*> reflectTypeSet;
|
||||
HashSet<BfType*> reflectSkipTypeSet;
|
||||
HashSet<BfType*> reflectFieldTypeSet;
|
||||
|
||||
vdataHashCtx.MixinStr(project->mStartupObject);
|
||||
|
@ -1398,20 +1398,49 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
|
|||
bool madeBfTypeData = false;
|
||||
|
||||
auto typeDefType = mContext->mBfTypeType;
|
||||
bool needsTypeList = bfModule->IsMethodImplementedAndReified(typeDefType, "GetType");
|
||||
bool needsFullTypeList = bfModule->IsMethodImplementedAndReified(typeDefType, "GetType");
|
||||
bool needsTypeList = needsFullTypeList || bfModule->IsMethodImplementedAndReified(typeDefType, "GetType_");
|
||||
bool needsObjectTypeData = needsTypeList || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "RawGetType") || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "GetType");
|
||||
bool needsTypeNames = bfModule->IsMethodImplementedAndReified(typeDefType, "GetName") || bfModule->IsMethodImplementedAndReified(typeDefType, "GetFullName");
|
||||
bool needsStringLiteralList = (mOptions.mAllowHotSwapping) || (bfModule->IsMethodImplementedAndReified(stringType, "Intern")) || (bfModule->IsMethodImplementedAndReified(stringViewType, "Intern"));
|
||||
|
||||
Dictionary<int, int> usedStringIdMap;
|
||||
BfCreateTypeDataContext createTypeDataCtx;
|
||||
|
||||
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectTypeInstanceTypeDef));
|
||||
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSpecializedGenericType));
|
||||
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectUnspecializedGenericType));
|
||||
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectArrayType));
|
||||
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectGenericParamType));
|
||||
if (!needsTypeList)
|
||||
{
|
||||
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mTypeTypeDef));
|
||||
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectTypeInstanceTypeDef));
|
||||
}
|
||||
|
||||
if (!needsFullTypeList)
|
||||
{
|
||||
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSpecializedGenericType));
|
||||
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectUnspecializedGenericType));
|
||||
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectConstExprType));
|
||||
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectArrayType));
|
||||
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectGenericParamType));
|
||||
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectPointerType));
|
||||
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSizedArrayType));
|
||||
reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectRefType));
|
||||
}
|
||||
|
||||
HashSet<BfType*> boxeeSet;
|
||||
for (auto type : vdataTypeList)
|
||||
{
|
||||
auto typeInst = type->ToTypeInstance();
|
||||
|
||||
if ((!type->IsReified()) || (type->IsUnspecializedType()))
|
||||
continue;
|
||||
|
||||
if (type->IsBoxed())
|
||||
boxeeSet.Add(typeInst->GetUnderlyingType());
|
||||
}
|
||||
|
||||
int usedTypeCount = 0;
|
||||
HashSet<BfType*> vDataTypeSet;
|
||||
SmallVector<BfIRValue, 256> typeDataVector;
|
||||
Array<BfType*> usedTypeDataVector;
|
||||
|
||||
for (auto type : vdataTypeList)
|
||||
{
|
||||
if (type->IsTypeAlias())
|
||||
|
@ -1425,9 +1454,12 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
|
|||
if ((typeInst != NULL) && (!typeInst->IsReified()) && (!typeInst->IsUnspecializedType()))
|
||||
continue;
|
||||
|
||||
bool needsTypeData = (needsTypeList) || ((type->IsObject()) && (needsObjectTypeData));
|
||||
bool needsTypeData = (needsFullTypeList) || ((type->IsObject()) && (needsObjectTypeData));
|
||||
bool needsVData = (type->IsObject()) && (typeInst->HasBeenInstantiated());
|
||||
|
||||
if ((needsObjectTypeData) && (boxeeSet.Contains(typeInst)))
|
||||
needsTypeData = true;
|
||||
|
||||
bool forceReflectFields = false;
|
||||
|
||||
if (bfModule->mProject->mReferencedTypeData.Contains(type))
|
||||
|
@ -1437,8 +1469,16 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
|
|||
forceReflectFields = true;
|
||||
}
|
||||
|
||||
BfIRValue typeVariable;
|
||||
if (reflectSkipTypeSet.Contains(type))
|
||||
{
|
||||
if (!bfModule->mProject->mReferencedTypeData.Contains(type))
|
||||
{
|
||||
needsTypeData = false;
|
||||
needsVData = false;
|
||||
}
|
||||
}
|
||||
|
||||
BfIRValue typeVariable;
|
||||
if ((needsTypeData) || (needsVData))
|
||||
{
|
||||
if (reflectFieldTypeSet.Contains(type))
|
||||
|
@ -1446,14 +1486,25 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
|
|||
needsTypeData = true;
|
||||
forceReflectFields = true;
|
||||
}
|
||||
else if (reflectTypeSet.Contains(type))
|
||||
/*else if (reflectTypeSet.Contains(type))
|
||||
{
|
||||
needsTypeData = true;
|
||||
needsVData = true;
|
||||
}*/
|
||||
|
||||
if (needsVData)
|
||||
vDataTypeSet.Add(type);
|
||||
|
||||
typeVariable = bfModule->CreateTypeData(type, createTypeDataCtx, forceReflectFields, needsTypeData, needsTypeNames, needsVData);
|
||||
if (typeVariable)
|
||||
usedTypeDataVector.Add(type);
|
||||
}
|
||||
else if ((type->IsInterface()) && (typeInst->mSlotNum >= 0))
|
||||
{
|
||||
bfModule->CreateSlotOfs(typeInst);
|
||||
}
|
||||
|
||||
typeVariable = bfModule->CreateTypeData(type, usedStringIdMap, forceReflectFields, needsTypeData, needsTypeNames, needsVData);
|
||||
}
|
||||
usedTypeCount++;
|
||||
type->mDirty = false;
|
||||
|
||||
if (needsTypeList)
|
||||
|
@ -1573,13 +1624,13 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
|
|||
BfMangler::MangleStaticFieldName(stringsVariableName, GetMangleKind(), stringType->ToTypeInstance(), "sIdStringLiterals", stringPtrType);
|
||||
Array<BfIRValue> stringList;
|
||||
|
||||
stringList.Resize(usedStringIdMap.size());
|
||||
for (auto& kv : usedStringIdMap)
|
||||
stringList.Resize(createTypeDataCtx.mUsedStringIdMap.size());
|
||||
for (auto& kv : createTypeDataCtx.mUsedStringIdMap)
|
||||
{
|
||||
stringList[kv.mValue] = bfModule->mStringObjectPool[kv.mKey];
|
||||
}
|
||||
|
||||
BfIRType stringArrayType = bfModule->mBfIRBuilder->GetSizedArrayType(stringPtrIRType, (int)usedStringIdMap.size());
|
||||
BfIRType stringArrayType = bfModule->mBfIRBuilder->GetSizedArrayType(stringPtrIRType, (int)createTypeDataCtx.mUsedStringIdMap.size());
|
||||
auto stringArray = bfModule->mBfIRBuilder->CreateConstAgg_Value(stringArrayType, stringList);
|
||||
|
||||
auto stringArrayVar = bfModule->mBfIRBuilder->CreateGlobalVariable(stringArrayType, true, BfIRLinkageType_External, stringArray, stringsVariableName);
|
||||
|
@ -3994,10 +4045,10 @@ void BfCompiler::VisitSourceExteriorNodes()
|
|||
|
||||
if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(usingDirective->mTypeRef))
|
||||
{
|
||||
mContext->mScratchModule->ResolveTypeRefAllowUnboundGenerics(usingDirective->mTypeRef, BfPopulateType_Identity);
|
||||
mContext->mScratchModule->ResolveTypeRefAllowUnboundGenerics(usingDirective->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_NoReify);
|
||||
}
|
||||
else
|
||||
mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, BfPopulateType_Identity);
|
||||
mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_NoReify);
|
||||
|
||||
if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL))
|
||||
mResolvePassData->mAutoComplete->CheckTypeRef(usingDirective->mTypeRef, false, false);
|
||||
|
@ -5608,12 +5659,19 @@ void BfCompiler::ClearBuildCache()
|
|||
}
|
||||
}
|
||||
|
||||
int BfCompiler::GetVDataPrefixDataCount()
|
||||
{
|
||||
return (mSystem->mPtrSize == 4) ? 2 : 1;
|
||||
}
|
||||
|
||||
int BfCompiler::GetDynCastVDataCount()
|
||||
{
|
||||
int dynElements = 1 + mMaxInterfaceSlots;
|
||||
return ((dynElements * 4) + mSystem->mPtrSize - 1) / mSystem->mPtrSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool BfCompiler::IsAutocomplete()
|
||||
{
|
||||
return (mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL);
|
||||
|
@ -7177,6 +7235,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
mActionTypeDef = _GetRequiredType("System.Action");
|
||||
mEnumTypeDef = _GetRequiredType("System.Enum");
|
||||
mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute");
|
||||
mNoStaticCtorAttributeTypeDef = _GetRequiredType("System.NoStaticCtorAttribute");
|
||||
mComptimeAttributeTypeDef = _GetRequiredType("System.ComptimeAttribute");
|
||||
mConstEvalAttributeTypeDef = _GetRequiredType("System.ConstEvalAttribute");
|
||||
mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute");
|
||||
|
|
|
@ -442,6 +442,7 @@ public:
|
|||
BfTypeDef* mDisableChecksAttributeTypeDef;
|
||||
BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef;
|
||||
BfTypeDef* mFriendAttributeTypeDef;
|
||||
BfTypeDef* mNoStaticCtorAttributeTypeDef;
|
||||
BfTypeDef* mComptimeAttributeTypeDef;
|
||||
BfTypeDef* mConstEvalAttributeTypeDef;
|
||||
BfTypeDef* mNoExtensionAttributeTypeDef;
|
||||
|
@ -501,6 +502,7 @@ public:
|
|||
void MarkStringPool(BfIRConstHolder* constHolder, BfIRValue irValue);
|
||||
void ClearUnusedStringPoolEntries();
|
||||
void ClearBuildCache();
|
||||
int GetVDataPrefixDataCount();
|
||||
int GetDynCastVDataCount();
|
||||
bool IsAutocomplete();
|
||||
bool IsDataResolvePass();
|
||||
|
|
|
@ -420,11 +420,18 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
|
|||
didWork = true;
|
||||
}
|
||||
|
||||
for (int populatePass = 0; populatePass < 2; populatePass++)
|
||||
{
|
||||
for (int workIdx = 0; workIdx < (int)mPopulateTypeWorkList.size(); workIdx++)
|
||||
{
|
||||
//BP_ZONE("PWL_PopulateType");
|
||||
if (IsCancellingAndYield())
|
||||
break;
|
||||
if (!mMidCompileWorkList.IsEmpty())
|
||||
{
|
||||
// Let these mid-compiles occur as soon as possible
|
||||
break;
|
||||
}
|
||||
|
||||
auto workItemRef = mPopulateTypeWorkList[workIdx];
|
||||
if (workItemRef == NULL)
|
||||
|
@ -441,6 +448,11 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
|
|||
continue;
|
||||
}
|
||||
|
||||
// We want to resolve type aliases first, allowing possible mMidCompileWorkList entries
|
||||
int wantPass = type->IsTypeAlias() ? 0 : 1;
|
||||
if (populatePass != wantPass)
|
||||
continue;
|
||||
|
||||
auto typeInst = type->ToTypeInstance();
|
||||
if ((typeInst != NULL) && (resolveParser != NULL))
|
||||
{
|
||||
|
@ -470,6 +482,13 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
|
|||
mCompiler->UpdateCompletion();
|
||||
didWork = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!mMidCompileWorkList.IsEmpty()) && (didWork))
|
||||
{
|
||||
// Let the mid-compile occur ASAP
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int workIdx = 0; workIdx < (int)mTypeRefVerifyWorkList.size(); workIdx++)
|
||||
{
|
||||
|
@ -1984,6 +2003,7 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds)
|
|||
}
|
||||
else if (dependentTypeInst != NULL)
|
||||
{
|
||||
mGhostDependencies.Add(type);
|
||||
// This keeps us from crashing from accessing deleted types on subsequent compiles
|
||||
mFailTypes.TryAdd(dependentTypeInst, BfFailKind_Normal);
|
||||
}
|
||||
|
@ -2396,6 +2416,38 @@ void BfContext::UpdateRevisedTypes()
|
|||
}
|
||||
}
|
||||
|
||||
// Handle these "mid-compiles" now so we handle them as early-stage
|
||||
BfParser* resolveParser = NULL;
|
||||
if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mParsers.IsEmpty()))
|
||||
resolveParser = mCompiler->mResolvePassData->mParsers[0];
|
||||
for (int workIdx = 0; workIdx < (int)mMidCompileWorkList.size(); workIdx++)
|
||||
{
|
||||
auto workItemRef = mMidCompileWorkList[workIdx];
|
||||
if (workItemRef == NULL)
|
||||
{
|
||||
workIdx = mMidCompileWorkList.RemoveAt(workIdx);
|
||||
continue;
|
||||
}
|
||||
|
||||
BfType* type = workItemRef->mType;
|
||||
String reason = workItemRef->mReason;
|
||||
|
||||
auto typeInst = type->ToTypeInstance();
|
||||
if ((typeInst != NULL) && (resolveParser != NULL))
|
||||
{
|
||||
if (!typeInst->mTypeDef->GetLatest()->HasSource(resolveParser))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
workIdx = mMidCompileWorkList.RemoveAt(workIdx);
|
||||
|
||||
BfLogSysM("Handling prior-revision MidCompile on type %s in early-stage UpdateRevisedTypes\n", type);
|
||||
RebuildDependentTypes(type->ToDependedType());
|
||||
//RebuildDependentTypes_MidCompile(type->ToDependedType(), reason);
|
||||
}
|
||||
|
||||
for (auto typeInst : defEmitParentCheckQueue)
|
||||
{
|
||||
if (typeInst->IsDeleting())
|
||||
|
@ -2675,6 +2727,8 @@ void BfContext::UpdateRevisedTypes()
|
|||
RebuildType(type);
|
||||
}
|
||||
}
|
||||
|
||||
BfLogSysM("BfContext::UpdateRevisedTypes done.\n");
|
||||
}
|
||||
|
||||
void BfContext::VerifyTypeLookups(BfTypeInstance* typeInst)
|
||||
|
@ -3459,6 +3513,7 @@ void BfContext::Cleanup()
|
|||
}
|
||||
}
|
||||
mTypeGraveyard.Clear();
|
||||
mGhostDependencies.Clear();
|
||||
|
||||
if (!mDeletingModules.IsEmpty())
|
||||
{
|
||||
|
|
|
@ -382,6 +382,7 @@ public:
|
|||
BfModule* mScratchModule;
|
||||
BfModule* mUnreifiedModule;
|
||||
HashSet<String> mUsedModuleNames;
|
||||
HashSet<BfType*> mGhostDependencies; // We couldn't properly rebuild our dependencies
|
||||
Dictionary<BfProject*, BfModule*> mProjectModule;
|
||||
Array<BfModule*> mModules;
|
||||
Array<BfModule*> mDeletingModules;
|
||||
|
|
|
@ -5205,8 +5205,13 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe
|
|||
return BfTypedValue(retVal, resolvedFieldType);
|
||||
}
|
||||
else if (fieldDef->mIsStatic)
|
||||
{
|
||||
if ((mModule->mAttributeState == NULL) || (mModule->mAttributeState->mCustomAttributes == NULL) ||
|
||||
(!mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoStaticCtorAttributeTypeDef)))
|
||||
{
|
||||
mModule->CheckStaticAccess(typeInstance);
|
||||
}
|
||||
|
||||
auto retVal = mModule->ReferenceStaticField(fieldInstance);
|
||||
bool isStaticCtor = (mModule->mCurMethodInstance != NULL) &&
|
||||
(mModule->mCurMethodInstance->mMethodDef->IsCtorOrInit()) &&
|
||||
|
@ -6684,7 +6689,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
|||
#endif
|
||||
int vExtOfs = typeInst->GetOrigImplBaseVTableSize();
|
||||
|
||||
vDataIdx = mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1 + mModule->mCompiler->GetDynCastVDataCount() + mModule->mCompiler->mMaxInterfaceSlots);
|
||||
|
||||
vDataIdx = mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, mModule->mCompiler->GetVDataPrefixDataCount() + mModule->mCompiler->GetDynCastVDataCount() + mModule->mCompiler->mMaxInterfaceSlots);
|
||||
vDataIdx = mModule->mBfIRBuilder->CreateAdd(vDataIdx, mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, vExtOfs));
|
||||
BfIRValue extendPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(vDataPtr, vDataIdx);
|
||||
vDataPtr = mModule->mBfIRBuilder->CreateLoad(extendPtr);
|
||||
|
@ -7600,8 +7606,15 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
// Handled in args
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prevBindResult.mPrevVal == NULL)
|
||||
{
|
||||
if ((mModule->mAttributeState == NULL) || (mModule->mAttributeState->mCustomAttributes == NULL) ||
|
||||
(!mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoStaticCtorAttributeTypeDef)))
|
||||
{
|
||||
mModule->CheckStaticAccess(methodInstance->mMethodInstanceGroup->mOwner);
|
||||
}
|
||||
}
|
||||
|
||||
if (target)
|
||||
{
|
||||
|
@ -8613,8 +8626,17 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
// the type has been initialized
|
||||
auto targetTypeInst = target.mType->ToTypeInstance();
|
||||
if (targetTypeInst != NULL)
|
||||
{
|
||||
if (prevBindResult.mPrevVal == NULL)
|
||||
{
|
||||
if ((mModule->mAttributeState == NULL) || (mModule->mAttributeState->mCustomAttributes == NULL) ||
|
||||
(!mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoStaticCtorAttributeTypeDef)))
|
||||
{
|
||||
mModule->CheckStaticAccess(targetTypeInst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (methodInstance->mReturnType == NULL)
|
||||
{
|
||||
|
@ -12535,7 +12557,7 @@ void BfExprEvaluator::Visit(BfCheckTypeExpression* checkTypeExpr)
|
|||
void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||
{
|
||||
auto targetValue = mModule->CreateValueFromExpression(dynCastExpr->mTarget);
|
||||
auto targetType = mModule->ResolveTypeRefAllowUnboundGenerics(dynCastExpr->mTypeRef, BfPopulateType_Data, false);
|
||||
auto targetType = mModule->ResolveTypeRefAllowUnboundGenerics(dynCastExpr->mTypeRef, BfPopulateType_Data, BfResolveTypeRefFlag_None, false);
|
||||
|
||||
auto autoComplete = GetAutoComplete();
|
||||
if (autoComplete != NULL)
|
||||
|
@ -18843,6 +18865,10 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
|
|||
checkedKind = BfCheckedKind_Unchecked;
|
||||
mModule->mAttributeState->mUsed = true;
|
||||
}
|
||||
if (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoStaticCtorAttributeTypeDef))
|
||||
{
|
||||
mModule->mAttributeState->mUsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((isCascade) && (cascadeOperatorToken != NULL) && ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0))
|
||||
|
@ -20967,7 +20993,7 @@ void BfExprEvaluator::InitializedSizedArray(BfSizedArrayType* arrayType, BfToken
|
|||
}
|
||||
|
||||
elementValue = mModule->LoadOrAggregateValue(elementValue);
|
||||
if (!elementValue.mValue.IsConst())
|
||||
if (!elemPtrValue.IsConst())
|
||||
mModule->mBfIRBuilder->CreateAlignedStore(elementValue.mValue, elemPtrValue, checkArrayType->mElementType->mAlign);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5391,6 +5391,8 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou
|
|||
mClassVDataRefs.TryGetValue(typeInstance, &globalVariablePtr);
|
||||
|
||||
int numElements = 1;
|
||||
if (mSystem->mPtrSize == 4)
|
||||
numElements++;
|
||||
|
||||
if ((outNumElements != NULL) || (globalVariablePtr == NULL))
|
||||
{
|
||||
|
@ -5432,11 +5434,6 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou
|
|||
if (outMangledName != NULL)
|
||||
*outMangledName = classVDataName;
|
||||
|
||||
/*if (itr != mClassVDataRefs.end())
|
||||
{
|
||||
globalVariable = itr->second;
|
||||
}*/
|
||||
|
||||
BfIRValue globalVariable;
|
||||
if (globalVariablePtr != NULL)
|
||||
{
|
||||
|
@ -5937,7 +5934,21 @@ BfIRValue BfModule::CreateFieldData(BfFieldInstance* fieldInstance, int customAt
|
|||
return result;
|
||||
}
|
||||
|
||||
BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStringIdMap, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData)
|
||||
void BfModule::CreateSlotOfs(BfTypeInstance* typeInstance)
|
||||
{
|
||||
int virtSlotIdx = -1;
|
||||
if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0))
|
||||
virtSlotIdx = typeInstance->mSlotNum + mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount();
|
||||
|
||||
// For interfaces we ONLY emit the slot num
|
||||
StringT<512> slotVarName;
|
||||
BfMangler::MangleStaticFieldName(slotVarName, mCompiler->GetMangleKind(), typeInstance, "sBfSlotOfs");
|
||||
auto intType = GetPrimitiveType(BfTypeCode_Int32);
|
||||
auto slotNumVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External,
|
||||
GetConstValue32(virtSlotIdx), slotVarName);
|
||||
}
|
||||
|
||||
BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData)
|
||||
{
|
||||
if ((IsHotCompile()) && (!type->mDirty))
|
||||
return BfIRValue();
|
||||
|
@ -6004,13 +6015,18 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
|
||||
if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type) && (!mIsComptimeModule))
|
||||
{
|
||||
CreateTypeData(typeDataSource, usedStringIdMap, false, true, needsTypeNames, true);
|
||||
CreateTypeData(typeDataSource, ctx, false, true, needsTypeNames, true);
|
||||
}
|
||||
|
||||
typeTypeData = CreateClassVDataGlobal(typeDataSource);
|
||||
|
||||
ctx.mReflectTypeSet.Add(typeDataSource);
|
||||
}
|
||||
else
|
||||
typeTypeData = CreateClassVDataGlobal(typeInstanceType->ToTypeInstance());
|
||||
{
|
||||
//typeTypeData = CreateClassVDataGlobal(typeInstanceType->ToTypeInstance());
|
||||
typeTypeData = mBfIRBuilder->CreateConstNull();
|
||||
}
|
||||
|
||||
BfType* longType = GetPrimitiveType(BfTypeCode_Int64);
|
||||
BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
|
||||
|
@ -6119,7 +6135,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
|
||||
int virtSlotIdx = -1;
|
||||
if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0))
|
||||
virtSlotIdx = typeInstance->mSlotNum + 1 + mCompiler->GetDynCastVDataCount();
|
||||
virtSlotIdx = typeInstance->mSlotNum + mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount();
|
||||
int memberDataOffset = 0;
|
||||
if (type->IsInterface())
|
||||
memberDataOffset = virtSlotIdx * mSystem->mPtrSize;
|
||||
|
@ -6316,18 +6332,13 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
String classVDataName;
|
||||
if (typeInstance->mSlotNum >= 0)
|
||||
{
|
||||
// For interfaces we ONLY emit the slot num
|
||||
StringT<512> slotVarName;
|
||||
BfMangler::MangleStaticFieldName(slotVarName, mCompiler->GetMangleKind(), typeInstance, "sBfSlotOfs");
|
||||
auto intType = GetPrimitiveType(BfTypeCode_Int32);
|
||||
auto slotNumVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External,
|
||||
GetConstValue32(virtSlotIdx), slotVarName);
|
||||
CreateSlotOfs(typeInstance);
|
||||
}
|
||||
else if ((typeInstance->IsObject()) && (!typeInstance->IsUnspecializedType()) && (needsVData))
|
||||
{
|
||||
int dynCastDataElems = 0;
|
||||
int numElements = 1;
|
||||
int vDataOfs = 1; // The number of intptrs before the iface slot map
|
||||
int vDataOfs = mCompiler->GetVDataPrefixDataCount(); // The number of intptrs before the iface slot map
|
||||
numElements += mCompiler->mMaxInterfaceSlots;
|
||||
if (!typeInstance->IsInterface())
|
||||
{
|
||||
|
@ -6342,7 +6353,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
classVDataVar = CreateClassVDataGlobal(typeInstance, &expectNumElements, &classVDataName);
|
||||
}
|
||||
|
||||
vData.push_back(BfIRValue()); // Type*
|
||||
for (int i = 0; i < mCompiler->GetVDataPrefixDataCount(); i++)
|
||||
vData.push_back(BfIRValue()); // Type
|
||||
|
||||
SizedArray<BfIRValue, 1> extVTableData;
|
||||
|
||||
|
@ -6752,6 +6764,9 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
// Force override of GetHashCode so we use the pointer address as the hash code
|
||||
for (auto& checkIFace : checkTypeInst->mInterfaces)
|
||||
{
|
||||
if (checkIFace.mStartVirtualIdx < 0)
|
||||
continue;
|
||||
|
||||
for (int methodIdx = 0; methodIdx < (int)checkIFace.mInterfaceType->mMethodInstanceGroups.size(); methodIdx++)
|
||||
{
|
||||
BfIRValue pushValue;
|
||||
|
@ -6976,7 +6991,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
for (auto arg : attr->mCtorArgs)
|
||||
{
|
||||
auto argType = ctorMethodInstance->GetParamType(argIdx);
|
||||
EncodeAttributeData(typeInstance, argType, arg, data, usedStringIdMap);
|
||||
EncodeAttributeData(typeInstance, argType, arg, data, ctx.mUsedStringIdMap);
|
||||
argIdx++;
|
||||
}
|
||||
|
||||
|
@ -7494,7 +7509,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
}
|
||||
else
|
||||
{
|
||||
vDataIdx = 1 + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
|
||||
vDataIdx = mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
|
||||
if ((mCompiler->mOptions.mHasVDataExtender) && (mCompiler->IsHotCompile()))
|
||||
{
|
||||
auto typeInst = defaultMethod->mMethodInstanceGroup->mOwner;
|
||||
|
@ -7560,7 +7575,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
BfIRType interfaceDataPtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapType(reflectInterfaceDataType));
|
||||
Array<bool> wantsIfaceMethod;
|
||||
bool wantsIfaceMethods = false;
|
||||
if (typeInstance->mInterfaces.IsEmpty())
|
||||
if ((typeInstance->mInterfaces.IsEmpty()) || (!needsTypeData))
|
||||
interfaceDataPtr = mBfIRBuilder->CreateConstNull(interfaceDataPtrType);
|
||||
else
|
||||
{
|
||||
|
@ -7802,7 +7817,22 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
{
|
||||
BF_ASSERT(!classVDataName.IsEmpty());
|
||||
|
||||
vData[0] = mBfIRBuilder->CreateBitCast(typeDataVar, voidPtrIRType);
|
||||
//vData[0] = mBfIRBuilder->CreateBitCast(typeDataVar, voidPtrIRType);
|
||||
|
||||
int unboxedTypeId = type->mTypeId;
|
||||
if (type->IsBoxed())
|
||||
unboxedTypeId = type->GetUnderlyingType()->mTypeId;
|
||||
|
||||
if (mSystem->mPtrSize == 4)
|
||||
{
|
||||
vData[0] = mBfIRBuilder->CreateIntToPtr(GetConstValue(type->mTypeId, intPtrType), voidPtrIRType);
|
||||
vData[1] = mBfIRBuilder->CreateIntToPtr(GetConstValue(unboxedTypeId, intPtrType), voidPtrIRType);
|
||||
}
|
||||
else
|
||||
{
|
||||
vData[0] = mBfIRBuilder->CreateIntToPtr(GetConstValue(((int64)unboxedTypeId << 32) | type->mTypeId, intPtrType), voidPtrIRType);
|
||||
}
|
||||
|
||||
auto classVDataConstDataType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)vData.size());
|
||||
auto classVDataConstData = mBfIRBuilder->CreateConstAgg_Value(classVDataConstDataType, vData);
|
||||
|
||||
|
@ -10459,18 +10489,24 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
|
|||
mBfIRBuilder->CreateObjectAccessCheck(typedVal.mValue, !IsOptimized());
|
||||
}
|
||||
|
||||
void BfModule::EmitEnsureInstructionAt()
|
||||
bool BfModule::WantsDebugHelpers()
|
||||
{
|
||||
if (mBfIRBuilder->mIgnoreWrites)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (mIsComptimeModule)
|
||||
{
|
||||
// Always add
|
||||
}
|
||||
else if ((mProject == NULL) || (!mHasFullDebugInfo) || (IsOptimized()) || (mCompiler->mOptions.mOmitDebugHelpers))
|
||||
return;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void BfModule::EmitEnsureInstructionAt()
|
||||
{
|
||||
if (!WantsDebugHelpers())
|
||||
return;
|
||||
mBfIRBuilder->CreateEnsureInstructionAt();
|
||||
}
|
||||
|
||||
|
@ -10549,7 +10585,7 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
|
|||
targetType = GetWrappedStructType(targetType);
|
||||
|
||||
AddDependency(targetType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
|
||||
int inheritanceIdOfs = mSystem->mPtrSize;
|
||||
int inheritanceIdOfs = mSystem->mPtrSize * mCompiler->GetVDataPrefixDataCount();
|
||||
vDataPtr = irb->CreateAdd(vDataPtr, irb->CreateConst(BfTypeCode_IntPtr, inheritanceIdOfs));
|
||||
vDataPtr = irb->CreateIntToPtr(vDataPtr, irb->MapType(int32PtrType));
|
||||
BfIRValue objInheritanceId = irb->CreateLoad(vDataPtr);
|
||||
|
@ -11107,6 +11143,9 @@ BfModuleMethodInstance BfModule::GetMethodInstanceAtIdx(BfTypeInstance* typeInst
|
|||
|
||||
PopulateType(typeInstance, BfPopulateType_DataAndMethods);
|
||||
|
||||
if (methodIdx >= typeInstance->mMethodInstanceGroups.mSize)
|
||||
return BfModuleMethodInstance();
|
||||
|
||||
auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault;
|
||||
|
||||
BfMethodDef* methodDef = NULL;
|
||||
|
@ -14003,7 +14042,7 @@ BfModule* BfModule::GetOrCreateMethodModule(BfMethodInstance* methodInstance)
|
|||
return declareModule;
|
||||
}
|
||||
|
||||
BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags, BfTypeInstance* foreignType)
|
||||
BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags, BfTypeInstance* foreignType, BfModule* referencingModule)
|
||||
{
|
||||
if (methodDef->mMethodType == BfMethodType_Init)
|
||||
return BfModuleMethodInstance();
|
||||
|
@ -14129,6 +14168,8 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
|
|||
instModule->mReifyQueued = true;
|
||||
}
|
||||
|
||||
BfLogSysM("REIFIED(GetMethodInstance QueueSpecializationRequest): %s %s MethodDef:%p RefModule:%s RefMethod:%p\n", TypeToString(typeInst).c_str(), methodDef->mName.c_str(), methodDef, mModuleName.c_str(), mCurMethodInstance);
|
||||
|
||||
// This ensures that the method will actually be created when it gets reified
|
||||
BfMethodSpecializationRequest* specializationRequest = mContext->mMethodSpecializationWorkList.Alloc();
|
||||
specializationRequest->mFromModule = typeInst->mModule;
|
||||
|
@ -14154,7 +14195,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
|
|||
|
||||
// Not extern
|
||||
// Create the instance in the proper module and then create a reference in this one
|
||||
moduleMethodInst = instModule->GetMethodInstance(typeInst, methodDef, methodGenericArguments, defFlags, foreignType);
|
||||
moduleMethodInst = instModule->GetMethodInstance(typeInst, methodDef, methodGenericArguments, defFlags, foreignType, this);
|
||||
if (!moduleMethodInst)
|
||||
return moduleMethodInst;
|
||||
tryModuleMethodLookup = true;
|
||||
|
@ -14549,8 +14590,18 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
|
|||
/*if ((!mCompiler->mIsResolveOnly) && (!isReified))
|
||||
BF_ASSERT(!methodInstance->mIsReified);*/
|
||||
|
||||
if ((!mCompiler->mIsResolveOnly) && (isReified))
|
||||
{
|
||||
auto refModule = referencingModule;
|
||||
if (refModule == NULL)
|
||||
refModule = this;
|
||||
BfLogSysM("REIFIED(GetMethodInstance Reference): %s MethodDef:%p MethodInst:%p RefModule:%s RefMethod:%p\n", methodInstance->mMethodDef->mName.c_str(), methodDef, methodInstance, refModule->mModuleName.c_str(), refModule->mCurMethodInstance);
|
||||
}
|
||||
|
||||
if (methodInstance->mIsReified != isReified)
|
||||
{
|
||||
BfLogSysM("GetMethodInstance %p Decl_AwaitingReference setting reified to %d\n", methodInstance, isReified);
|
||||
}
|
||||
|
||||
if ((!isReified) &&
|
||||
((methodInstance->mDeclModule == NULL) || (!methodInstance->mDeclModule->mIsModuleMutable)))
|
||||
|
@ -14975,6 +15026,9 @@ BfIRValue BfModule::GetInterfaceSlotNum(BfTypeInstance* ifaceType)
|
|||
|
||||
globalValue = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External, value, slotVarName);
|
||||
mInterfaceSlotRefs[ifaceType] = globalValue;
|
||||
// Make sure we reify
|
||||
PopulateType(ifaceType, BfPopulateType_Declaration);
|
||||
AddDependency(ifaceType, mCurTypeInstance, BfDependencyMap::DependencyFlag_StaticValue);
|
||||
}
|
||||
|
||||
return mBfIRBuilder->CreateAlignedLoad(globalValue/*, "slotOfs"*/, 4);
|
||||
|
@ -20087,6 +20141,26 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
|
|||
if (mAwaitingInitFinish)
|
||||
FinishInit();
|
||||
|
||||
if ((methodInstance->mIsReified) && (!mCompiler->mIsResolveOnly))
|
||||
{
|
||||
BfLogSysM("REIFIED(ProcessMethod): %s %p Module: %s\n", methodInstance->mMethodDef->mName.c_str(), methodInstance, mModuleName.c_str());
|
||||
}
|
||||
|
||||
// Reify types that are actually used - they don't get reified during method declaration
|
||||
if ((!mCompiler->mIsResolveOnly) && (mIsReified))
|
||||
{
|
||||
auto _CheckType = [&](BfType* type)
|
||||
{
|
||||
if (!type->IsReified())
|
||||
PopulateType(type, BfPopulateType_Declaration);
|
||||
};
|
||||
_CheckType(methodInstance->mReturnType);
|
||||
for (auto& param : methodInstance->mParams)
|
||||
{
|
||||
_CheckType(param.mResolvedType);
|
||||
}
|
||||
}
|
||||
|
||||
if (!methodInstance->mIsReified)
|
||||
BF_ASSERT(!mIsReified);
|
||||
|
||||
|
@ -22047,12 +22121,15 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
|
|||
if ((retVal) && (!retVal.mType->IsVar()) && (expectingType != NULL))
|
||||
{
|
||||
mCurMethodState->mHadReturn = true;
|
||||
if (!mCurMethodState->mLeftBlockUncond)
|
||||
{
|
||||
retVal = LoadOrAggregateValue(retVal);
|
||||
EmitReturn(retVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BF_ASSERT(mCurMethodState->mCurScope == &mCurMethodState->mHeadScope);
|
||||
|
||||
|
@ -23719,6 +23796,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
BfTypeState typeState(mCurTypeInstance);
|
||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||
|
||||
BfModule* resolveModule = mContext->mUnreifiedModule;
|
||||
|
||||
if (mCompiler->IsAutocomplete())
|
||||
prevIsCapturingMethodMatchInfo.Init(mCompiler->mResolvePassData->mAutoComplete->mIsCapturingMethodMatchInfo, false);
|
||||
|
||||
|
@ -23963,7 +24042,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
mIgnoreErrors = false;
|
||||
}
|
||||
|
||||
BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric);
|
||||
BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric | BfResolveTypeRefFlag_NoReify);
|
||||
|
||||
if ((((methodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) || (methodInstance->mIsAutocompleteMethod))
|
||||
&& (methodDef->mReturnTypeRef->IsA<BfVarTypeReference>()))
|
||||
|
@ -24055,14 +24134,14 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
{
|
||||
BfTypeUtils::SplatIterate([&](BfType* checkType)
|
||||
{
|
||||
PopulateType(checkType, BfPopulateType_Data);
|
||||
resolveModule->PopulateType(checkType, BfPopulateType_Data);
|
||||
}, thisType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
thisType = mCurTypeInstance;
|
||||
PopulateType(thisType, BfPopulateType_Declaration);
|
||||
resolveModule->PopulateType(thisType, BfPopulateType_Declaration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24137,7 +24216,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
bool wasGenericParam = false;
|
||||
if (resolvedParamType == NULL)
|
||||
{
|
||||
BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue);
|
||||
BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue | BfResolveTypeRefFlag_NoReify);
|
||||
if (paramDef->mParamKind == BfParamKind_ExplicitThis)
|
||||
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_NoWarnOnMut);
|
||||
resolvedParamType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, resolveFlags);
|
||||
|
@ -24388,7 +24467,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
}
|
||||
|
||||
int argIdx = 0;
|
||||
PopulateType(methodInstance->mReturnType, BfPopulateType_Data);
|
||||
resolveModule->PopulateType(methodInstance->mReturnType, BfPopulateType_Data);
|
||||
if ((!methodDef->mIsStatic) && (!methodDef->mHasExplicitThis))
|
||||
{
|
||||
int thisIdx = methodDef->mHasExplicitThis ? 0 : -1;
|
||||
|
@ -24428,7 +24507,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
}
|
||||
else if ((checkType->IsComposite()) && (methodInstance->AllowsSplatting(paramIdx)))
|
||||
{
|
||||
PopulateType(checkType, BfPopulateType_Data);
|
||||
resolveModule->PopulateType(checkType, BfPopulateType_Data);
|
||||
if (checkType->IsSplattable())
|
||||
{
|
||||
bool isSplat = false;
|
||||
|
@ -24569,7 +24648,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
{
|
||||
auto paramType = methodInstance->GetParamType(paramIdx);
|
||||
if (paramType->IsComposite())
|
||||
PopulateType(paramType, BfPopulateType_Data);
|
||||
resolveModule->PopulateType(paramType, BfPopulateType_Data);
|
||||
|
||||
if (!methodInstance->IsParamSkipped(paramIdx))
|
||||
{
|
||||
|
@ -24588,7 +24667,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
if (methodInstance->mIsUnspecializedVariation)
|
||||
return;
|
||||
|
||||
PopulateType(resolvedReturnType, BfPopulateType_Data);
|
||||
resolveModule->PopulateType(resolvedReturnType, BfPopulateType_Data);
|
||||
auto retLLVMType = mBfIRBuilder->MapType(resolvedReturnType);
|
||||
if (resolvedReturnType->IsValuelessType())
|
||||
retLLVMType = mBfIRBuilder->GetPrimitiveType(BfTypeCode_None);
|
||||
|
@ -26023,6 +26102,8 @@ void BfModule::DbgFinish()
|
|||
if (mBfIRBuilder->DbgHasInfo())
|
||||
{
|
||||
bool needForceLinking = false;
|
||||
if (WantsDebugHelpers())
|
||||
{
|
||||
for (auto& ownedType : mOwnedTypeInstances)
|
||||
{
|
||||
bool hasConfirmedReference = false;
|
||||
|
@ -26039,6 +26120,7 @@ void BfModule::DbgFinish()
|
|||
if ((!hasConfirmedReference) || (ownedType->IsBoxed()))
|
||||
needForceLinking = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((needForceLinking) && (mProject->mCodeGenOptions.mAsmKind == BfAsmKind_None))
|
||||
{
|
||||
|
@ -26153,7 +26235,7 @@ bool BfModule::Finish()
|
|||
codeGenOptions.mWriteLLVMIR = mCompiler->mOptions.mWriteIR;
|
||||
codeGenOptions.mWriteObj = mCompiler->mOptions.mGenerateObj;
|
||||
codeGenOptions.mWriteBitcode = mCompiler->mOptions.mGenerateBitcode;
|
||||
codeGenOptions.mVirtualMethodOfs = 1 + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
|
||||
codeGenOptions.mVirtualMethodOfs = mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
|
||||
codeGenOptions.mDynSlotOfs = mSystem->mPtrSize - mCompiler->GetDynCastVDataCount() * 4;
|
||||
|
||||
mCompiler->mStats.mIRBytes += mBfIRBuilder->mStream.GetSize();
|
||||
|
|
|
@ -158,6 +158,12 @@ enum BfLocalVarAssignKind : int8
|
|||
BfLocalVarAssignKind_Unconditional = 2
|
||||
};
|
||||
|
||||
struct BfCreateTypeDataContext
|
||||
{
|
||||
Dictionary<int, int> mUsedStringIdMap;
|
||||
HashSet<BfTypeInstance*> mReflectTypeSet;
|
||||
};
|
||||
|
||||
class BfLocalVariable
|
||||
{
|
||||
public:
|
||||
|
@ -1740,6 +1746,7 @@ public:
|
|||
bool HasExecutedOutput();
|
||||
void SkipObjectAccessCheck(BfTypedValue typedVal);
|
||||
void EmitObjectAccessCheck(BfTypedValue typedVal);
|
||||
bool WantsDebugHelpers();
|
||||
void EmitEnsureInstructionAt();
|
||||
void EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* targetType, BfIRBlock trueBlock, BfIRBlock falseBlock, bool nullSucceeds = false);
|
||||
void EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull);
|
||||
|
@ -1966,7 +1973,7 @@ public:
|
|||
bool ValidateTypeWildcard(BfAstNode* typeRef, bool isAttributeRef);
|
||||
void GetDelegateTypeRefAttributes(BfDelegateTypeRef* delegateTypeRef, BfCallingConvention& callingConvention);
|
||||
BfType* ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, int numGenericArgs = 0);
|
||||
BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool resolveGenericParam = true);
|
||||
BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, bool resolveGenericParam = true);
|
||||
BfType* ResolveTypeRef_Type(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
|
||||
BfType* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfAstNode*>* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
|
||||
BfType* ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);
|
||||
|
@ -2062,7 +2069,7 @@ public:
|
|||
void SetMethodDependency(BfMethodInstance* methodInstance);
|
||||
BfModuleMethodInstance ReferenceExternalMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);
|
||||
BfModule* GetOrCreateMethodModule(BfMethodInstance* methodInstance);
|
||||
BfModuleMethodInstance GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None, BfTypeInstance* foreignType = NULL);
|
||||
BfModuleMethodInstance GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None, BfTypeInstance* foreignType = NULL, BfModule* referencingModule = NULL);
|
||||
BfModuleMethodInstance GetMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);
|
||||
BfMethodInstance* GetOuterMethodInstance(BfMethodInstance* methodInstance); // Only useful for local methods
|
||||
void SetupMethodIdHash(BfMethodInstance* methodInstance);
|
||||
|
@ -2075,7 +2082,8 @@ public:
|
|||
BfIRValue CreateTypeDataRef(BfType* type);
|
||||
void EncodeAttributeData(BfTypeInstance* typeInstance, BfType* argType, BfIRValue arg, SizedArrayImpl<uint8>& data, Dictionary<int, int>& usedStringIdMap);
|
||||
BfIRValue CreateFieldData(BfFieldInstance* fieldInstance, int customAttrIdx);
|
||||
BfIRValue CreateTypeData(BfType* type, Dictionary<int, int>& usedStringIdMap, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData);
|
||||
void CreateSlotOfs(BfTypeInstance* typeInstance);
|
||||
BfIRValue CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData);
|
||||
BfIRValue FixClassVData(BfIRValue value);
|
||||
|
||||
public:
|
||||
|
|
|
@ -410,7 +410,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
|
|||
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, mIgnoreErrors || ignoreErrors);
|
||||
genericTypeInst->mGenericTypeInfo->mValidatedGenericConstraints = true;
|
||||
if (!genericTypeInst->mGenericTypeInfo->mFinishedGenericParams)
|
||||
PopulateType(genericTypeInst, BfPopulateType_Interfaces_All);
|
||||
mContext->mUnreifiedModule->PopulateType(genericTypeInst, BfPopulateType_Interfaces_All);
|
||||
|
||||
if (genericTypeInst->IsTypeAlias())
|
||||
{
|
||||
|
@ -418,7 +418,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
|
|||
if ((underlyingType != NULL) && (underlyingType->IsGenericTypeInstance()))
|
||||
{
|
||||
auto underlyingGenericType = underlyingType->ToGenericTypeInstance();
|
||||
PopulateType(underlyingType, BfPopulateType_Declaration);
|
||||
mContext->mUnreifiedModule->PopulateType(underlyingType, BfPopulateType_Declaration);
|
||||
bool result = ValidateGenericConstraints(typeRef, underlyingGenericType, ignoreErrors);
|
||||
if (underlyingGenericType->mGenericTypeInfo->mHadValidateErrors)
|
||||
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
|
||||
|
@ -441,7 +441,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
|
|||
{
|
||||
startGenericParamIdx = typeDef->mOuterType->mGenericParamDefs.mSize + typeDef->mOuterType->mExternalConstraints.mSize;
|
||||
auto outerType = GetOuterType(genericTypeInst);
|
||||
PopulateType(outerType, BfPopulateType_Declaration);
|
||||
mContext->mUnreifiedModule->PopulateType(outerType, BfPopulateType_Declaration);
|
||||
if ((outerType->mGenericTypeInfo != NULL) && (outerType->mGenericTypeInfo->mHadValidateErrors))
|
||||
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
|
||||
}
|
||||
|
@ -802,6 +802,11 @@ void BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((typeInst != NULL) && (typeInst->mIsReified) && (!mCompiler->mIsResolveOnly))
|
||||
{
|
||||
BfLogSysM("REIFIED(InitType): %s Type:%p FromModule:%s FromMethod:%p\n", TypeToString(resolvedTypeRef).c_str(), resolvedTypeRef, mModuleName.c_str(), prevMethodInstance.mPrevVal);
|
||||
}
|
||||
|
||||
BfLogSysM("%p InitType: %s Type: %p TypeDef: %p Revision:%d\n", mContext, TypeToString(resolvedTypeRef).c_str(), resolvedTypeRef, (typeInst != NULL) ? typeInst->mTypeDef : NULL, mCompiler->mRevision);
|
||||
|
||||
// When we're autocomplete, we can't do the method processing so we have to add this type to the type work list
|
||||
|
@ -1212,6 +1217,14 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
|
|||
canFastReify = false;
|
||||
}
|
||||
|
||||
if (!mCompiler->mIsResolveOnly)
|
||||
{
|
||||
for (auto ownedTypes : typeModule->mOwnedTypeInstances)
|
||||
{
|
||||
BfLogSysM("REIFIED(PopulateType-Reference): %s %p FromModule:%s FromMethod: %p\n", TypeToString(ownedTypes).c_str(), ownedTypes, mModuleName.c_str(), mCurMethodInstance);
|
||||
}
|
||||
}
|
||||
|
||||
if (canFastReify)
|
||||
{
|
||||
BfLogSysM("Setting reified type %p in module %p in PopulateType on module awaiting finish\n", resolvedTypeRef, typeModule);
|
||||
|
@ -1292,7 +1305,17 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
|
|||
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
|
||||
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL);
|
||||
|
||||
BF_ASSERT((resolvedTypeRef->mRebuildFlags & (BfTypeRebuildFlag_Deleted | BfTypeRebuildFlag_DeleteQueued)) == 0);
|
||||
if ((resolvedTypeRef->mRebuildFlags & (BfTypeRebuildFlag_Deleted | BfTypeRebuildFlag_DeleteQueued)) != 0)
|
||||
{
|
||||
if (mContext->mGhostDependencies.Contains(resolvedTypeRef))
|
||||
{
|
||||
// Not a nice state, but we should be able to recover
|
||||
return;
|
||||
}
|
||||
|
||||
InternalError("Attempting PopulateType on deleted type");
|
||||
return;
|
||||
}
|
||||
|
||||
bool isNew = resolvedTypeRef->mDefineState == BfTypeDefineState_Undefined;
|
||||
if (isNew)
|
||||
|
@ -8268,7 +8291,7 @@ BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType
|
|||
|
||||
auto typeDefTypeRef = mContext->mTypeDefTypeRefPool.Get();
|
||||
typeDefTypeRef->mTypeDef = typeDef;
|
||||
auto resolvedtypeDefType = ResolveTypeRef(typeDefTypeRef, populateType);
|
||||
auto resolvedtypeDefType = ResolveTypeRef(typeDefTypeRef, populateType, resolveFlags);
|
||||
if (resolvedtypeDefType == NULL)
|
||||
{
|
||||
mContext->mTypeDefTypeRefPool.GiveBack(typeDefTypeRef);
|
||||
|
@ -11347,7 +11370,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
}
|
||||
}
|
||||
|
||||
return ResolveTypeResult(typeRef, ResolveTypeDef(typeDef, genericArgs, populateType), populateType, resolveFlags);
|
||||
return ResolveTypeResult(typeRef, ResolveTypeDef(typeDef, genericArgs, populateType, resolveFlags), populateType, resolveFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12635,7 +12658,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
|
||||
}
|
||||
|
||||
BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType, bool resolveGenericParam)
|
||||
BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags, bool resolveGenericParam)
|
||||
{
|
||||
if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(typeRef))
|
||||
{
|
||||
|
@ -12648,7 +12671,7 @@ BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, B
|
|||
BfTypeVector typeVector;
|
||||
for (int i = 0; i < (int)genericTypeDef->mGenericParamDefs.size(); i++)
|
||||
typeVector.push_back(GetGenericParamType(BfGenericParamKind_Type, i));
|
||||
auto result = ResolveTypeDef(genericTypeDef, typeVector, populateType);
|
||||
auto result = ResolveTypeDef(genericTypeDef, typeVector, populateType, resolveFlags);
|
||||
if ((result != NULL) && (genericTypeRef->mCommas.size() + 1 != genericTypeDef->mGenericParamDefs.size()))
|
||||
{
|
||||
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, result->ToTypeInstance());
|
||||
|
|
|
@ -1270,11 +1270,12 @@ bool BfMethodInstance::WasGenericParam(int paramIdx)
|
|||
|
||||
bool BfMethodInstance::IsParamSkipped(int paramIdx)
|
||||
{
|
||||
auto resolveModule = GetModule()->mContext->mUnreifiedModule;
|
||||
if (paramIdx == -1)
|
||||
return false;
|
||||
BfType* paramType = GetParamType(paramIdx);
|
||||
if ((paramType->CanBeValuelessType()) && (paramType->IsDataIncomplete()))
|
||||
GetModule()->PopulateType(paramType, BfPopulateType_Data);
|
||||
resolveModule->PopulateType(paramType, BfPopulateType_Data);
|
||||
if ((paramType->IsValuelessType()) && (!paramType->IsMethodRef()))
|
||||
return true;
|
||||
return false;
|
||||
|
@ -1344,7 +1345,7 @@ int BfMethodInstance::DbgGetVirtualMethodNum()
|
|||
module->HadSlotCountDependency();
|
||||
|
||||
int vDataIdx = -1;
|
||||
vDataIdx = 1 + module->mCompiler->mMaxInterfaceSlots;
|
||||
vDataIdx = module->mCompiler->GetVDataPrefixDataCount() + module->mCompiler->mMaxInterfaceSlots;
|
||||
vDataIdx += module->mCompiler->GetDynCastVDataCount();
|
||||
if ((module->mCompiler->mOptions.mHasVDataExtender) && (module->mCompiler->IsHotCompile()))
|
||||
{
|
||||
|
@ -1375,7 +1376,9 @@ int BfMethodInstance::DbgGetVirtualMethodNum()
|
|||
|
||||
void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, SizedArrayImpl<BfIRType>& paramTypes, bool forceStatic)
|
||||
{
|
||||
module->PopulateType(mReturnType);
|
||||
BfModule* resolveModule = module->mContext->mUnreifiedModule;
|
||||
|
||||
resolveModule->PopulateType(mReturnType);
|
||||
|
||||
BfTypeCode loweredReturnTypeCode = BfTypeCode_None;
|
||||
BfTypeCode loweredReturnTypeCode2 = BfTypeCode_None;
|
||||
|
@ -1459,7 +1462,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
|
|||
else
|
||||
{
|
||||
if ((checkType->IsComposite()) && (checkType->IsIncomplete()))
|
||||
module->PopulateType(checkType, BfPopulateType_Data);
|
||||
resolveModule->PopulateType(checkType, BfPopulateType_Data);
|
||||
|
||||
if (checkType->IsMethodRef())
|
||||
{
|
||||
|
@ -1492,7 +1495,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
|
|||
}
|
||||
|
||||
if (checkType->CanBeValuelessType())
|
||||
module->PopulateType(checkType, BfPopulateType_Data);
|
||||
resolveModule->PopulateType(checkType, BfPopulateType_Data);
|
||||
if ((checkType->IsValuelessType()) && (!checkType->IsMethodRef()))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -6714,7 +6714,8 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
PopulateType(itrInterface, BfPopulateType_Full_Force);
|
||||
getNextMethodInst = GetMethodByName(itrInterface, "GetNext");
|
||||
}
|
||||
BF_ASSERT(getNextMethodInst);
|
||||
if (getNextMethodInst)
|
||||
{
|
||||
nextResult = BfTypedValue(CreateAlloca(getNextMethodInst.mMethodInstance->mReturnType), getNextMethodInst.mMethodInstance->mReturnType, true);
|
||||
|
||||
if (nextResult.mType->IsGenericTypeInstance())
|
||||
|
@ -6722,6 +6723,11 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
nextEmbeddedType = ((BfTypeInstance*)nextResult.mType)->mGenericTypeInfo->mTypeGenericArguments[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
InternalError("Failed to find GetNext");
|
||||
}
|
||||
}
|
||||
if (nextEmbeddedType == NULL)
|
||||
nextEmbeddedType = GetPrimitiveType(BfTypeCode_Var);
|
||||
|
||||
|
|
|
@ -3865,8 +3865,8 @@ addr_ce CeContext::GetReflectType(int typeId)
|
|||
if (bfType->mDefineState != BfTypeDefineState_CETypeInit)
|
||||
ceModule->PopulateType(bfType, BfPopulateType_DataAndMethods);
|
||||
|
||||
Dictionary<int, int> usedStringMap;
|
||||
auto irData = ceModule->CreateTypeData(bfType, usedStringMap, true, true, true, false);
|
||||
BfCreateTypeDataContext createTypeDataCtx;
|
||||
auto irData = ceModule->CreateTypeData(bfType, createTypeDataCtx, true, true, true, false);
|
||||
|
||||
BeValue* beValue = NULL;
|
||||
if (auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(irData))
|
||||
|
|
|
@ -833,6 +833,11 @@ bool DbgSubprogram::IsLambda()
|
|||
return StringView(mName).Contains('$');
|
||||
}
|
||||
|
||||
int DbgSubprogram::GetByteCount()
|
||||
{
|
||||
return (int)(mBlock.mHighPC - mBlock.mLowPC);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbgSubprogram::~DbgSubprogram()
|
||||
|
@ -5783,7 +5788,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
|
|||
|
||||
Array<PESectionHeader> sectionHeaders;
|
||||
sectionHeaders.Resize(ntHdr.mFileHeader.mNumberOfSections);
|
||||
mSectionRVAs.Resize(sectionHeaders.size() + 1);
|
||||
mSectionHeaders.Resize(sectionHeaders.size() + 1);
|
||||
|
||||
Array<String> sectionNames;
|
||||
sectionNames.Resize(ntHdr.mFileHeader.mNumberOfSections);
|
||||
|
@ -5792,7 +5797,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
|
|||
|
||||
for (int sectNum = 0; sectNum < ntHdr.mFileHeader.mNumberOfSections; sectNum++)
|
||||
{
|
||||
mSectionRVAs[sectNum] = sectionHeaders[sectNum].mVirtualAddress;
|
||||
mSectionHeaders[sectNum] = sectionHeaders[sectNum];
|
||||
}
|
||||
|
||||
int tlsSection = -1;
|
||||
|
@ -5827,6 +5832,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
|
|||
}
|
||||
|
||||
DbgSection dwSection;
|
||||
dwSection.mName = name;
|
||||
dwSection.mIsExecutable = (sectHdr.mCharacteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
|
||||
dwSection.mAddrStart = sectHdr.mVirtualAddress;
|
||||
dwSection.mAddrLength = BF_MAX(sectHdr.mSizeOfRawData, sectHdr.mVirtualSize);
|
||||
|
@ -6290,7 +6296,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
|
|||
}
|
||||
}
|
||||
else
|
||||
targetAddr = mSectionRVAs[symInfo->mSectionNum - 1] + symInfo->mValue;
|
||||
targetAddr = mSectionHeaders[symInfo->mSectionNum - 1].mVirtualAddress + symInfo->mValue;
|
||||
|
||||
if (((targetAddr != 0) || (isTLS)) &&
|
||||
(name[0] != '.'))
|
||||
|
|
|
@ -442,6 +442,7 @@ public:
|
|||
bool IsGenericMethod();
|
||||
bool ThisIsSplat();
|
||||
bool IsLambda();
|
||||
int GetByteCount();
|
||||
|
||||
DbgSubprogram* GetRootInlineParent()
|
||||
{
|
||||
|
@ -823,6 +824,7 @@ public:
|
|||
addr_target mAddress;
|
||||
int mCompileUnitId;
|
||||
int mLength;
|
||||
int mSection;
|
||||
};
|
||||
|
||||
class DbgCompileUnit
|
||||
|
@ -874,6 +876,7 @@ public:
|
|||
class DbgSection
|
||||
{
|
||||
public:
|
||||
String mName;
|
||||
addr_target mAddrStart;
|
||||
addr_target mAddrLength;
|
||||
bool mWritingEnabled;
|
||||
|
@ -1183,7 +1186,7 @@ public:
|
|||
bool mIsDwarf64;
|
||||
|
||||
HashSet<DbgSrcFile*> mSrcFileDeferredRefs;
|
||||
Array<addr_target> mSectionRVAs;
|
||||
Array<PESectionHeader> mSectionHeaders;
|
||||
SLIList<DbgSymbol*> mDeferredSymbols;
|
||||
Beefy::OwnedVector<DbgDeferredHotResolve> mDeferredHotResolveList;
|
||||
Array<DbgHotTargetSection*> mHotTargetSections;
|
||||
|
|
|
@ -1548,6 +1548,13 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetModulesInfo()
|
|||
return outString.c_str();
|
||||
}
|
||||
|
||||
BF_EXPORT const char* BF_CALLTYPE Debugger_GetModuleInfo(const char* moduleName)
|
||||
{
|
||||
String& outString = *gTLStrReturn.Get();
|
||||
outString = gDebugger->GetModuleInfo(moduleName);
|
||||
return outString.c_str();
|
||||
}
|
||||
|
||||
BF_EXPORT void BF_CALLTYPE Debugger_CancelSymSrv()
|
||||
{
|
||||
gDebugger->CancelSymSrv();
|
||||
|
|
|
@ -343,6 +343,7 @@ public:
|
|||
virtual String FindLineCallAddresses(intptr address) = 0;
|
||||
virtual String GetCurrentException() = 0;
|
||||
virtual String GetModulesInfo() = 0;
|
||||
virtual String GetModuleInfo(const StringImpl& moduleName) { return ""; }
|
||||
virtual void SetAliasPath(const StringImpl& origPath, const StringImpl& localPath) = 0;
|
||||
virtual void CancelSymSrv() = 0;
|
||||
virtual bool HasPendingDebugLoads() = 0;
|
||||
|
|
|
@ -8,6 +8,8 @@ USING_NS_BF_DBG;
|
|||
DbgHotScanner::DbgHotScanner(WinDebugger* debugger)
|
||||
{
|
||||
mDebugger = debugger;
|
||||
mBfTypesInfoAddr = 0;
|
||||
mDbgGCData = { 0 };
|
||||
}
|
||||
|
||||
NS_BF_DBG_BEGIN
|
||||
|
@ -255,7 +257,11 @@ void DbgHotScanner::ScanSpan(TCFake::Span* span, int expectedStartPage, int memK
|
|||
int* typeIdPtr = NULL;
|
||||
if (mFoundClassVDataAddrs.TryAdd(classVDataAddr, NULL, &typeIdPtr))
|
||||
{
|
||||
addr_target typeAddr = mDebugger->ReadMemory<addr_target>(classVDataAddr);
|
||||
if (mBfTypesInfoAddr > 0)
|
||||
{
|
||||
addr_target typeId = mDebugger->ReadMemory<int32>(classVDataAddr);
|
||||
addr_target arrayAddr = mBfTypesInfoAddr + typeId * sizeof(addr_target);
|
||||
addr_target typeAddr = mDebugger->ReadMemory<addr_target>(arrayAddr);
|
||||
Fake_Type_Data typeData;
|
||||
mDebugger->ReadMemory(typeAddr + objectSize, sizeof(typeData), &typeData);
|
||||
|
||||
|
@ -272,6 +278,7 @@ void DbgHotScanner::ScanSpan(TCFake::Span* span, int expectedStartPage, int memK
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_MarkTypeUsed(*typeIdPtr, elementSize);
|
||||
|
@ -358,6 +365,7 @@ void DbgHotScanner::Scan(DbgHotResolveFlags flags)
|
|||
{
|
||||
if ((module->mFilePath.Contains("Beef")) && (module->mFilePath.Contains("Dbg")))
|
||||
{
|
||||
module->ParseTypeData();
|
||||
module->ParseSymbolData();
|
||||
auto entry = module->mSymbolNameMap.Find("gGCDbgData");
|
||||
if ((entry != NULL) && (entry->mValue != NULL))
|
||||
|
@ -365,6 +373,44 @@ void DbgHotScanner::Scan(DbgHotResolveFlags flags)
|
|||
}
|
||||
}
|
||||
|
||||
auto module = mDebugger->mDebugTarget->mTargetBinary;
|
||||
if (module->mBfTypesInfoAddr == 0)
|
||||
{
|
||||
module->mBfTypesInfoAddr = -1;
|
||||
auto typeTypeEntry = module->FindType("System.Type", DbgLanguage_Beef);
|
||||
if ((typeTypeEntry != NULL) && (typeTypeEntry->mValue != NULL))
|
||||
{
|
||||
auto typeType = typeTypeEntry->mValue;
|
||||
module->mBfTypeType = typeType;
|
||||
if (typeType->mNeedsGlobalsPopulated)
|
||||
typeType->mCompileUnit->mDbgModule->PopulateTypeGlobals(typeType);
|
||||
|
||||
for (auto member : typeType->mMemberList)
|
||||
{
|
||||
if ((member->mIsStatic) && (member->mName != NULL) && (strcmp(member->mName, "sTypes") == 0) && (member->mLocationData != NULL))
|
||||
{
|
||||
DbgAddrType addrType;
|
||||
module->mBfTypesInfoAddr = member->mCompileUnit->mDbgModule->EvaluateLocation(NULL, member->mLocationData, member->mLocationLen, NULL, &addrType);
|
||||
}
|
||||
}
|
||||
|
||||
if (module->mBfTypesInfoAddr <= 0)
|
||||
{
|
||||
auto entry = module->mSymbolNameMap.Find(
|
||||
#ifdef BF_DBG_64
|
||||
"?sTypes@Type@System@bf@@2PEAPEAV123@A"
|
||||
#else
|
||||
"?sTypes@Type@System@bf@@2PAPAV123@A"
|
||||
#endif
|
||||
);
|
||||
|
||||
if (entry)
|
||||
module->mBfTypesInfoAddr = entry->mValue->mAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
mBfTypesInfoAddr = module->mBfTypesInfoAddr;
|
||||
|
||||
if (gcDbgDataAddr == 0)
|
||||
return;
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ class DbgHotScanner
|
|||
public:
|
||||
WinDebugger* mDebugger;
|
||||
DbgGCData mDbgGCData;
|
||||
addr_target mBfTypesInfoAddr;
|
||||
Beefy::Dictionary<addr_target, int> mFoundClassVDataAddrs;
|
||||
Beefy::Dictionary<addr_target, int> mFoundRawAllocDataAddrs;
|
||||
Beefy::Dictionary<addr_target, int> mFoundTypeAddrs;
|
||||
|
|
|
@ -8,6 +8,9 @@ StartupProject = "Tests"
|
|||
[Configs.Debug.Win64]
|
||||
IntermediateType = "ObjectAndIRCode"
|
||||
|
||||
[Configs.Debug.Win32]
|
||||
IntermediateType = "ObjectAndIRCode"
|
||||
|
||||
[Configs.Test.Win64]
|
||||
IntermediateType = "ObjectAndIRCode"
|
||||
COptimizationLevel = "O2"
|
||||
|
|
|
@ -12872,6 +12872,210 @@ String WinDebugger::GetModulesInfo()
|
|||
return str;
|
||||
}
|
||||
|
||||
String WinDebugger::GetModuleInfo(const StringImpl& modulePath)
|
||||
{
|
||||
AutoCrit autoCrit(mDebugManager->mCritSect);
|
||||
|
||||
String result;
|
||||
|
||||
for (auto dbgModule : mDebugTarget->mDbgModules)
|
||||
{
|
||||
if (modulePath.Equals(dbgModule->mFilePath, StringImpl::CompareKind_OrdinalIgnoreCase))
|
||||
{
|
||||
dbgModule->ParseGlobalsData();
|
||||
dbgModule->PopulateStaticVariableMap();
|
||||
|
||||
auto coff = (COFF*)dbgModule;
|
||||
coff->ParseCompileUnits();
|
||||
|
||||
int fileSize = 0;
|
||||
//
|
||||
{
|
||||
FileStream fs;
|
||||
fs.Open(coff->mFilePath, "rb");
|
||||
fileSize = fs.GetSize();
|
||||
}
|
||||
|
||||
result += StrFormat("Path: %s FileSize:%0.2fk MemoryImage:%0.2fk\n", coff->mFilePath.c_str(), fileSize / 1024.0f, coff->mImageSize / 1024.0f);
|
||||
|
||||
result += "Sections:\n";
|
||||
for (auto& section : coff->mSections)
|
||||
{
|
||||
result += StrFormat("\t%s\t%0.2fk\n", section.mName.c_str(), (section.mAddrLength) / 1024.0f);
|
||||
}
|
||||
result += "\n";
|
||||
|
||||
result += "Compile Units:\n";
|
||||
for (auto compileUnit : dbgModule->mCompileUnits)
|
||||
{
|
||||
coff->MapCompileUnitMethods(compileUnit);
|
||||
result += StrFormat("\t%s PCRange:%0.2fk\n", compileUnit->mName.c_str(), (compileUnit->mHighPC - compileUnit->mLowPC) / 1024.0f);
|
||||
}
|
||||
result += "\n";
|
||||
|
||||
Array<CvModuleInfo*> moduleInfos;
|
||||
for (auto moduleInfo : coff->mCvModuleInfo)
|
||||
{
|
||||
if (moduleInfo->mSectionContrib.mSize > 0)
|
||||
moduleInfos.Add(moduleInfo);
|
||||
}
|
||||
moduleInfos.Sort([](CvModuleInfo* lhs, CvModuleInfo* rhs)
|
||||
{
|
||||
return lhs->mSectionContrib.mSize > rhs->mSectionContrib.mSize;
|
||||
});
|
||||
|
||||
int totalContrib = 0;
|
||||
result += "CV Module Info:\n";
|
||||
for (auto moduleInfo : moduleInfos)
|
||||
{
|
||||
auto section = coff->mSections[moduleInfo->mSectionContrib.mSection - 1];
|
||||
|
||||
result += StrFormat("\t%s\t%s\t%0.2fk\t%@-%@\n", moduleInfo->mModuleName, section.mName.c_str(), (moduleInfo->mSectionContrib.mSize) / 1024.0f,
|
||||
coff->GetSectionAddr(moduleInfo->mSectionContrib.mSection, moduleInfo->mSectionContrib.mOffset),
|
||||
coff->GetSectionAddr(moduleInfo->mSectionContrib.mSection, moduleInfo->mSectionContrib.mOffset + moduleInfo->mSectionContrib.mSize));
|
||||
totalContrib += moduleInfo->mSectionContrib.mSize;
|
||||
}
|
||||
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
|
||||
result += "\n";
|
||||
|
||||
addr_target minAddr = 0;
|
||||
Array<DbgCompileUnitContrib*> contribs;
|
||||
for (auto itr = mDebugTarget->mContribMap.begin(); itr != mDebugTarget->mContribMap.end(); ++itr)
|
||||
{
|
||||
auto contrib = *itr;
|
||||
if (contrib->mDbgModule != coff)
|
||||
continue;
|
||||
|
||||
if (contrib->mAddress < minAddr)
|
||||
continue;
|
||||
|
||||
minAddr = contrib->mAddress + contrib->mLength;
|
||||
|
||||
auto section = &coff->mSectionHeaders[contrib->mSection - 1];
|
||||
if (section->mSizeOfRawData <= 0)
|
||||
continue;
|
||||
|
||||
contribs.Add(contrib);
|
||||
}
|
||||
contribs.Sort([](DbgCompileUnitContrib* lhs, DbgCompileUnitContrib* rhs)
|
||||
{
|
||||
return lhs->mLength > rhs->mLength;
|
||||
});
|
||||
|
||||
totalContrib = 0;
|
||||
result += "Contribs:\n";
|
||||
for (auto contrib : contribs)
|
||||
{
|
||||
auto cvModule = coff->mCvModuleInfo[contrib->mCompileUnitId];
|
||||
auto section = &coff->mSectionHeaders[contrib->mSection - 1];
|
||||
result += StrFormat("\t%s\t%s\t%0.2fk\t%@\n", cvModule->mModuleName, section->mName, (contrib->mLength)/1024.0f, contrib->mAddress);
|
||||
totalContrib += contrib->mLength;
|
||||
}
|
||||
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
|
||||
result += "\n";
|
||||
|
||||
struct SymbolEntry
|
||||
{
|
||||
const char* mName;
|
||||
addr_target mAddress;
|
||||
int mSize;
|
||||
};
|
||||
Array<SymbolEntry> symbolEntries;
|
||||
|
||||
for (auto symbol : mDebugTarget->mSymbolMap)
|
||||
{
|
||||
if (symbol->mDbgModule != coff)
|
||||
continue;
|
||||
|
||||
if (!symbolEntries.IsEmpty())
|
||||
{
|
||||
auto lastSymbol = &symbolEntries.back();
|
||||
if (lastSymbol->mSize == 0)
|
||||
lastSymbol->mSize = symbol->mAddress - lastSymbol->mAddress;
|
||||
}
|
||||
|
||||
SymbolEntry symbolEntry;
|
||||
symbolEntry.mName = symbol->mName;
|
||||
symbolEntry.mAddress = symbol->mAddress;
|
||||
symbolEntry.mSize = 0;
|
||||
symbolEntries.Add(symbolEntry);
|
||||
}
|
||||
if (!symbolEntries.IsEmpty())
|
||||
{
|
||||
auto lastSymbol = &symbolEntries.back();
|
||||
for (auto contrib : contribs)
|
||||
{
|
||||
if ((lastSymbol->mAddress >= contrib->mAddress) && (lastSymbol->mAddress < contrib->mAddress + contrib->mLength))
|
||||
{
|
||||
lastSymbol->mSize = (contrib->mAddress + contrib->mLength) - lastSymbol->mAddress;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
symbolEntries.Sort([](const SymbolEntry& lhs, const SymbolEntry& rhs)
|
||||
{
|
||||
return lhs.mSize > rhs.mSize;
|
||||
});
|
||||
|
||||
totalContrib = 0;
|
||||
result += "Symbols:\n";
|
||||
for (auto symbolEntry : symbolEntries)
|
||||
{
|
||||
result += StrFormat("\t%s\t%0.2fk\t%@\n", symbolEntry.mName, (symbolEntry.mSize) / 1024.0f, symbolEntry.mAddress);
|
||||
totalContrib += symbolEntry.mSize;
|
||||
}
|
||||
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
|
||||
result += "\n";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
totalContrib = 0;
|
||||
result += "Static Variables:\n";
|
||||
for (auto& variable : coff->mStaticVariables)
|
||||
{
|
||||
result += StrFormat("\t%s\t%0.2fk\n", variable->mName, (variable->mType->GetByteCount()) / 1024.0f);
|
||||
totalContrib += variable->mType->GetByteCount();
|
||||
}
|
||||
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
|
||||
result += "\n";
|
||||
|
||||
totalContrib = 0;
|
||||
result += "Methods:\n";
|
||||
Array<DbgSubprogram*> methods;
|
||||
for (int typeIdx = 0; typeIdx < coff->mTypes.mSize; typeIdx++)
|
||||
{
|
||||
auto type = coff->mTypes[typeIdx];
|
||||
type->PopulateType();
|
||||
for (auto method : type->mMethodList)
|
||||
methods.Add(method);
|
||||
}
|
||||
for (auto compileUnit : dbgModule->mCompileUnits)
|
||||
{
|
||||
for (auto method : compileUnit->mOrphanMethods)
|
||||
methods.Add(method);
|
||||
}
|
||||
methods.Sort([](DbgSubprogram* lhs, DbgSubprogram* rhs)
|
||||
{
|
||||
return lhs->GetByteCount() > rhs->GetByteCount();
|
||||
});
|
||||
for (auto method : methods)
|
||||
{
|
||||
int methodSize = method->GetByteCount();
|
||||
if (methodSize <= 0)
|
||||
continue;
|
||||
auto name = method->ToString();
|
||||
result += StrFormat("\t%s\t%0.2fk\n", name.c_str(), methodSize / 1024.0f);
|
||||
totalContrib += methodSize;
|
||||
}
|
||||
|
||||
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
|
||||
result += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void WinDebugger::CancelSymSrv()
|
||||
{
|
||||
AutoCrit autoCrit(mDebugManager->mCritSect);
|
||||
|
|
|
@ -656,6 +656,7 @@ public:
|
|||
virtual String GetCurrentException() override;
|
||||
virtual void SetAliasPath(const StringImpl& origPath, const StringImpl& localPath) override;
|
||||
virtual String GetModulesInfo() override;
|
||||
virtual String GetModuleInfo(const StringImpl& moduleName) override;
|
||||
virtual void CancelSymSrv() override;
|
||||
virtual bool HasPendingDebugLoads() override;
|
||||
virtual int LoadImageForModule(const StringImpl& moduleName, const StringImpl& debugFileName) override;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
@ECHO --------------------------- Beef Test_Build.Bat Version 1 ---------------------------
|
||||
|
||||
@SET P4_CHANGELIST=%1
|
||||
|
@ -33,6 +32,20 @@ IDE\Tests\SysMSVCRT\build\Debug_Win64\SysMSVCRT\SysMSVCRT.exe 1000 234
|
|||
IDE\dist\BeefBuild_d -proddir=BeefLibs\corlib -test
|
||||
@IF %ERRORLEVEL% NEQ 0 GOTO HADERROR
|
||||
|
||||
@ECHO Building Tiny
|
||||
bin\RunWithStats IDE\dist\BeefBuild -proddir=IDE\Tests\Tiny -clean -config=Release
|
||||
set size=0
|
||||
FOR /F "usebackq" %%A IN ('IDE\Tests\Tiny\build\Release_Win64\Tiny\Tiny.exe') DO set size=%%~zA
|
||||
echo Tiny executable size: %size% (expected 13824, max 16000)
|
||||
if %size% LSS 10000 (
|
||||
echo TINY executable not found?
|
||||
goto :HADERROR
|
||||
)
|
||||
if %size% GTR 16000 (
|
||||
echo TINY executable is too large!
|
||||
goto :HADERROR
|
||||
)
|
||||
|
||||
@ECHO Building BeefIDE_d with BeefBuild_d
|
||||
bin\RunAndWait IDE\dist\BeefPerf.exe -cmd="Nop()"
|
||||
@IF %ERRORLEVEL% NEQ 0 GOTO FAILPERF_START
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue