1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Extensive runtime refactor to reduce generated executable sizes

This commit is contained in:
Brian Fiete 2024-03-16 07:23:29 -04:00
parent 4e750a7e1a
commit ddd9b1b218
74 changed files with 2514 additions and 717 deletions

View file

@ -15,12 +15,8 @@ namespace FMOD
*/ */
public class VERSION public class VERSION
{ {
public const int32 number = 0x00010803; public const int32 number = 0x00020220;
#if BF_64_BIT
public const String dll = "fmod64.dll";
#else
public const String dll = "fmod.dll"; public const String dll = "fmod.dll";
#endif
} }
public class CONSTANTS 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 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 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 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 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 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. */ 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; RESULT result = RESULT.OK;
int rawPtr = 0; int rawPtr = 0;
result = FMOD_System_Create(out rawPtr); result = FMOD_System_Create(out rawPtr, VERSION.number);
if (result != RESULT.OK) if (result != RESULT.OK)
{ {
return result; return result;
@ -1602,7 +1598,7 @@ namespace FMOD
#region importfunctions #region importfunctions
[Import(VERSION.dll), CLink, CallingConvention(.Stdcall)] [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 #endregion
} }
@ -2008,6 +2004,7 @@ namespace FMOD
stringData = name.CStr(); stringData = name.CStr();
exinfo.cbsize = (int32)sizeof(CREATESOUNDEXINFO); exinfo.cbsize = (int32)sizeof(CREATESOUNDEXINFO);
//int offset = offsetof(CREATESOUNDEXINFO, channelmask);
int soundraw; int soundraw;
RESULT result = FMOD_System_CreateSound(rawPtr, stringData, mode, ref exinfo, out soundraw); RESULT result = FMOD_System_CreateSound(rawPtr, stringData, mode, ref exinfo, out soundraw);

View file

@ -172,6 +172,12 @@ namespace System
} }
[AttributeUsage(.MemberAccess)]
public struct NoStaticCtorAttribute : Attribute
{
}
[AttributeUsage(.Block)] [AttributeUsage(.Block)]
public struct ConstSkipAttribute : Attribute public struct ConstSkipAttribute : Attribute

View file

@ -13,8 +13,38 @@ namespace System
CtrlBreak CtrlBreak
} }
static Encoding InputEncoding = Encoding.ASCII; public struct CancelInfo
static Encoding OutputEncoding = Encoding.ASCII; {
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 sForegroundColor = .White;
static ConsoleColor sBackgroundColor = .Black; static ConsoleColor sBackgroundColor = .Black;
@ -22,9 +52,6 @@ namespace System
static readonly ConsoleColor sOriginalForegroundColor = sForegroundColor; static readonly ConsoleColor sOriginalForegroundColor = sForegroundColor;
static readonly ConsoleColor sOriginalBackgroundColor = sBackgroundColor; static readonly ConsoleColor sOriginalBackgroundColor = sBackgroundColor;
static Event<delegate void (CancelKind cancelKind, ref bool terminate)> sOnCancel ~ _.Dispose();
static bool sCancelEventRegistered;
public static ConsoleColor ForegroundColor public static ConsoleColor ForegroundColor
{ {
get { return sForegroundColor; } 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 public static ref Event<delegate void (CancelKind cancelKind, ref bool terminate)> OnCancel
{ {
get get
{ {
if (!sCancelEventRegistered) if (!CancelInfo.sCancelEventRegistered)
{ {
sCancelEventRegistered = true; CancelInfo.sCancelEventRegistered = true;
#if BF_PLATFORM_WINDOWS #if BF_PLATFORM_WINDOWS
SetConsoleCtrlHandler(=> ConsoleCtrlHandler, true); SetConsoleCtrlHandler(=> ConsoleCtrlHandler, true);
#endif #endif
} }
return ref sOnCancel; return ref CancelInfo.sOnCancel;
} }
} }
@ -77,7 +125,7 @@ namespace System
{ {
bool terminate = true; bool terminate = true;
if ((ctrlType == 0) || (ctrlType == 1)) if ((ctrlType == 0) || (ctrlType == 1))
sOnCancel((.)ctrlType, ref terminate); CancelInfo.sOnCancel((.)ctrlType, ref terminate);
return terminate ? false : true; return terminate ? false : true;
} }
@ -286,7 +334,7 @@ namespace System
public static void Write(StringView line) public static void Write(StringView line)
{ {
Out.Write(line).IgnoreError(); OutString(line);
} }
public static void Write(StringView fmt, params Object[] args) public static void Write(StringView fmt, params Object[] args)
@ -308,12 +356,13 @@ namespace System
public static void WriteLine() public static void WriteLine()
{ {
Out.Write("\n").IgnoreError(); OutString("\n");
} }
public static void WriteLine(StringView line) public static void WriteLine(StringView line)
{ {
Out.WriteLine(line).IgnoreError(); OutString(line);
OutString("\n");
} }
public static void WriteLine(StringView fmt, params Object[] args) public static void WriteLine(StringView fmt, params Object[] args)

View file

@ -14,7 +14,14 @@ namespace System.Diagnostics.Contracts
Assume, Assume,
} }
#if !BF_RUNTIME_DISABLE
static extern void ReportFailure(ContractFailureKind failureKind, char8* userMessage, int32 userMessageLen, char8* conditionText, int32 conditionTextLen); 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> /// <summary>
/// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly. /// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly.

View file

@ -9,10 +9,16 @@ namespace System.Diagnostics
{ {
if (!condition) 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; 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); Internal.FatalError(failStr, 1);
#else
Internal.FatalError("Assert failed", 1);
#endif
} }
} }
@ -21,7 +27,9 @@ namespace System.Diagnostics
#endif #endif
public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum) 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); Internal.FatalError(failStr, 1);
} }
@ -87,7 +95,7 @@ namespace System.Diagnostics
} }
static bool gIsDebuggerPresent = IsDebuggerPresent; static bool gIsDebuggerPresent = IsDebuggerPresent;
[LinkName("IsDebuggerPresent"), CallingConvention(.Stdcall)] [LinkName("IsDebuggerPresent"), CallingConvention(.Stdcall), Import("kernel32.lib")]
static extern int32 Internal_IsDebuggerPresent(); static extern int32 Internal_IsDebuggerPresent();
public static bool IsDebuggerPresent public static bool IsDebuggerPresent

View file

@ -199,7 +199,11 @@ namespace System
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern int32 ftoa(float val, char8* str); static extern int32 ftoa(float val, char8* str);
#if !BF_RUNTIME_DISABLE
static extern int32 ToString(double val, char8* str, bool roundTrip); 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) public override void ToString(String strBuffer)
{ {

View file

@ -1,6 +1,7 @@
using System.IO; using System.IO;
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using System.Threading;
namespace System namespace System
{ {
@ -12,7 +13,23 @@ namespace System
public static readonly String NewLine = "\n"; public static readonly String NewLine = "\n";
#endif // BF_PLATFORM_WINDOWS #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; public static void* ModuleHandle => Internal.[Friend]sModuleHandle;

View file

@ -147,7 +147,11 @@ namespace System
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
static extern int32 ftoa(float val, char8* str); static extern int32 ftoa(float val, char8* str);
#if !BF_RUNTIME_DISABLE
static extern int32 ToString(float val, char8* str, bool roundTrip); 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) public override void ToString(String strBuffer)
{ {

View file

@ -91,7 +91,7 @@ namespace System
#endif #endif
} }
#if BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC #if (BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC) && !BF_RUNTIME_DISABLE
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public extern static void Report(); public extern static void Report();
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]

View file

@ -13,6 +13,14 @@ namespace System
case InvalidChar(int partialResult); 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 MaxValue = (sizeof(int) == 8) ? 0x7FFFFFFFFFFFFFFFL : 0x7FFFFFFF;
public const int MinValue = (sizeof(int) == 8) ? -0x8000000000000000L : -0x80000000; public const int MinValue = (sizeof(int) == 8) ? -0x8000000000000000L : -0x80000000;

View file

@ -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) public void ToString(String outString, String format, IFormatProvider formatProvider)
{ {
if(format == null || format.IsEmpty) if(format == null || format.IsEmpty)

View file

@ -81,12 +81,6 @@ namespace System
public static extern Object UnsafeCastToObject(void* ptr); public static extern Object UnsafeCastToObject(void* ptr);
[Intrinsic("cast")] [Intrinsic("cast")]
public static extern void* UnsafeCastToPtr(Object obj); 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")] [Intrinsic("memcpy")]
public static extern void MemCpy(void* dest, void* src, int length, int32 align = 1, bool isVolatile = false); public static extern void MemCpy(void* dest, void* src, int length, int32 align = 1, bool isVolatile = false);
[Intrinsic("memmove")] [Intrinsic("memmove")]
@ -103,6 +97,32 @@ namespace System
public static extern void StdFree(void* ptr); public static extern void StdFree(void* ptr);
[Intrinsic("returnaddress")] [Intrinsic("returnaddress")]
public static extern void* GetReturnAddress(int32 level = 0); 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)] [CallingConvention(.Cdecl)]
public static extern void* VirtualAlloc(int size, bool canExecute, bool canWrite); public static extern void* VirtualAlloc(int size, bool canExecute, bool canWrite);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
@ -160,25 +180,236 @@ namespace System
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern void Dbg_RawFree(void* ptr); public static extern void Dbg_RawFree(void* ptr);
[CallingConvention(.Cdecl), AlwaysInclude]
static extern void Shutdown();
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
static extern void Test_Init(char8* testData); static extern void Shutdown_Internal();
[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; [CallingConvention(.Cdecl), AlwaysInclude]
[AlwaysInclude] static void Shutdown()
static void SetModuleHandle(void* handle)
{ {
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] [AlwaysInclude]
static void AddRtFlags(int32 flags) static void AddRtFlags(int32 flags)
{ {
@ -254,9 +485,9 @@ namespace System
} }
} }
[AlwaysInclude]
public static String[] CreateParamsArray() public static String[] CreateParamsArray()
{ {
#if !BF_RUNTIME_DISABLE
char8* cmdLine = GetCommandLineArgs(); char8* cmdLine = GetCommandLineArgs();
//Windows.MessageBoxA(default, scope String()..AppendF("CmdLine: {0}", StringView(cmdLine)), "HI", 0); //Windows.MessageBoxA(default, scope String()..AppendF("CmdLine: {0}", StringView(cmdLine)), "HI", 0);
@ -357,9 +588,11 @@ namespace System
} }
return strVals; return strVals;
#else
return new String[0];
#endif
} }
[AlwaysInclude]
public static void DeleteStringArray(String[] arr) public static void DeleteStringArray(String[] arr)
{ {
for (var str in arr) for (var str in arr)
@ -367,8 +600,10 @@ namespace System
delete arr; delete arr;
} }
#if !BF_RUNTIME_DISABLE
extern static this(); extern static this();
extern static ~this(); extern static ~this();
#endif
} }
struct CRTAlloc struct CRTAlloc

View file

@ -224,6 +224,7 @@ namespace System
return intPart; return intPart;
} }
#if !BF_RUNTIME_DISABLE
public static extern float Sqrt(float f); public static extern float Sqrt(float f);
public static extern double Sqrt(double d); public static extern double Sqrt(double d);
public static extern float Cbrt(float f); public static extern float Cbrt(float f);
@ -236,6 +237,20 @@ namespace System
public static extern double Exp(double d); public static extern double Exp(double d);
public static extern float Pow(float x, float y); public static extern float Pow(float x, float y);
public static extern double Pow(double x, double 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) public static float IEEERemainder(float x, float y)
{ {

View file

@ -1130,12 +1130,14 @@ namespace System
// Hexadecimal digits representation. // Hexadecimal digits representation.
private static uint32 FastToDecHex (int32 val) private static uint32 FastToDecHex (int32 val)
{ {
var decHexDigits = DecHexDigits;
if (val < 100) if (val < 100)
return (uint32)DecHexDigits [val]; return (uint32)decHexDigits[val];
// Uses 2^19 (524288) to compute val / 100 for val < 10000. // Uses 2^19 (524288) to compute val / 100 for val < 10000.
int32 v = (val * 5243) >> 19; 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 // Helper to translate an int in the range 0 .. 99999999 to its
@ -1741,6 +1743,31 @@ namespace System
inst.IntegerToString(format, fp, outString); 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) public static void NumberToString (StringView format, int32 value, IFormatProvider fp, String outString)
{ {
NumberFormatter inst = GetInstance!(fp); NumberFormatter inst = GetInstance!(fp);

View file

@ -14,6 +14,7 @@ namespace System
ClassVData* mClassVData; ClassVData* mClassVData;
#endif #endif
[AlwaysInclude]
public virtual ~this() public virtual ~this()
{ {
#if BF_ENABLE_OBJECT_DEBUG_FLAGS #if BF_ENABLE_OBJECT_DEBUG_FLAGS
@ -47,42 +48,79 @@ namespace System
if (Compiler.IsComptime) if (Compiler.IsComptime)
return Comptime_GetType(); return Comptime_GetType();
Type type; ClassVData* classVData;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS #if BF_ENABLE_OBJECT_DEBUG_FLAGS
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF); classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
type = maskedVData.mType;
#else #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 #endif
if ((type.[Friend]mTypeFlags & TypeFlags.Boxed) != 0)
{
//int32 underlyingType = (int32)((TypeInstance)type).mUnderlyingType;
type = Type.[Friend]GetType(((TypeInstance)type).[Friend]mUnderlyingType);
}
return type; 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] [NoShow]
Type RawGetType() Type RawGetType()
{ {
if (Compiler.IsComptime) if (Compiler.IsComptime)
return Comptime_GetType(); return Comptime_GetType();
Type type; ClassVData* classVData;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS #if BF_ENABLE_OBJECT_DEBUG_FLAGS
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF); classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
type = maskedVData.mType;
#else #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 #endif
return type; 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 #if BF_DYNAMIC_CAST_CHECK || BF_ENABLE_REALTIME_LEAK_CHECK
[NoShow] [NoShow]
public virtual Object DynamicCastToTypeId(int32 typeId) public virtual Object DynamicCastToTypeId(int32 typeId)
{ {
if (typeId == (int32)RawGetType().[Friend]mTypeId) if (typeId == (.)RawGetTypeId())
return this; return this;
return null; return null;
} }
@ -101,6 +139,10 @@ namespace System
public virtual void ToString(String strBuffer) 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(); let t = RawGetType();
if (t.IsBoxedStructPtr) if (t.IsBoxedStructPtr)
{ {
@ -108,13 +150,15 @@ namespace System
let innerPtr = *(void**)((uint8*)Internal.UnsafeCastToPtr(this) + ti.[Friend]mMemberDataOffset); let innerPtr = *(void**)((uint8*)Internal.UnsafeCastToPtr(this) + ti.[Friend]mMemberDataOffset);
strBuffer.Append("("); strBuffer.Append("(");
ti.UnderlyingType.GetFullName(strBuffer); 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; return;
} }
t.GetFullName(strBuffer); t.GetFullName(strBuffer);
strBuffer.Append("@0x"); strBuffer.Append("@0x");
NumberFormatter.AddrToString((uint)Internal.UnsafeCastToPtr(this), strBuffer);
((int)Internal.UnsafeCastToPtr(this)).ToString(strBuffer, "A", null); #endif
} }
private static void ToString(Object obj, String strBuffer) private static void ToString(Object obj, String strBuffer)

View file

@ -78,7 +78,7 @@ namespace System
public uint32 dwFileDateLS; // e.g. 0 public uint32 dwFileDateLS; // e.g. 0
} }
[CLink, CallingConvention(.Stdcall)] [Import("kernel32.lib"), CLink, CallingConvention(.Stdcall)]
extern static bool GetVersionExA(OSVersionInfoExA* lpVersionInformation); extern static bool GetVersionExA(OSVersionInfoExA* lpVersionInformation);
[CLink, CallingConvention(.Stdcall)] [CLink, CallingConvention(.Stdcall)]
@ -274,9 +274,9 @@ namespace System
String arch = Arch32; String arch = Arch32;
#endif #endif
if (Version.Revision == 0) 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 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 #elif BF_PLATFORM_LINUX
outVar.AppendF("{} {} (Version {}.{}.{})", PrettyName, Name, Version.Major, Version.Minor, Version.Revision); outVar.AppendF("{} {} (Version {}.{}.{})", PrettyName, Name, Version.Major, Version.Minor, Version.Revision);
#else // MACOS and ANDROID #else // MACOS and ANDROID

View file

@ -34,15 +34,29 @@ namespace System
NotEmpty NotEmpty
}; };
public struct BfpCritSect {}
public struct BfpSpawn {} public struct BfpSpawn {}
public struct BfpFile {} public struct BfpFile {}
public struct BfpFindFileData {} public struct BfpFindFileData {}
public struct BfpDynLib {} public struct BfpDynLib {}
public struct BfpEvent {};
public struct BfpFileWatcher {} public struct BfpFileWatcher {}
public struct BfpProcess {} public struct BfpProcess {}
public struct BfpTLS; 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 public enum BfpSystemResult : int32
{ {
@ -51,6 +65,7 @@ namespace System
TempFileError = (int)Result.TempFileError TempFileError = (int)Result.TempFileError
} }
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern uint32 BfpSystem_TickCount(); public static extern uint32 BfpSystem_TickCount();
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -107,6 +122,62 @@ namespace System
public static extern void BfpTLS_SetValue(BfpTLS* tls, void* value); public static extern void BfpTLS_SetValue(BfpTLS* tls, void* value);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern void* BfpTLS_GetValue(BfpTLS* tls); 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 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); public function void BfpDirectoryChangeFunc(BfpFileWatcher* watcher, void* userData, BfpFileChangeKind changeKind, char8* directory, char8* fileName, char8* oldName);
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern BfpFileWatcher* BfpFileWatcher_WatchDirectory(char8* path, BfpDirectoryChangeFunc callback, BfpFileWatcherFlags flags, void* userData, BfpFileResult* outResult); public static extern BfpFileWatcher* BfpFileWatcher_WatchDirectory(char8* path, BfpDirectoryChangeFunc callback, BfpFileWatcherFlags flags, void* userData, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern void BfpFileWatcher_Release(BfpFileWatcher* fileWatcher); 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 public enum BfpProcessResult : int32
{ {
@ -136,6 +213,7 @@ namespace System
InsufficientBuffer = (int)Result.InsufficientBuffer InsufficientBuffer = (int)Result.InsufficientBuffer
} }
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern bool BfpProcess_IsRemoteMachine(char8* machineName); public static extern bool BfpProcess_IsRemoteMachine(char8* machineName);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -150,6 +228,22 @@ namespace System
public static extern void BfpProcess_GetProcessName(BfpProcess* process, char8* outName, int32* inOutNameSize, BfpProcessResult* outResult); public static extern void BfpProcess_GetProcessName(BfpProcess* process, char8* outName, int32* inOutNameSize, BfpProcessResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern int32 BfpProcess_GetProcessId(BfpProcess* process); 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 public enum BfpSpawnFlags : int32
{ {
@ -181,6 +275,7 @@ namespace System
UnknownError = (int)Result.UnknownError UnknownError = (int)Result.UnknownError
}; };
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern BfpSpawn* BfpSpawn_Create(char8* targetPath, char8* args, char8* workingDir, char8* env, BfpSpawnFlags flags, BfpSpawnResult* outResult); public static extern BfpSpawn* BfpSpawn_Create(char8* targetPath, char8* args, char8* workingDir, char8* env, BfpSpawnFlags flags, BfpSpawnResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -205,6 +300,47 @@ namespace System
public static extern bool BfpCritSect_TryEnter(BfpCritSect* critSect, int32 waitMS); public static extern bool BfpCritSect_TryEnter(BfpCritSect* critSect, int32 waitMS);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern void BfpCritSect_Leave(BfpCritSect* critSect); 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 public enum BfpEventFlags : int32
{ {
@ -221,6 +357,7 @@ namespace System
BfpEventResult_NotSupported = (int)Result.NotSupported BfpEventResult_NotSupported = (int)Result.NotSupported
}; };
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern BfpEvent* BfpEvent_Create(BfpEventFlags flags); public static extern BfpEvent* BfpEvent_Create(BfpEventFlags flags);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -231,6 +368,46 @@ namespace System
public static extern void BfpEvent_Reset(BfpEvent* event, BfpEventResult* outResult); public static extern void BfpEvent_Reset(BfpEvent* event, BfpEventResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern bool BfpEvent_WaitFor(BfpEvent* event, int32 waitMS); 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 public enum BfpLibResult : int32
{ {
@ -239,6 +416,7 @@ namespace System
InsufficientBuffer = (int)Result.InsufficientBuffer InsufficientBuffer = (int)Result.InsufficientBuffer
}; };
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern BfpDynLib* BfpDynLib_Load(char8* fileName); public static extern BfpDynLib* BfpDynLib_Load(char8* fileName);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -247,6 +425,16 @@ namespace System
public static extern void BfpDynLib_GetFilePath(BfpDynLib* lib, char8* outPath, int32* inOutPathSize, BfpLibResult* outResult); public static extern void BfpDynLib_GetFilePath(BfpDynLib* lib, char8* outPath, int32* inOutPathSize, BfpLibResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern void* BfpDynLib_GetProcAddress(BfpDynLib* lib, char8* name); 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 public enum BfpFileResult : int32
{ {
@ -265,6 +453,7 @@ namespace System
NotEmpty = (int)Result.NotEmpty, NotEmpty = (int)Result.NotEmpty,
}; };
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern void BfpDirectory_Create(char8* name, BfpFileResult* outResult); public static extern void BfpDirectory_Create(char8* name, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -279,6 +468,22 @@ namespace System
public static extern bool BfpDirectory_Exists(char8* path); public static extern bool BfpDirectory_Exists(char8* path);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern void BfpDirectory_GetSysDirectory(BfpSysDirectoryKind sysDirKind, char8* outPath, int32* inOutPathLen, BfpFileResult* outResult); 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 public enum BfpFileCreateKind : int32
{ {
@ -347,6 +552,7 @@ namespace System
In In
} }
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern BfpFile* BfpFile_Create(char8* name, BfpFileCreateKind createKind, BfpFileCreateFlags createFlags, BfpFileAttributes createdFileAttrs, BfpFileResult* outResult); public static extern BfpFile* BfpFile_Create(char8* name, BfpFileCreateKind createKind, BfpFileCreateFlags createFlags, BfpFileAttributes createdFileAttrs, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -389,6 +595,50 @@ namespace System
public static extern void BfpFile_GetFullPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult); public static extern void BfpFile_GetFullPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern void BfpFile_GetActualPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult); 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 public enum BfpFindFileFlags : int32
{ {
@ -397,6 +647,7 @@ namespace System
Directories = 2, Directories = 2,
}; };
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern BfpFindFileData* BfpFindFileData_FindFirstFile(char8* path, BfpFindFileFlags flags, BfpFileResult* outResult); public static extern BfpFindFileData* BfpFindFileData_FindFirstFile(char8* path, BfpFindFileFlags flags, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -415,6 +666,26 @@ namespace System
public static extern int64 BfpFindFileData_GetFileSize(BfpFindFileData* findData); public static extern int64 BfpFindFileData_GetFileSize(BfpFindFileData* findData);
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
public static extern void BfpFindFileData_Release(BfpFindFileData* findData); 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 public enum BfpSysDirectoryKind : int32
{ {

View file

@ -18,7 +18,7 @@ namespace System
public override void ToString(String strBuffer) 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) public override void ToString(String strBuffer)
{ {
strBuffer.Append("("); strBuffer.Append("(");
typeof(T).GetFullName(strBuffer); typeof(T).ToString(strBuffer);
strBuffer.AppendF("*)0x{0:A}", (uint)(void*)mVal); strBuffer.AppendF("*)0x{0:A}", (UInt.Simple)(uint)(void*)mVal);
} }
} }
} }

View file

@ -1,9 +1,11 @@
using System.Threading; using System.Threading;
using System.Collections; 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 #define BF_DBG_RUNTIME
#endif #endif
using internal System.Threading.Thread;
namespace System namespace System
{ {
struct RuntimeFeatures struct RuntimeFeatures
@ -17,7 +19,7 @@ namespace System
{ {
const int32 cVersion = 10; const int32 cVersion = 10;
[CRepr, AlwaysInclude] [CRepr]
struct BfDebugMessageData struct BfDebugMessageData
{ {
enum MessageType : int32 enum MessageType : int32
@ -104,7 +106,7 @@ namespace System
struct BfRtCallbacks struct BfRtCallbacks
{ {
public static BfRtCallbacks sCallbacks = .(); public static BfRtCallbacks sCallbacks;
function void* (int size) mAlloc; function void* (int size) mAlloc;
function void (void* ptr) mFree; function void (void* ptr) mFree;
@ -115,7 +117,7 @@ namespace System
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId; function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
function void (Type type, String str) mType_GetFullName; function void (Type type, String str) mType_GetFullName;
function String () mString_Alloc; function String () mString_Alloc;
function char8* (String str) mString_ToCStr; function StringView (String str) mString_ToStringView;
function Object () mThread_Alloc; function Object () mThread_Alloc;
function Object () mThread_GetMainThread; function Object () mThread_GetMainThread;
function void (Object thread) mThread_ThreadProc; function void (Object thread) mThread_ThreadProc;
@ -178,7 +180,7 @@ namespace System
static void Type_GetFullName(Type type, String str) static void Type_GetFullName(Type type, String str)
{ {
#if BF_DBG_RUNTIME #if BF_DBG_RUNTIME
type.GetFullName(str); type.ToString(str);
#else #else
// //
#endif #endif
@ -189,9 +191,9 @@ namespace System
return new String(); return new String();
} }
static char8* String_ToCStr(String str) static StringView String_ToStringView(String str)
{ {
return str.CStr(); return str;
} }
static void GC_MarkAllStaticMembers() static void GC_MarkAllStaticMembers()
@ -219,39 +221,37 @@ namespace System
static void DebugMessageData_SetupError(char8* str, int32 stackWindbackCount) static void DebugMessageData_SetupError(char8* str, int32 stackWindbackCount)
{ {
#if !BF_RUNTIME_REDUCED
BfDebugMessageData.gBfDebugMessageData.SetupError(str, stackWindbackCount); BfDebugMessageData.gBfDebugMessageData.SetupError(str, stackWindbackCount);
#endif
} }
static void DebugMessageData_SetupProfilerCmd(char8* str) static void DebugMessageData_SetupProfilerCmd(char8* str)
{ {
#if !BF_RUNTIME_REDUCED
BfDebugMessageData.gBfDebugMessageData.SetupProfilerCmd(str); BfDebugMessageData.gBfDebugMessageData.SetupProfilerCmd(str);
#endif
} }
static void DebugMessageData_Fatal() static void DebugMessageData_Fatal()
{ {
#if !BF_RUNTIME_REDUCED
BfDebugMessageData.gBfDebugMessageData.Fatal(); BfDebugMessageData.gBfDebugMessageData.Fatal();
#endif
} }
static void DebugMessageData_Clear() static void DebugMessageData_Clear()
{ {
#if !BF_RUNTIME_REDUCED
BfDebugMessageData.gBfDebugMessageData.Clear(); 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; if (Runtime.CheckErrorHandler != null)
switch (StringView(kind)) return Runtime.CheckErrorHandler(kind, arg1, arg2, arg3);
{
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 0;
return (int32)Runtime.CheckErrorHandlers(error);
} }
public void Init() mut public void Init() mut
@ -264,7 +264,7 @@ namespace System
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId; mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;
mType_GetFullName = => Type_GetFullName; mType_GetFullName = => Type_GetFullName;
mString_Alloc = => String_Alloc; mString_Alloc = => String_Alloc;
mString_ToCStr = => String_ToCStr; mString_ToStringView = => String_ToStringView;
mGC_MarkAllStaticMembers = => GC_MarkAllStaticMembers; mGC_MarkAllStaticMembers = => GC_MarkAllStaticMembers;
mGC_CallRootCallbacks = => GC_CallRootCallbacks; mGC_CallRootCallbacks = => GC_CallRootCallbacks;
mGC_Shutdown = => GC_Shutdown; 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 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 AddCrashInfoFunc(void* func);
private static extern void Dbg_Init(int32 version, int32 flags, BfRtCallbacks* callbacks); private static extern void Dbg_Init(int32 version, int32 flags, BfRtCallbacks* callbacks);
private static extern void SetErrorString(char8* error); private static extern void SetErrorString(char8* error);
private static extern void* Dbg_GetCrashInfoFunc(); private static extern void* Dbg_GetCrashInfoFunc();
public static extern void SetCrashReportKind(RtCrashReportKind crashReportKind); 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 public enum RtCrashReportKind : int32
{ {
@ -359,18 +370,23 @@ namespace System
Fail Fail
} }
static struct ErrorHandlerData
{
public delegate ErrorHandlerResult ErrorHandler(ErrorStage stage, Error error); 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 RtFlags sExtraFlags;
static AllocWrapper<Monitor> sMonitor ~ _.Dispose();
static List<ErrorHandler> sErrorHandlers ~ DeleteContainerAndItems!(_);
static bool sInsideErrorHandler;
static bool sQueriedFeatures = false; static bool sQueriedFeatures = false;
static RuntimeFeatures sFeatures; static RuntimeFeatures sFeatures;
static function void() sThreadInit;
public static this() public static this()
{ {
#if !BF_RUNTIME_DISABLE
BfRtCallbacks.sCallbacks.Init(); BfRtCallbacks.sCallbacks.Init();
RtFlags flags = sExtraFlags; RtFlags flags = sExtraFlags;
@ -384,23 +400,36 @@ namespace System
flags |= .DebugAlloc; flags |= .DebugAlloc;
#endif #endif
Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks); Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks);
#if !BF_RUNTIME_REDUCED && BF_PLATFORM_WINDOWS
InitCrashCatcher((int32)flags);
#endif
#if BF_DBG_RUNTIME #if BF_DBG_RUNTIME
Dbg_Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks); Dbg_Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks);
#endif #endif
Thread.[Friend]Init(); if (sThreadInit != null)
sThreadInit();
#endif
} }
[NoReturn] [NoReturn]
public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum) 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); Internal.FatalError(failStr, 1);
#else
Internal.FatalError("Fatal error", 1);
#endif
} }
[NoReturn] [NoReturn]
public static void NotImplemented(String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum) 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); Internal.FatalError(failStr, 1);
} }
@ -408,60 +437,97 @@ namespace System
{ {
if (!condition) 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; 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); 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) if (Compiler.IsComptime)
return; return;
using (sMonitor.Val.Enter()) using (ErrorHandlerData.sMonitor.Val.Enter())
{ {
if (sErrorHandlers == null) if (CheckAssertError == null)
sErrorHandlers = new .(); {
sErrorHandlers.Add(handler); 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) if (Compiler.IsComptime)
return .Ok; return .Ok;
using (sMonitor.Val.Enter()) using (ErrorHandlerData.sMonitor.Val.Enter())
{ {
if (sErrorHandlers.RemoveStrict(handler)) if (ErrorHandlerData.sErrorHandlers.RemoveStrict(handler))
return .Ok; return .Ok;
} }
return .Err; 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) if (Compiler.IsComptime)
return .ContinueFailure; return .ContinueFailure;
using (sMonitor.Val.Enter()) using (ErrorHandlerData.sMonitor.Val.Enter())
{ {
if (sInsideErrorHandler) if (ErrorHandlerData.sInsideErrorHandler)
return .ContinueFailure; return .ContinueFailure;
sInsideErrorHandler = true; ErrorHandlerData.sInsideErrorHandler = true;
defer { sInsideErrorHandler = false; } defer { ErrorHandlerData.sInsideErrorHandler = false; }
for (int pass = 0; pass < 2; pass++) for (int pass = 0; pass < 2; pass++)
{ {
int idx = (sErrorHandlers?.Count).GetValueOrDefault() - 1; int idx = (ErrorHandlerData.sErrorHandlers?.Count).GetValueOrDefault() - 1;
while (idx >= 0) 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); var result = handler((pass == 0) ? .PreFail : .Fail, error);
if (result == .Ignore) if (result == .Ignore)
{ {
@ -562,5 +628,122 @@ namespace System
[Intrinsic("xgetbv")] [Intrinsic("xgetbv")]
private static extern uint64 xgetbv(uint32 xcr); private static extern uint64 xgetbv(uint32 xcr);
#endif #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

View file

@ -330,7 +330,7 @@ namespace System
public override void ToString(String strBuffer) public override void ToString(String strBuffer)
{ {
strBuffer.Append("("); strBuffer.Append("(");
typeof(T).GetFullName(strBuffer); typeof(T).ToString(strBuffer);
strBuffer.AppendF("*)0x{0:A}[{1}]", (uint)(void*)mPtr, mLength); strBuffer.AppendF("*)0x{0:A}[{1}]", (uint)(void*)mPtr, mLength);
} }

View file

@ -10,6 +10,8 @@ using System.Threading;
using System.Interop; using System.Interop;
using System; using System;
using internal System.String;
namespace System namespace System
{ {
// String size type // String size type
@ -46,6 +48,13 @@ namespace System
NullTerminate = 1 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; int_strsize mLength;
uint_strsize mAllocSizeAndFlags; uint_strsize mAllocSizeAndFlags;
char8* mPtrOrBuffer = null; char8* mPtrOrBuffer = null;
@ -53,9 +62,6 @@ namespace System
extern const String* sStringLiterals; extern const String* sStringLiterals;
extern const String* sIdStringLiterals; extern const String* sIdStringLiterals;
static String* sPrevInternLinkPtr; // For detecting changes to sStringLiterals for hot loads 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 = ""; public const String Empty = "";
#if BF_LARGE_STRINGS #if BF_LARGE_STRINGS
@ -619,7 +625,6 @@ namespace System
String.Quote(Ptr, mLength, outString); String.Quote(Ptr, mLength, outString);
} }
[AlwaysInclude]
public char8* CStr() public char8* CStr()
{ {
EnsureNullTerminator(); EnsureNullTerminator();
@ -2846,15 +2851,15 @@ namespace System
String str = *(ptr++); String str = *(ptr++);
if (str == null) if (str == null)
break; break;
sInterns.Add(str); Interns.sInterns.Add(str);
} }
} }
public String Intern() 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)); String* internalLinkPtr = *((String**)(sStringLiterals));
if (internalLinkPtr != sPrevInternLinkPtr) if (internalLinkPtr != sPrevInternLinkPtr)
{ {
@ -2865,13 +2870,13 @@ namespace System
CheckLiterals(sStringLiterals); CheckLiterals(sStringLiterals);
String* entryPtr; String* entryPtr;
if (sInterns.TryAdd(this, out entryPtr)) if (Interns.sInterns.TryAdd(this, out entryPtr))
{ {
String result = new String(mLength + 1); String result = new String(mLength + 1);
result.Append(this); result.Append(this);
result.EnsureNullTerminator(); result.EnsureNullTerminator();
*entryPtr = result; *entryPtr = result;
sOwnedInterns.Add(result); Interns.sOwnedInterns.Add(result);
return result; return result;
} }
return *entryPtr; return *entryPtr;
@ -4256,9 +4261,9 @@ namespace System
public String Intern() 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)); String* internalLinkPtr = *((String**)(String.[Friend]sStringLiterals));
if (internalLinkPtr != String.[Friend]sPrevInternLinkPtr) if (internalLinkPtr != String.[Friend]sPrevInternLinkPtr)
{ {
@ -4269,13 +4274,13 @@ namespace System
String.[Friend]CheckLiterals(String.[Friend]sStringLiterals); String.[Friend]CheckLiterals(String.[Friend]sStringLiterals);
String* entryPtr; String* entryPtr;
if (String.[Friend]sInterns.TryAddAlt(this, out entryPtr)) if (String.Interns.sInterns.TryAddAlt(this, out entryPtr))
{ {
String result = new String(mLength + 1); String result = new String(mLength + 1);
result.Append(this); result.Append(this);
result.EnsureNullTerminator(); result.EnsureNullTerminator();
*entryPtr = result; *entryPtr = result;
String.[Friend]sOwnedInterns.Add(result); String.Interns.sOwnedInterns.Add(result);
return result; return result;
} }
return *entryPtr; return *entryPtr;
@ -4367,7 +4372,7 @@ namespace System
} }
#if TEST #if TEST
extension String class StringTest
{ {
[Test] [Test]
public static void Test_Intern() public static void Test_Intern()

View file

@ -70,7 +70,7 @@ namespace System
{ {
if (!condition) 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; return;
String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath); String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath);
Internal.[Friend]Test_Error(failStr); Internal.[Friend]Test_Error(failStr);

View file

@ -1,4 +1,5 @@
using System.Diagnostics; using System.Diagnostics;
using System.Threading;
namespace System.Text namespace System.Text
{ {
[StaticInitPriority(100)] [StaticInitPriority(100)]
@ -15,11 +16,39 @@ namespace System.Text
case PartialEncode(int inChars, int encodedBytes); case PartialEncode(int inChars, int encodedBytes);
} }
public static readonly ASCIIEncoding ASCII = new ASCIIEncoding() ~ delete _; static Encoding sASCII ~ delete _;
public static readonly UTF8Encoding UTF8 = new UTF8Encoding() ~ delete _; static Encoding sUTF8 ~ delete _;
public static readonly UTF8EncodingWithBOM UTF8WithBOM = new UTF8EncodingWithBOM() ~ delete _; static Encoding sUTF8WithBOM ~ delete _;
public static readonly UTF16Encoding UTF16 = new UTF16Encoding() ~ delete _; static Encoding sUTF16 ~ delete _;
public static readonly UTF16EncodingWithBOM UTF16WithBOM = new UTF16EncodingWithBOM() ~ 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 GetCharUnitSize();
public abstract int GetEncodedLength(char32 c); public abstract int GetEncodedLength(char32 c);

View file

@ -26,7 +26,7 @@ namespace System.Threading
static Event<delegate void()> sOnExit ~ _.Dispose(); static Event<delegate void()> sOnExit ~ _.Dispose();
Event<delegate void()> mOnExit ~ _.Dispose(); Event<delegate void()> mOnExit ~ _.Dispose();
public static Thread sMainThread = new Thread() ~ delete _; public static Thread sMainThread ~ delete _;
[StaticInitPriority(102)] [StaticInitPriority(102)]
struct RuntimeThreadInit struct RuntimeThreadInit
@ -48,8 +48,10 @@ namespace System.Threading
static void Thread_SetInternalThread(Object thread, void* internalThread) static void Thread_SetInternalThread(Object thread, void* internalThread)
{ {
#if BF_ENABLE_REALTIME_LEAK_CHECK
if (internalThread != null) if (internalThread != null)
GC.[Friend]AddPendingThread(internalThread); GC.[Friend]AddPendingThread(internalThread);
#endif
((Thread)thread).[Friend]mInternalThread = (int)internalThread; ((Thread)thread).[Friend]mInternalThread = (int)internalThread;
} }
@ -118,7 +120,18 @@ namespace System.Threading
cb.[Friend]mThread_AutoDelete = => Thread_AutoDelete; cb.[Friend]mThread_AutoDelete = => Thread_AutoDelete;
cb.[Friend]mThread_GetMaxStackSize = => Thread_GetMaxStackSize; cb.[Friend]mThread_GetMaxStackSize = => Thread_GetMaxStackSize;
cb.[Friend]mThread_Exiting = => Thread_Exiting; cb.[Friend]mThread_Exiting = => Thread_Exiting;
Runtime.[Friend, NoStaticCtor]sThreadInit = => Thread.Init;
} }
public static void Check()
{
}
}
public static this()
{
RuntimeThreadInit.Check();
} }
private this() private this()
@ -170,6 +183,7 @@ namespace System.Threading
{ {
#unwarn #unwarn
RuntimeThreadInit runtimeThreadInitRef = ?; RuntimeThreadInit runtimeThreadInitRef = ?;
sMainThread = new Thread();
sMainThread.ManualThreadInit(); 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) public void Start(bool autoDelete = true)
{ {
mAutoDelete = autoDelete; mAutoDelete = autoDelete;
@ -247,7 +256,7 @@ namespace System.Threading
StartInternal(); StartInternal();
} }
#if BF_PLATFORM_WINDOWS #if BF_PLATFORM_WINDOWS && !BF_RUNTIME_DISABLE
[CLink] [CLink]
static extern int32 _tls_index; static extern int32 _tls_index;
#endif #endif
@ -256,7 +265,7 @@ namespace System.Threading
{ {
get get
{ {
#if BF_PLATFORM_WINDOWS #if BF_PLATFORM_WINDOWS && !BF_RUNTIME_DISABLE
return _tls_index; return _tls_index;
#else #else
return 0; 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 public ThreadPriority Priority
{ {
get get
@ -283,12 +288,7 @@ namespace System.Threading
SetPriorityNative((int32)value); SetPriorityNative((int32)value);
} }
} }
[CallingConvention(.Cdecl)]
private extern int32 GetPriorityNative();
[CallingConvention(.Cdecl)]
private extern void SetPriorityNative(int32 priority);
extern bool GetIsAlive();
public bool IsAlive public bool IsAlive
{ {
get get
@ -297,8 +297,7 @@ namespace System.Threading
} }
} }
[CallingConvention(.Cdecl)]
extern bool GetIsThreadPoolThread();
public bool IsThreadPoolThread public bool IsThreadPoolThread
{ {
get get
@ -307,8 +306,6 @@ namespace System.Threading
} }
} }
private extern bool JoinInternal(int32 millisecondsTimeout);
public void Join() public void Join()
{ {
JoinInternal(Timeout.Infinite); JoinInternal(Timeout.Infinite);
@ -328,7 +325,6 @@ namespace System.Threading
return Join((int32)tm); return Join((int32)tm);
} }
private static extern void SleepInternal(int32 millisecondsTimeout);
public static void Sleep(int32 millisecondsTimeout) public static void Sleep(int32 millisecondsTimeout)
{ {
SleepInternal(millisecondsTimeout); SleepInternal(millisecondsTimeout);
@ -342,15 +338,11 @@ namespace System.Threading
Sleep((int32)tm); Sleep((int32)tm);
} }
private static extern void SpinWaitInternal(int32 iterations);
public static void SpinWait(int iterations) public static void SpinWait(int iterations)
{ {
SpinWaitInternal((int32)iterations); SpinWaitInternal((int32)iterations);
} }
private static extern bool YieldInternal();
public static bool Yield() public static bool Yield()
{ {
return YieldInternal(); return YieldInternal();
@ -364,9 +356,6 @@ namespace System.Threading
} }
} }
[CallingConvention(.Cdecl)]
extern int GetThreadId();
public int Id public int Id
{ {
get get
@ -377,9 +366,6 @@ namespace System.Threading
public static int CurrentThreadId => Platform.BfpThread_GetCurrentId(); public static int CurrentThreadId => Platform.BfpThread_GetCurrentId();
[CallingConvention(.Cdecl)]
private static extern Thread GetCurrentThreadNative();
void SetStart(Delegate ownStartDelegate, int32 maxStackSize) void SetStart(Delegate ownStartDelegate, int32 maxStackSize)
{ {
mDelegate = ownStartDelegate; mDelegate = ownStartDelegate;
@ -405,18 +391,11 @@ namespace System.Threading
delete mDelegate; delete mDelegate;
} }
[CallingConvention(.Cdecl)]
private extern void InternalFinalize();
public bool IsBackground public bool IsBackground
{ {
get { return IsBackgroundNative(); } get { return IsBackgroundNative(); }
set { SetBackgroundNative(value); } set { SetBackgroundNative(value); }
} }
[CallingConvention(.Cdecl)]
private extern bool IsBackgroundNative();
[CallingConvention(.Cdecl)]
private extern void SetBackgroundNative(bool isBackground);
public void SetJoinOnDelete(bool joinOnDelete) public void SetJoinOnDelete(bool joinOnDelete)
{ {
@ -427,8 +406,6 @@ namespace System.Threading
{ {
get { return (ThreadState)GetThreadStateNative(); } get { return (ThreadState)GetThreadStateNative(); }
} }
[CallingConvention(.Cdecl)]
private extern int32 GetThreadStateNative();
public void SetName(String name) public void SetName(String name)
{ {
@ -450,7 +427,63 @@ namespace System.Threading
if (mName != null) if (mName != null)
outName.Append(mName); outName.Append(mName);
} }
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
private extern void InformThreadNameChange(String name); 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
} }
} }

View file

@ -7,12 +7,15 @@ namespace System
{ {
struct ClassVData 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, // The rest of this structured is generated by the compiler,
// including the vtable and interface slots // including the vtable and interface slots
} }
[Ordered, AlwaysInclude(AssumeInstantiated=true)] [Ordered, AlwaysInclude, Reflect(.Type)]
public class Type public class Type
{ {
extern const Type* sTypes; extern const Type* sTypes;
@ -746,7 +749,12 @@ namespace System
public override void ToString(String strBuffer) public override void ToString(String strBuffer)
{ {
#if !BF_REFLECT_MINIMAL
GetFullName(strBuffer); GetFullName(strBuffer);
#else
strBuffer.Append("Type#");
mTypeId.ToString(strBuffer);
#endif
} }
public struct Enumerator : IEnumerator<Type> public struct Enumerator : IEnumerator<Type>
@ -890,6 +898,7 @@ namespace System.Reflection
public int32 mCustomAttributesIdx; public int32 mCustomAttributesIdx;
} }
[CRepr, AlwaysInclude]
public struct InterfaceData public struct InterfaceData
{ {
public TypeId mInterfaceType; public TypeId mInterfaceType;
@ -1272,7 +1281,7 @@ namespace System.Reflection
if (size == -1) if (size == -1)
strBuffer.Append("[?]"); strBuffer.Append("[?]");
else else
strBuffer.AppendF($"[{size}]"); strBuffer.AppendF($"[{(Int.Simple)size}]");
} }
} }
} }

View file

@ -11,6 +11,14 @@ namespace System
case InvalidChar(uint partialResult); 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 MaxValue = (sizeof(uint) == 8) ? 0xFFFFFFFFFFFFFFFFUL : 0xFFFFFFFFL;
public const uint MinValue = 0; public const uint MinValue = 0;

View file

@ -58,8 +58,6 @@ namespace System
} }
} }
static String sHexUpperChars = "0123456789ABCDEF";
static String sHexLowerChars = "0123456789abcdef";
public void ToString(String outString, String format, IFormatProvider formatProvider) public void ToString(String outString, String format, IFormatProvider formatProvider)
{ {
if(format == null || format.IsEmpty) if(format == null || format.IsEmpty)

View file

@ -90,7 +90,7 @@ namespace bf
bf::System::Object* (*Object_DynamicCastToTypeId)(bf::System::Object* obj, int typeId); bf::System::Object* (*Object_DynamicCastToTypeId)(bf::System::Object* obj, int typeId);
void(*Type_GetFullName)(System::Type* type, bf::System::String* str); void(*Type_GetFullName)(System::Type* type, bf::System::String* str);
bf::System::String* (*String_Alloc)(); 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_Alloc)();
bf::System::Threading::Thread* (*Thread_GetMainThread)(); bf::System::Threading::Thread* (*Thread_GetMainThread)();
void(*Thread_ThreadProc)(bf::System::Threading::Thread* thread); void(*Thread_ThreadProc)(bf::System::Threading::Thread* thread);
@ -116,6 +116,8 @@ namespace bf
private: private:
BFRT_EXPORT static void Init(int version, int flags, BfRtCallbacks* callbacks); 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 AddCrashInfoFunc(void* func);
BFRT_EXPORT static void SetErrorString(char* errorStr); BFRT_EXPORT static void SetErrorString(char* errorStr);
BFRT_EXPORT static void Dbg_Init(int version, int flags, BfRtCallbacks* callbacks); BFRT_EXPORT static void Dbg_Init(int version, int flags, BfRtCallbacks* callbacks);
@ -252,9 +254,9 @@ namespace bf
uint mAllocSizeAndFlags; uint mAllocSizeAndFlags;
char* mPtr; char* mPtr;
const char* CStr() Beefy::StringView ToStringView()
{ {
return BFRTCALLBACKS.String_ToCStr(this); return BFRTCALLBACKS.String_ToStringView(this);
} }
}; };
} }

View file

@ -52,6 +52,7 @@
USING_NS_BF; USING_NS_BF;
static Beefy::StringT<0> gCmdLineString; static Beefy::StringT<0> gCmdLineString;
bool gCmdLineStringHandled;
bf::System::Runtime::BfRtCallbacks gBfRtCallbacks; bf::System::Runtime::BfRtCallbacks gBfRtCallbacks;
BfRtFlags gBfRtFlags = (BfRtFlags)0; BfRtFlags gBfRtFlags = (BfRtFlags)0;
@ -65,7 +66,10 @@ static int gTestMethodIdx = -1;
static uint32 gTestStartTick = 0; static uint32 gTestStartTick = 0;
static bool gTestBreakOnFailure = false; static bool gTestBreakOnFailure = false;
typedef void(*ClientPipeErrorFunc)(const Beefy::StringView& error, int stackOffset);
static BfpFile* gClientPipe = NULL; static BfpFile* gClientPipe = NULL;
static ClientPipeErrorFunc gClientPipeErrorFunc;
static Beefy::String gTestInBuffer; static Beefy::String gTestInBuffer;
namespace bf namespace bf
@ -85,7 +89,7 @@ namespace bf
BFRT_EXPORT static void BfStaticCtor(); BFRT_EXPORT static void BfStaticCtor();
BFRT_EXPORT static void BfStaticDtor(); BFRT_EXPORT static void BfStaticDtor();
BFRT_EXPORT static void Shutdown(); BFRT_EXPORT static void Shutdown_Internal();
public: public:
BFRT_EXPORT static Object* UnsafeCastToObject(void* inPtr); BFRT_EXPORT static Object* UnsafeCastToObject(void* inPtr);
BFRT_EXPORT static void* UnsafeCastToPtr(Object* obj); BFRT_EXPORT static void* UnsafeCastToPtr(Object* obj);
@ -224,18 +228,8 @@ static void Internal_FatalError(const char* error)
if (gBfRtCallbacks.CheckErrorHandler != NULL) if (gBfRtCallbacks.CheckErrorHandler != NULL)
gBfRtCallbacks.CheckErrorHandler("FatalError", error, NULL, 0); gBfRtCallbacks.CheckErrorHandler("FatalError", error, NULL, 0);
if ((gClientPipe != NULL) && (!gTestBreakOnFailure)) if (gClientPipeErrorFunc != NULL)
{ gClientPipeErrorFunc(error, 0);
Beefy::String str = ":TestFatal\t";
str += error;
str.Replace('\n', '\r');
str += "\n";
TestString(str);
Beefy::String result;
TestReadCmd(result);
exit(1);
}
else else
BfpSystem_FatalError(error, "BEEF FATAL ERROR"); 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) if ((flags & 4) != 0)
sysInitFlags = (BfpSystemInitFlags)(sysInitFlags | BfpSystemInitFlag_SilentCrash); sysInitFlags = (BfpSystemInitFlags)(sysInitFlags | BfpSystemInitFlag_SilentCrash);
BfpSystem_Init(BFP_VERSION, sysInitFlags); BfpSystem_Init(BFP_VERSION, sysInitFlags);
BfpSystem_AddCrashInfoFunc(GetCrashInfo);
if (gBfRtCallbacks.Alloc != NULL) 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) 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; gBfRtCallbacks = *callbacks;
gBfRtFlags = (BfRtFlags)flags; 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 #ifdef BF_PLATFORM_WINDOWS
gBfTLSKey = FlsAlloc(TlsFreeFunc); gBfTLSKey = FlsAlloc(TlsFreeFunc);
#else #else
@ -362,6 +321,20 @@ void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
#endif #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) void bf::System::Runtime::SetErrorString(char* errorStr)
{ {
::SetErrorString(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(); BfInternalThread::WaitForAllDone();
if (gBfRtCallbacks.GC_Shutdown != NULL) if (gBfRtCallbacks.GC_Shutdown != NULL)
@ -419,20 +392,9 @@ void* Internal::UnsafeCastToPtr(Object* obj)
void Internal::ThrowIndexOutOfRange(intptr stackOffset) void Internal::ThrowIndexOutOfRange(intptr stackOffset)
{ {
if (gClientPipe != NULL) if (gClientPipeErrorFunc != NULL)
{ gClientPipeErrorFunc("Index out of range", 0);
if (gTestBreakOnFailure) else if ((stackOffset != -1) && (::IsDebuggerPresent()))
{
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()))
{ {
SETUP_ERROR("Index out of range", (int)(2 + stackOffset)); SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();
@ -443,20 +405,9 @@ void Internal::ThrowIndexOutOfRange(intptr stackOffset)
void Internal::ThrowObjectNotInitialized(intptr stackOffset) void Internal::ThrowObjectNotInitialized(intptr stackOffset)
{ {
if (gClientPipe != NULL) if (gClientPipeErrorFunc != NULL)
{ gClientPipeErrorFunc("Object not initialized", 0);
if (gTestBreakOnFailure) else if ((stackOffset != -1) && (::IsDebuggerPresent()))
{
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()))
{ {
SETUP_ERROR("Object not initialized", (int)(2 + stackOffset)); SETUP_ERROR("Object not initialized", (int)(2 + stackOffset));
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();
@ -467,29 +418,17 @@ void Internal::ThrowObjectNotInitialized(intptr stackOffset)
void Internal::FatalError(bf::System::String* error, intptr stackOffset) void Internal::FatalError(bf::System::String* error, intptr stackOffset)
{ {
if (gClientPipe != NULL) Beefy::StringView errorStringView = error->ToStringView();
{ Beefy::StringSimple errorString = errorStringView;
if (gTestBreakOnFailure) if (gClientPipeErrorFunc != NULL)
{ gClientPipeErrorFunc(errorStringView, 0);
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);
}
if ((stackOffset != -1) && (::IsDebuggerPresent())) if ((stackOffset != -1) && (::IsDebuggerPresent()))
{ {
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset)); SETUP_ERROR(errorString.c_str(), (int)(2 + stackOffset));
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();
} }
Internal_FatalError(error->CStr()); Internal_FatalError(errorString.c_str());
} }
void Internal::MemCpy(void* dest, void* src, intptr length) void Internal::MemCpy(void* dest, void* src, intptr length)
@ -630,6 +569,46 @@ void Internal::GetSharedProcAddressInto(void* libHandle, char* procName, void**
char* Internal::GetCommandLineArgs() 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(); 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) void Internal::Test_Init(char* testData)
{ {
BfpSystem_SetCrashReportKind(BfpCrashReportKind_None); BfpSystem_SetCrashReportKind(BfpCrashReportKind_None);
@ -708,6 +708,8 @@ void Internal::Test_Init(char* testData)
if (fileResult != BfpFileResult_Ok) if (fileResult != BfpFileResult_Ok)
BF_FATAL("Test_Init failed to create pipe to test manager"); BF_FATAL("Test_Init failed to create pipe to test manager");
gClientPipeErrorFunc = TestFailed;
Beefy::String outStr; Beefy::String outStr;
outStr += ":TestInit\n"; outStr += ":TestInit\n";
outStr += testData; outStr += testData;
@ -853,7 +855,6 @@ void Internal::ObjectDynCheck(bf::System::Object* object, int typeId, bool allow
if (result == NULL) if (result == NULL)
{ {
Beefy::String errorStr = "Attempting invalid cast on object"; 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); errorStr += StrFormat("\x1LEAK\t0x%@\n (%s)0x%@\n", object, "System.Object", object);
SETUP_ERROR(errorStr.c_str(), 2); SETUP_ERROR(errorStr.c_str(), 2);
BF_DEBUG_BREAK(); BF_DEBUG_BREAK();

View file

@ -7,7 +7,7 @@ Beefy::String bf::System::Object::GetTypeName()
String* strObj = BFRTCALLBACKS.String_Alloc(); String* strObj = BFRTCALLBACKS.String_Alloc();
Type* type = _GetType(); Type* type = _GetType();
BFRTCALLBACKS.Type_GetFullName(type, strObj); BFRTCALLBACKS.Type_GetFullName(type, strObj);
Beefy::String str = strObj->CStr(); Beefy::String str = strObj->ToStringView();
BFRTCALLBACKS.Object_Delete(strObj); BFRTCALLBACKS.Object_Delete(strObj);
return str; return str;
} }
@ -16,7 +16,7 @@ Beefy::String bf::System::Type::GetFullName()
{ {
String* strObj = BFRTCALLBACKS.String_Alloc(); String* strObj = BFRTCALLBACKS.String_Alloc();
BFRTCALLBACKS.Type_GetFullName(this, strObj); BFRTCALLBACKS.Type_GetFullName(this, strObj);
Beefy::String str = strObj->CStr(); Beefy::String str = strObj->ToStringView();
BFRTCALLBACKS.Object_Delete(strObj); BFRTCALLBACKS.Object_Delete(strObj);
return str; return str;
} }

View file

@ -318,7 +318,10 @@ int Thread::GetThreadStateNative()
void Thread::InformThreadNameChange(String* name) 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() void Thread::MemoryBarrier()

View file

@ -100,12 +100,14 @@ enum BfpCrashReportKind
}; };
BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flags); 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_SetCommandLine(int argc, char** argv);
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashReportKind(BfpCrashReportKind crashReportKind); BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashReportKind(BfpCrashReportKind crashReportKind);
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfoFunc(BfpCrashInfoFunc crashInfoFunc); 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_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_SetCrashRelaunchCmd(const char* str);
BFP_EXPORT void BFP_CALLTYPE BfpSystem_Shutdown(); BFP_EXPORT void BFP_CALLTYPE BfpSystem_Shutdown();
BFP_EXPORT void BFP_CALLTYPE BfpSystem_ShutdownCrashCatcher();
BFP_EXPORT uint32 BFP_CALLTYPE BfpSystem_TickCount(); BFP_EXPORT uint32 BFP_CALLTYPE BfpSystem_TickCount();
BFP_EXPORT BfpTimeStamp BFP_CALLTYPE BfpSystem_GetTimeStamp(); BFP_EXPORT BfpTimeStamp BFP_CALLTYPE BfpSystem_GetTimeStamp();
BFP_EXPORT uint16 BFP_CALLTYPE BfpSystem_EndianSwap16(uint16 val); BFP_EXPORT uint16 BFP_CALLTYPE BfpSystem_EndianSwap16(uint16 val);

View file

@ -52,7 +52,6 @@ static SYMGETMODULEBASEPROC gSymGetModuleBase = NULL;
static SYMGETSYMFROMADDRPROC gSymGetSymFromAddr = NULL; static SYMGETSYMFROMADDRPROC gSymGetSymFromAddr = NULL;
static SYMGETLINEFROMADDR gSymGetLineFromAddr = NULL; static SYMGETLINEFROMADDR gSymGetLineFromAddr = NULL;
static bool CreateMiniDump(EXCEPTION_POINTERS* pep, const StringImpl& filePath); static bool CreateMiniDump(EXCEPTION_POINTERS* pep, const StringImpl& filePath);
static bool LoadImageHelp() static bool LoadImageHelp()
@ -117,47 +116,6 @@ static bool LoadImageHelp()
return true; 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 gDebugButtonWindow = NULL;
static HWND gYesButtonWindow = NULL; static HWND gYesButtonWindow = NULL;
static HWND gNoButtonWindow = 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; gUseDefaultFonts = aVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT;
int aHeight = -MulDiv(8, 96, 72); 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, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, "Tahoma"); DEFAULT_PITCH | FF_DONTCARE, "Tahoma");
aHeight = -MulDiv(10, 96, 72); 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, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, "Tahoma"); DEFAULT_PITCH | FF_DONTCARE, "Tahoma");
::SetCursor(::LoadCursor(NULL, IDC_ARROW)); ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
gErrorTitle = errorTitle; String gErrorTitle = errorTitle;
gErrorText = errorText; String gErrorText = errorText;
WNDCLASSW wc; WNDCLASSW wc;
wc.style = 0; wc.style = 0;
@ -935,6 +893,44 @@ static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
/////////////////////////// ///////////////////////////
// first name the exception // 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; char *szName = NULL;
for (int i = 0; gMsgTable[i].dwExceptionCode != 0xFFFFFFFF; i++) for (int i = 0; gMsgTable[i].dwExceptionCode != 0xFFFFFFFF; i++)
{ {

View file

@ -39,9 +39,14 @@
USING_NS_BF; USING_NS_BF;
static void Crash_Error(const char* msg);
typedef void(*BfpCrashErrorFunc)(const char* str);
static bool gTimerInitialized = false; static bool gTimerInitialized = false;
static int gTimerDivisor = 0; static int gTimerDivisor = 0;
CritSect gBfpCritSect; CritSect gBfpCritSect;
BfpCrashErrorFunc gCrashErrorFunc = Crash_Error;
struct WindowsSharedInfo struct WindowsSharedInfo
{ {
@ -415,8 +420,9 @@ void Beefy::BFFatalError(const StringImpl& message, const StringImpl& file, int
gBFApp->mSysDialogCnt++; gBFApp->mSysDialogCnt++;
#endif #endif
String failMsg = StrFormat("%s in %s:%d", message.c_str(), file.c_str(), line); char* failMsg = new char[message.length() + file.length() + 64];
BfpSystem_FatalError(failMsg.c_str(), "FATAL ERROR"); sprintf(failMsg, "%s in %s:%d", message.c_str(), file.c_str(), line);
BfpSystem_FatalError(failMsg, "FATAL ERROR");
#ifndef BF_NO_BFAPP #ifndef BF_NO_BFAPP
if (gBFApp != NULL) if (gBFApp != NULL)
@ -906,6 +912,7 @@ static void __cdecl AbortHandler(int)
static int64 gCPUFreq = -1; static int64 gCPUFreq = -1;
static int64 gStartCPUTick = -1; static int64 gStartCPUTick = -1;
static int64 gStartQPF = -1; static int64 gStartQPF = -1;
static void(*sOldSIGABRTHandler)(int signal) = nullptr;
static void InitCPUFreq() 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) BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flags)
{ {
gCrashErrorFunc = Crash_Error;
InitCPUFreq(); InitCPUFreq();
::_set_error_mode(_OUT_TO_STDERR); ::_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) 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) if ((flags & BfpSystemInitFlag_InstallCrashCatcher) != 0)
@ -953,11 +983,15 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flag
sOldSIGABRTHandler = signal(SIGABRT, &AbortHandler); sOldSIGABRTHandler = signal(SIGABRT, &AbortHandler);
if (sOldSIGABRTHandler == SIG_ERR) if (sOldSIGABRTHandler == SIG_ERR)
sOldSIGABRTHandler = nullptr; sOldSIGABRTHandler = nullptr;
}
}
BFP_EXPORT void BFP_CALLTYPE BfpSystem_InitCrashCatcher(BfpSystemInitFlags flags)
{
CrashCatcher::Get()->Init(); CrashCatcher::Get()->Init();
if ((flags & BfpSystemInitFlag_SilentCrash) != 0) if ((flags & BfpSystemInitFlag_SilentCrash) != 0)
CrashCatcher::Get()->SetCrashReportKind(BfpCrashReportKind_None); CrashCatcher::Get()->SetCrashReportKind(BfpCrashReportKind_None);
} gCrashErrorFunc = Crash_Error_CrashHandler;
} }
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCommandLine(int argc, char** argv) BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCommandLine(int argc, char** argv)
@ -993,7 +1027,10 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_Shutdown()
delete gManagerTail; delete gManagerTail;
gManagerTail = next; gManagerTail = next;
} }
}
BFP_EXPORT void BFP_CALLTYPE BfpSystem_ShutdownCrashCatcher()
{
if (CrashCatcher::Shutdown()) if (CrashCatcher::Shutdown())
{ {
_set_purecall_handler(nullptr); _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) BFP_EXPORT void BFP_CALLTYPE BfpSystem_FatalError(const char* error, const char* title)
{ {
if (title != NULL) 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 else
CrashCatcher::Get()->Crash(error); gCrashErrorFunc(error);
} }
BFP_EXPORT void BFP_CALLTYPE BfpSystem_GetCommandLine(char* outStr, int* inOutStrSize, BfpSystemResult* outResult) 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); typedef BOOL(WINAPI* SETXSTATEFEATURESMASK)(PCONTEXT Context, DWORD64 FeatureMask);
static SETXSTATEFEATURESMASK pfnSetXStateFeaturesMask = NULL; static SETXSTATEFEATURESMASK pfnSetXStateFeaturesMask = NULL;
static uint8 ContextBuffer[4096]; static uint8* ContextBuffer;
static CONTEXT* CaptureRegistersEx(HANDLE hThread, intptr*& curPtr) static CONTEXT* CaptureRegistersEx(HANDLE hThread, intptr*& curPtr)
{ {
if (ContextBuffer == NULL)
ContextBuffer = new uint8[4096];
PCONTEXT Context; PCONTEXT Context;
DWORD ContextSize; DWORD ContextSize;
DWORD64 FeatureMask; DWORD64 FeatureMask;

View file

@ -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> class UTF16String : public Array<uint16>
{ {
public: public:

View file

@ -24,7 +24,7 @@ OtherLinkFlags = ""
TargetDirectory = "$(WorkspaceDir)/dist" TargetDirectory = "$(WorkspaceDir)/dist"
TargetName = "BeefIDE_d" TargetName = "BeefIDE_d"
OtherLinkFlags = "$(LinkFlags) Comdlg32.lib kernel32.lib user32.lib advapi32.lib shell32.lib IDEHelper64_d.lib" 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)\\.." DebugWorkingDirectory = "$(WorkspaceDir)\\.."
EnvironmentVars = ["_NO_DEBUG_HEAP=1"] EnvironmentVars = ["_NO_DEBUG_HEAP=1"]

View file

@ -0,0 +1,8 @@
FileVersion = 1
[Project]
Name = "Tiny"
StartupObject = "Tiny.Program"
[Configs.Release.Win64]
CLibType = "SystemMSVCRT"

View 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"

View file

@ -0,0 +1,13 @@
using System;
using System.Diagnostics;
namespace Tiny;
class Program
{
public static int Main()
{
Console.WriteLine("Hello, World!");
return 0;
}
}

View file

@ -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 /// 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. /// that the method applies extra runtime checks such as bounds checking or other parameter or state validation.
[AttributeUsage(.Invocation | .Method | .Property)] [AttributeUsage(.Invocation | .Method | .Property)]

View file

@ -92,8 +92,15 @@ namespace System
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
public static extern void Dbg_RawFree(void* ptr); public static extern void Dbg_RawFree(void* ptr);
[CallingConvention(.Cdecl)]
static extern void Shutdown_Internal();
[CallingConvention(.Cdecl), AlwaysInclude] [CallingConvention(.Cdecl), AlwaysInclude]
static extern void Shutdown(); static void Shutdown()
{
Shutdown_Internal();
}
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]
static extern void Test_Init(char8* testData); static extern void Test_Init(char8* testData);
[CallingConvention(.Cdecl)] [CallingConvention(.Cdecl)]

View file

@ -48,7 +48,7 @@ namespace System
class Object : IHashable class Object : IHashable
{ {
#if BF_ENABLE_OBJECT_DEBUG_FLAGS #if BF_ENABLE_OBJECT_DEBUG_FLAGS
int mClassVData; int mClassVData;
int mDbgAllocInfo; int mDbgAllocInfo;
#else #else
@ -62,46 +62,105 @@ namespace System
#endif #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() public Type GetType()
{ {
Type type; if (Compiler.IsComptime)
return Comptime_GetType();
ClassVData* classVData;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS #if BF_ENABLE_OBJECT_DEBUG_FLAGS
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF); classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
type = maskedVData.mType;
#else #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 #endif
if ((type.[Friend]mTypeFlags & TypeFlags.Boxed) != 0)
{
//int32 underlyingType = (int32)((TypeInstance)type).mUnderlyingType;
type = Type.[Friend]GetType(((TypeInstance)type).[Friend]mUnderlyingType);
}
return type; 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] [NoShow]
Type RawGetType() Type RawGetType()
{ {
Type type; if (Compiler.IsComptime)
return Comptime_GetType();
ClassVData* classVData;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS #if BF_ENABLE_OBJECT_DEBUG_FLAGS
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF); classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
type = maskedVData.mType;
#else #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 #endif
return type; 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 #if BF_DYNAMIC_CAST_CHECK || BF_ENABLE_REALTIME_LEAK_CHECK
[NoShow] [NoShow]
public virtual Object DynamicCastToTypeId(int32 typeId) public virtual Object DynamicCastToTypeId(int32 typeId)
{ {
if (typeId == (int32)RawGetType().[Friend]mTypeId) if (typeId == (.)RawGetTypeId())
return this; return this;
return null; return null;
} }
@ -113,10 +172,15 @@ namespace System
} }
#endif #endif
int IHashable.GetHashCode()
{
return (int)Internal.UnsafeCastToPtr(this);
}
public virtual void ToString(String strBuffer) public virtual void ToString(String strBuffer)
{ {
//strBuffer.Set(stack string(GetType().mName)); strBuffer.Append("Type#");
RawGetType().GetName(strBuffer); GetTypeId().ToString(strBuffer);
} }
/*public virtual int GetHashCode() /*public virtual int GetHashCode()

View file

@ -7,7 +7,10 @@ namespace System
{ {
struct ClassVData 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, // The rest of this structured is generated by the compiler,
// including the vtable and interface slots // including the vtable and interface slots
} }
@ -757,6 +760,7 @@ namespace System.Reflection
public int32 mCustomAttributesIdx; public int32 mCustomAttributesIdx;
} }
[CRepr, AlwaysInclude]
public struct InterfaceData public struct InterfaceData
{ {
public TypeId mInterfaceType; public TypeId mInterfaceType;

View file

@ -46,8 +46,8 @@ namespace Hey.Dude.Bro
[Import(@"C:\Beef\BeefTools\TestDLL\x64\Debug\TestDLL.dll"), LinkName("Test2")] //[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 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) public static Color GetColor(int32 a, int32 b)
{ {
@ -61,7 +61,9 @@ namespace Hey.Dude.Bro
public static int Main(String[] args) public static int Main(String[] args)
{ {
Test2(1, 2, 3, 4, => GetColor); Debug.WriteLine("Hey!");
//Test2(1, 2, 3, 4, => GetColor);
//Blurg.Hey(); //Blurg.Hey();
return 1; return 1;

View file

@ -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) 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 ((platformType == .Linux) || (platformType == .macOS) || (platformType == .iOS))
{ {
if (options.mBuildOptions.mBeefLibType == .DynamicDebug) if (options.mBuildOptions.mBeefLibType == .DynamicDebug)
@ -1059,10 +1062,13 @@ namespace IDE
return false; return false;
}*/ }*/
switch (options.mBuildOptions.mCLibType) var clibType = options.mBuildOptions.mCLibType;
if (workspaceOptions.mRuntimeKind == .Disabled)
clibType = .None;
switch (clibType)
{ {
case .None: case .None:
linkLine.Append("-nodefaultlib "); linkLine.Append("-nodefaultlib chkstk.obj ");
case .Dynamic: case .Dynamic:
//linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:msvcprt " : "-defaultlib:msvcrt "); //linkLine.Append((workspaceOptions.mMachineType == .x86) ? "-defaultlib:msvcprt " : "-defaultlib:msvcrt ");
linkLine.Append("-defaultlib:msvcrt "); linkLine.Append("-defaultlib:msvcrt ");

View file

@ -5,6 +5,7 @@ namespace IDE
{ {
class BuildOptions class BuildOptions
{ {
[Reflect(.All)]
public enum LTOType public enum LTOType
{ {
case None; case None;
@ -18,6 +19,7 @@ namespace IDE
} }
} }
[Reflect(.All)]
public enum EmitDebugInfo public enum EmitDebugInfo
{ {
No, No,
@ -25,6 +27,7 @@ namespace IDE
LinesOnly, LinesOnly,
} }
[Reflect(.All)]
public enum SIMDSetting public enum SIMDSetting
{ {
None, None,
@ -38,6 +41,7 @@ namespace IDE
AVX2, AVX2,
} }
[Reflect]
public enum BfOptimizationLevel public enum BfOptimizationLevel
{ {
case O0; case O0;
@ -53,6 +57,7 @@ namespace IDE
} }
} }
[Reflect]
public enum RelocType public enum RelocType
{ {
NotSet, NotSet,
@ -64,6 +69,7 @@ namespace IDE
ROPI_RWPI ROPI_RWPI
} }
[Reflect]
public enum PICLevel public enum PICLevel
{ {
NotSet, NotSet,
@ -72,6 +78,7 @@ namespace IDE
Big Big
} }
[Reflect]
public enum AlwaysIncludeKind public enum AlwaysIncludeKind
{ {
NotSet, NotSet,

View file

@ -739,9 +739,14 @@ namespace IDE.Compiler
SetOpt(options.mAllowHotSwapping, .EnableHotSwapping); SetOpt(options.mAllowHotSwapping, .EnableHotSwapping);
#endif #endif
var allocType = options.mAllocType;
if ((options.mRuntimeKind == .Disabled) && (allocType == .Debug))
allocType = .CRT;
String mallocLinkName; String mallocLinkName;
String freeLinkName; String freeLinkName;
switch (options.mAllocType) switch (allocType)
{ {
case .CRT: case .CRT:
mallocLinkName = "malloc"; mallocLinkName = "malloc";

View file

@ -366,6 +366,9 @@ namespace IDE.Debugger
[CallingConvention(.Stdcall),CLink] [CallingConvention(.Stdcall),CLink]
static extern char8* Debugger_GetModulesInfo(); static extern char8* Debugger_GetModulesInfo();
[CallingConvention(.Stdcall),CLink]
static extern char8* Debugger_GetModuleInfo(char8* moduleName);
[CallingConvention(.Stdcall),CLink] [CallingConvention(.Stdcall),CLink]
static extern bool Debugger_HasPendingDebugLoads(); static extern bool Debugger_HasPendingDebugLoads();
@ -1194,6 +1197,11 @@ namespace IDE.Debugger
modulesInfo.Append(Debugger_GetModulesInfo()); modulesInfo.Append(Debugger_GetModulesInfo());
} }
public void GetModuleInfo(StringView moduleName, String moduleInfo)
{
moduleInfo.Append(Debugger_GetModuleInfo(moduleName.ToScopeCStr!()));
}
public int32 LoadDebugInfoForModule(String moduleName) public int32 LoadDebugInfoForModule(String moduleName)
{ {
return Debugger_LoadDebugInfoForModule(moduleName); return Debugger_LoadDebugInfoForModule(moduleName);

View file

@ -8488,6 +8488,13 @@ namespace IDE
macroList.Add("BF_LARGE_COLLECTIONS"); 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 // Only supported on Windows at the moment
bool hasLeakCheck = false; bool hasLeakCheck = false;
if (workspaceOptions.LeakCheckingEnabled) if (workspaceOptions.LeakCheckingEnabled)

View file

@ -94,6 +94,12 @@ namespace IDE
BitcodeAndIRCode, BitcodeAndIRCode,
} }
public enum ReflectKind
{
Normal,
Minimal
}
public enum PlatformType public enum PlatformType
{ {
case Unknown; case Unknown;
@ -263,6 +269,13 @@ namespace IDE
Custom Custom
} }
public enum RuntimeKind
{
Default,
Reduced,
Disabled
}
public class BeefGlobalOptions public class BeefGlobalOptions
{ {
[Reflect] [Reflect]
@ -305,6 +318,10 @@ namespace IDE
[Reflect] [Reflect]
public bool mLargeCollections; public bool mLargeCollections;
[Reflect] [Reflect]
public RuntimeKind mRuntimeKind;
[Reflect]
public ReflectKind mReflectKind;
[Reflect]
public AllocType mAllocType = .CRT; public AllocType mAllocType = .CRT;
[Reflect] [Reflect]
public String mAllocMalloc = new String() ~ delete _; public String mAllocMalloc = new String() ~ delete _;
@ -352,7 +369,7 @@ namespace IDE
get get
{ {
#if BF_PLATFORM_WINDOWS #if BF_PLATFORM_WINDOWS
return mEnableRealtimeLeakCheck && mEnableObjectDebugFlags && (mAllocType == .Debug); return mEnableRealtimeLeakCheck && mEnableObjectDebugFlags && (mAllocType == .Debug) && (mRuntimeKind != .Disabled);
#else #else
return false; return false;
#endif #endif
@ -376,6 +393,8 @@ namespace IDE
mNoOmitFramePointers = prev.mNoOmitFramePointers; mNoOmitFramePointers = prev.mNoOmitFramePointers;
mLargeStrings = prev.mLargeStrings; mLargeStrings = prev.mLargeStrings;
mLargeCollections = prev.mLargeCollections; mLargeCollections = prev.mLargeCollections;
mRuntimeKind = prev.mRuntimeKind;
mReflectKind = prev.mReflectKind;
mAllocType = prev.mAllocType; mAllocType = prev.mAllocType;
mAllocMalloc.Set(prev.mAllocMalloc); mAllocMalloc.Set(prev.mAllocMalloc);
mAllocFree.Set(prev.mAllocFree); mAllocFree.Set(prev.mAllocFree);
@ -813,6 +832,8 @@ namespace IDE
data.ConditionalAdd("NoOmitFramePointers", options.mNoOmitFramePointers, false); data.ConditionalAdd("NoOmitFramePointers", options.mNoOmitFramePointers, false);
data.ConditionalAdd("LargeStrings", options.mLargeStrings, false); data.ConditionalAdd("LargeStrings", options.mLargeStrings, false);
data.ConditionalAdd("LargeCollections", options.mLargeCollections, 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("InitLocalVariables", options.mInitLocalVariables, false);
data.ConditionalAdd("RuntimeChecks", options.mRuntimeChecks, !isRelease); data.ConditionalAdd("RuntimeChecks", options.mRuntimeChecks, !isRelease);
data.ConditionalAdd("EmitDynamicCastCheck", options.mEmitDynamicCastCheck, !isRelease); data.ConditionalAdd("EmitDynamicCastCheck", options.mEmitDynamicCastCheck, !isRelease);
@ -1004,6 +1025,8 @@ namespace IDE
options.mNoOmitFramePointers = false; options.mNoOmitFramePointers = false;
options.mLargeStrings = false; options.mLargeStrings = false;
options.mLargeCollections = false; options.mLargeCollections = false;
options.mRuntimeKind = .Default;
options.mReflectKind = .Normal;
options.mInitLocalVariables = false; options.mInitLocalVariables = false;
options.mRuntimeChecks = !isRelease; options.mRuntimeChecks = !isRelease;
options.mEmitDynamicCastCheck = !isRelease; options.mEmitDynamicCastCheck = !isRelease;
@ -1113,6 +1136,8 @@ namespace IDE
options.mNoOmitFramePointers = data.GetBool("NoOmitFramePointers", false); options.mNoOmitFramePointers = data.GetBool("NoOmitFramePointers", false);
options.mLargeStrings = data.GetBool("LargeStrings", false); options.mLargeStrings = data.GetBool("LargeStrings", false);
options.mLargeCollections = data.GetBool("LargeCollections", 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.mInitLocalVariables = data.GetBool("InitLocalVariables", false);
options.mRuntimeChecks = data.GetBool("RuntimeChecks", !isRelease); options.mRuntimeChecks = data.GetBool("RuntimeChecks", !isRelease);
options.mEmitDynamicCastCheck = data.GetBool("EmitDynamicCastCheck", !isRelease); options.mEmitDynamicCastCheck = data.GetBool("EmitDynamicCastCheck", !isRelease);

View file

@ -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 menuWidget = ThemeFactory.mDefault.CreateMenuWidget(menu);
menuWidget.Init(relWidget, x, y); menuWidget.Init(relWidget, x, y);
} }

View file

@ -797,6 +797,8 @@ namespace IDE.ui
AddPropertiesItem(category, "No Omit Frame Pointers", "mNoOmitFramePointers"); AddPropertiesItem(category, "No Omit Frame Pointers", "mNoOmitFramePointers");
AddPropertiesItem(category, "Large Strings", "mLargeStrings"); AddPropertiesItem(category, "Large Strings", "mLargeStrings");
AddPropertiesItem(category, "Large Collections", "mLargeCollections"); AddPropertiesItem(category, "Large Collections", "mLargeCollections");
AddPropertiesItem(category, "Runtime", "mRuntimeKind");
AddPropertiesItem(category, "Reflection", "mReflectKind");
category.Open(true, true); category.Open(true, true);
(category, propEntry) = AddPropertiesItem(root, "Debug"); (category, propEntry) = AddPropertiesItem(root, "Debug");

View file

@ -509,7 +509,7 @@ addr_target COFF::GetSectionAddr(uint16 section, uint32 offset)
return hiBase + offset; return hiBase + offset;
} }
int rva = mSectionRVAs[section - 1]; int rva = mSectionHeaders[section - 1].mVirtualAddress;
if (rva == 0) if (rva == 0)
return ADDR_FLAG_ABS + offset; return ADDR_FLAG_ABS + offset;
@ -5178,6 +5178,7 @@ bool COFF::CvParseDBI(int wantAge)
contribEntry->mLength = curSize; contribEntry->mLength = curSize;
contribEntry->mDbgModule = this; contribEntry->mDbgModule = this;
contribEntry->mCompileUnitId = contrib.mModule; contribEntry->mCompileUnitId = contrib.mModule;
contribEntry->mSection = contrib.mSection;
mDebugTarget->mContribMap.Insert(contribEntry); mDebugTarget->mContribMap.Insert(contribEntry);
} }
} }
@ -5288,7 +5289,7 @@ bool COFF::CvParseDBI(int wantAge)
void COFF::ParseSectionHeader(int sectionIdx) void COFF::ParseSectionHeader(int sectionIdx)
{ {
bool fakeRVAS = mSectionRVAs.empty(); bool fakeRVAS = mSectionHeaders.empty();
int sectionSize = 0; int sectionSize = 0;
uint8* sectionData = CvReadStream(sectionIdx, &sectionSize); uint8* sectionData = CvReadStream(sectionIdx, &sectionSize);
@ -5300,12 +5301,15 @@ void COFF::ParseSectionHeader(int sectionIdx)
auto& sectionHeader = GET(PESectionHeader); auto& sectionHeader = GET(PESectionHeader);
if (fakeRVAS) if (fakeRVAS)
{ {
mSectionRVAs.push_back(sectionHeader.mVirtualAddress); mSectionHeaders.push_back(sectionHeader);
} }
} }
if (fakeRVAS) if (fakeRVAS)
mSectionRVAs.push_back(0); {
PESectionHeader sectionHeader = { 0 };
mSectionHeaders.push_back(sectionHeader);
}
delete sectionData; delete sectionData;
} }

View file

@ -1220,7 +1220,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
Array<BfType*> vdataTypeList; Array<BfType*> vdataTypeList;
HashSet<BfModule*> usedModuleSet; HashSet<BfModule*> usedModuleSet;
HashSet<BfType*> reflectTypeSet; HashSet<BfType*> reflectSkipTypeSet;
HashSet<BfType*> reflectFieldTypeSet; HashSet<BfType*> reflectFieldTypeSet;
vdataHashCtx.MixinStr(project->mStartupObject); vdataHashCtx.MixinStr(project->mStartupObject);
@ -1398,20 +1398,49 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
bool madeBfTypeData = false; bool madeBfTypeData = false;
auto typeDefType = mContext->mBfTypeType; 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 needsObjectTypeData = needsTypeList || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "RawGetType") || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "GetType");
bool needsTypeNames = bfModule->IsMethodImplementedAndReified(typeDefType, "GetName") || bfModule->IsMethodImplementedAndReified(typeDefType, "GetFullName"); bool needsTypeNames = bfModule->IsMethodImplementedAndReified(typeDefType, "GetName") || bfModule->IsMethodImplementedAndReified(typeDefType, "GetFullName");
bool needsStringLiteralList = (mOptions.mAllowHotSwapping) || (bfModule->IsMethodImplementedAndReified(stringType, "Intern")) || (bfModule->IsMethodImplementedAndReified(stringViewType, "Intern")); bool needsStringLiteralList = (mOptions.mAllowHotSwapping) || (bfModule->IsMethodImplementedAndReified(stringType, "Intern")) || (bfModule->IsMethodImplementedAndReified(stringViewType, "Intern"));
Dictionary<int, int> usedStringIdMap; BfCreateTypeDataContext createTypeDataCtx;
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectTypeInstanceTypeDef)); if (!needsTypeList)
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSpecializedGenericType)); {
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectUnspecializedGenericType)); reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mTypeTypeDef));
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectArrayType)); reflectSkipTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectTypeInstanceTypeDef));
reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectGenericParamType)); }
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; SmallVector<BfIRValue, 256> typeDataVector;
Array<BfType*> usedTypeDataVector;
for (auto type : vdataTypeList) for (auto type : vdataTypeList)
{ {
if (type->IsTypeAlias()) if (type->IsTypeAlias())
@ -1425,9 +1454,12 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
if ((typeInst != NULL) && (!typeInst->IsReified()) && (!typeInst->IsUnspecializedType())) if ((typeInst != NULL) && (!typeInst->IsReified()) && (!typeInst->IsUnspecializedType()))
continue; continue;
bool needsTypeData = (needsTypeList) || ((type->IsObject()) && (needsObjectTypeData)); bool needsTypeData = (needsFullTypeList) || ((type->IsObject()) && (needsObjectTypeData));
bool needsVData = (type->IsObject()) && (typeInst->HasBeenInstantiated()); bool needsVData = (type->IsObject()) && (typeInst->HasBeenInstantiated());
if ((needsObjectTypeData) && (boxeeSet.Contains(typeInst)))
needsTypeData = true;
bool forceReflectFields = false; bool forceReflectFields = false;
if (bfModule->mProject->mReferencedTypeData.Contains(type)) if (bfModule->mProject->mReferencedTypeData.Contains(type))
@ -1437,8 +1469,16 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
forceReflectFields = true; forceReflectFields = true;
} }
BfIRValue typeVariable; if (reflectSkipTypeSet.Contains(type))
{
if (!bfModule->mProject->mReferencedTypeData.Contains(type))
{
needsTypeData = false;
needsVData = false;
}
}
BfIRValue typeVariable;
if ((needsTypeData) || (needsVData)) if ((needsTypeData) || (needsVData))
{ {
if (reflectFieldTypeSet.Contains(type)) if (reflectFieldTypeSet.Contains(type))
@ -1446,14 +1486,25 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
needsTypeData = true; needsTypeData = true;
forceReflectFields = true; forceReflectFields = true;
} }
else if (reflectTypeSet.Contains(type)) /*else if (reflectTypeSet.Contains(type))
{ {
needsTypeData = true; needsTypeData = true;
needsVData = 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; type->mDirty = false;
if (needsTypeList) if (needsTypeList)
@ -1573,13 +1624,13 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
BfMangler::MangleStaticFieldName(stringsVariableName, GetMangleKind(), stringType->ToTypeInstance(), "sIdStringLiterals", stringPtrType); BfMangler::MangleStaticFieldName(stringsVariableName, GetMangleKind(), stringType->ToTypeInstance(), "sIdStringLiterals", stringPtrType);
Array<BfIRValue> stringList; Array<BfIRValue> stringList;
stringList.Resize(usedStringIdMap.size()); stringList.Resize(createTypeDataCtx.mUsedStringIdMap.size());
for (auto& kv : usedStringIdMap) for (auto& kv : createTypeDataCtx.mUsedStringIdMap)
{ {
stringList[kv.mValue] = bfModule->mStringObjectPool[kv.mKey]; 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 stringArray = bfModule->mBfIRBuilder->CreateConstAgg_Value(stringArrayType, stringList);
auto stringArrayVar = bfModule->mBfIRBuilder->CreateGlobalVariable(stringArrayType, true, BfIRLinkageType_External, stringArray, stringsVariableName); 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)) if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(usingDirective->mTypeRef))
{ {
mContext->mScratchModule->ResolveTypeRefAllowUnboundGenerics(usingDirective->mTypeRef, BfPopulateType_Identity); mContext->mScratchModule->ResolveTypeRefAllowUnboundGenerics(usingDirective->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_NoReify);
} }
else else
mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, BfPopulateType_Identity); mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_NoReify);
if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL)) if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL))
mResolvePassData->mAutoComplete->CheckTypeRef(usingDirective->mTypeRef, false, false); 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 BfCompiler::GetDynCastVDataCount()
{ {
int dynElements = 1 + mMaxInterfaceSlots; int dynElements = 1 + mMaxInterfaceSlots;
return ((dynElements * 4) + mSystem->mPtrSize - 1) / mSystem->mPtrSize; return ((dynElements * 4) + mSystem->mPtrSize - 1) / mSystem->mPtrSize;
} }
bool BfCompiler::IsAutocomplete() bool BfCompiler::IsAutocomplete()
{ {
return (mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL); return (mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL);
@ -7177,6 +7235,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mActionTypeDef = _GetRequiredType("System.Action"); mActionTypeDef = _GetRequiredType("System.Action");
mEnumTypeDef = _GetRequiredType("System.Enum"); mEnumTypeDef = _GetRequiredType("System.Enum");
mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute"); mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute");
mNoStaticCtorAttributeTypeDef = _GetRequiredType("System.NoStaticCtorAttribute");
mComptimeAttributeTypeDef = _GetRequiredType("System.ComptimeAttribute"); mComptimeAttributeTypeDef = _GetRequiredType("System.ComptimeAttribute");
mConstEvalAttributeTypeDef = _GetRequiredType("System.ConstEvalAttribute"); mConstEvalAttributeTypeDef = _GetRequiredType("System.ConstEvalAttribute");
mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute"); mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute");

View file

@ -442,6 +442,7 @@ public:
BfTypeDef* mDisableChecksAttributeTypeDef; BfTypeDef* mDisableChecksAttributeTypeDef;
BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef; BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef;
BfTypeDef* mFriendAttributeTypeDef; BfTypeDef* mFriendAttributeTypeDef;
BfTypeDef* mNoStaticCtorAttributeTypeDef;
BfTypeDef* mComptimeAttributeTypeDef; BfTypeDef* mComptimeAttributeTypeDef;
BfTypeDef* mConstEvalAttributeTypeDef; BfTypeDef* mConstEvalAttributeTypeDef;
BfTypeDef* mNoExtensionAttributeTypeDef; BfTypeDef* mNoExtensionAttributeTypeDef;
@ -501,6 +502,7 @@ public:
void MarkStringPool(BfIRConstHolder* constHolder, BfIRValue irValue); void MarkStringPool(BfIRConstHolder* constHolder, BfIRValue irValue);
void ClearUnusedStringPoolEntries(); void ClearUnusedStringPoolEntries();
void ClearBuildCache(); void ClearBuildCache();
int GetVDataPrefixDataCount();
int GetDynCastVDataCount(); int GetDynCastVDataCount();
bool IsAutocomplete(); bool IsAutocomplete();
bool IsDataResolvePass(); bool IsDataResolvePass();

View file

@ -420,11 +420,18 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
didWork = true; didWork = true;
} }
for (int populatePass = 0; populatePass < 2; populatePass++)
{
for (int workIdx = 0; workIdx < (int)mPopulateTypeWorkList.size(); workIdx++) for (int workIdx = 0; workIdx < (int)mPopulateTypeWorkList.size(); workIdx++)
{ {
//BP_ZONE("PWL_PopulateType"); //BP_ZONE("PWL_PopulateType");
if (IsCancellingAndYield()) if (IsCancellingAndYield())
break; break;
if (!mMidCompileWorkList.IsEmpty())
{
// Let these mid-compiles occur as soon as possible
break;
}
auto workItemRef = mPopulateTypeWorkList[workIdx]; auto workItemRef = mPopulateTypeWorkList[workIdx];
if (workItemRef == NULL) if (workItemRef == NULL)
@ -441,6 +448,11 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
continue; 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(); auto typeInst = type->ToTypeInstance();
if ((typeInst != NULL) && (resolveParser != NULL)) if ((typeInst != NULL) && (resolveParser != NULL))
{ {
@ -470,6 +482,13 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
mCompiler->UpdateCompletion(); mCompiler->UpdateCompletion();
didWork = true; didWork = true;
} }
}
if ((!mMidCompileWorkList.IsEmpty()) && (didWork))
{
// Let the mid-compile occur ASAP
continue;
}
for (int workIdx = 0; workIdx < (int)mTypeRefVerifyWorkList.size(); workIdx++) for (int workIdx = 0; workIdx < (int)mTypeRefVerifyWorkList.size(); workIdx++)
{ {
@ -1984,6 +2003,7 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds)
} }
else if (dependentTypeInst != NULL) else if (dependentTypeInst != NULL)
{ {
mGhostDependencies.Add(type);
// This keeps us from crashing from accessing deleted types on subsequent compiles // This keeps us from crashing from accessing deleted types on subsequent compiles
mFailTypes.TryAdd(dependentTypeInst, BfFailKind_Normal); 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) for (auto typeInst : defEmitParentCheckQueue)
{ {
if (typeInst->IsDeleting()) if (typeInst->IsDeleting())
@ -2675,6 +2727,8 @@ void BfContext::UpdateRevisedTypes()
RebuildType(type); RebuildType(type);
} }
} }
BfLogSysM("BfContext::UpdateRevisedTypes done.\n");
} }
void BfContext::VerifyTypeLookups(BfTypeInstance* typeInst) void BfContext::VerifyTypeLookups(BfTypeInstance* typeInst)
@ -3459,6 +3513,7 @@ void BfContext::Cleanup()
} }
} }
mTypeGraveyard.Clear(); mTypeGraveyard.Clear();
mGhostDependencies.Clear();
if (!mDeletingModules.IsEmpty()) if (!mDeletingModules.IsEmpty())
{ {

View file

@ -382,6 +382,7 @@ public:
BfModule* mScratchModule; BfModule* mScratchModule;
BfModule* mUnreifiedModule; BfModule* mUnreifiedModule;
HashSet<String> mUsedModuleNames; HashSet<String> mUsedModuleNames;
HashSet<BfType*> mGhostDependencies; // We couldn't properly rebuild our dependencies
Dictionary<BfProject*, BfModule*> mProjectModule; Dictionary<BfProject*, BfModule*> mProjectModule;
Array<BfModule*> mModules; Array<BfModule*> mModules;
Array<BfModule*> mDeletingModules; Array<BfModule*> mDeletingModules;

View file

@ -5205,8 +5205,13 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe
return BfTypedValue(retVal, resolvedFieldType); return BfTypedValue(retVal, resolvedFieldType);
} }
else if (fieldDef->mIsStatic) else if (fieldDef->mIsStatic)
{
if ((mModule->mAttributeState == NULL) || (mModule->mAttributeState->mCustomAttributes == NULL) ||
(!mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoStaticCtorAttributeTypeDef)))
{ {
mModule->CheckStaticAccess(typeInstance); mModule->CheckStaticAccess(typeInstance);
}
auto retVal = mModule->ReferenceStaticField(fieldInstance); auto retVal = mModule->ReferenceStaticField(fieldInstance);
bool isStaticCtor = (mModule->mCurMethodInstance != NULL) && bool isStaticCtor = (mModule->mCurMethodInstance != NULL) &&
(mModule->mCurMethodInstance->mMethodDef->IsCtorOrInit()) && (mModule->mCurMethodInstance->mMethodDef->IsCtorOrInit()) &&
@ -6684,7 +6689,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
#endif #endif
int vExtOfs = typeInst->GetOrigImplBaseVTableSize(); 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)); vDataIdx = mModule->mBfIRBuilder->CreateAdd(vDataIdx, mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, vExtOfs));
BfIRValue extendPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(vDataPtr, vDataIdx); BfIRValue extendPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(vDataPtr, vDataIdx);
vDataPtr = mModule->mBfIRBuilder->CreateLoad(extendPtr); vDataPtr = mModule->mBfIRBuilder->CreateLoad(extendPtr);
@ -7600,8 +7606,15 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
// Handled in args // Handled in args
} }
else 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); mModule->CheckStaticAccess(methodInstance->mMethodInstanceGroup->mOwner);
}
}
if (target) if (target)
{ {
@ -8613,8 +8626,17 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
// the type has been initialized // the type has been initialized
auto targetTypeInst = target.mType->ToTypeInstance(); auto targetTypeInst = target.mType->ToTypeInstance();
if (targetTypeInst != NULL) 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); mModule->CheckStaticAccess(targetTypeInst);
} }
}
}
}
if (methodInstance->mReturnType == NULL) if (methodInstance->mReturnType == NULL)
{ {
@ -12535,7 +12557,7 @@ void BfExprEvaluator::Visit(BfCheckTypeExpression* checkTypeExpr)
void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr) void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
{ {
auto targetValue = mModule->CreateValueFromExpression(dynCastExpr->mTarget); 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(); auto autoComplete = GetAutoComplete();
if (autoComplete != NULL) if (autoComplete != NULL)
@ -18843,6 +18865,10 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
checkedKind = BfCheckedKind_Unchecked; checkedKind = BfCheckedKind_Unchecked;
mModule->mAttributeState->mUsed = true; mModule->mAttributeState->mUsed = true;
} }
if (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mNoStaticCtorAttributeTypeDef))
{
mModule->mAttributeState->mUsed = true;
}
} }
if ((isCascade) && (cascadeOperatorToken != NULL) && ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0)) if ((isCascade) && (cascadeOperatorToken != NULL) && ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0))
@ -20967,7 +20993,7 @@ void BfExprEvaluator::InitializedSizedArray(BfSizedArrayType* arrayType, BfToken
} }
elementValue = mModule->LoadOrAggregateValue(elementValue); elementValue = mModule->LoadOrAggregateValue(elementValue);
if (!elementValue.mValue.IsConst()) if (!elemPtrValue.IsConst())
mModule->mBfIRBuilder->CreateAlignedStore(elementValue.mValue, elemPtrValue, checkArrayType->mElementType->mAlign); mModule->mBfIRBuilder->CreateAlignedStore(elementValue.mValue, elemPtrValue, checkArrayType->mElementType->mAlign);
} }
} }

View file

@ -5391,6 +5391,8 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou
mClassVDataRefs.TryGetValue(typeInstance, &globalVariablePtr); mClassVDataRefs.TryGetValue(typeInstance, &globalVariablePtr);
int numElements = 1; int numElements = 1;
if (mSystem->mPtrSize == 4)
numElements++;
if ((outNumElements != NULL) || (globalVariablePtr == NULL)) if ((outNumElements != NULL) || (globalVariablePtr == NULL))
{ {
@ -5432,11 +5434,6 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou
if (outMangledName != NULL) if (outMangledName != NULL)
*outMangledName = classVDataName; *outMangledName = classVDataName;
/*if (itr != mClassVDataRefs.end())
{
globalVariable = itr->second;
}*/
BfIRValue globalVariable; BfIRValue globalVariable;
if (globalVariablePtr != NULL) if (globalVariablePtr != NULL)
{ {
@ -5937,7 +5934,21 @@ BfIRValue BfModule::CreateFieldData(BfFieldInstance* fieldInstance, int customAt
return result; 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)) if ((IsHotCompile()) && (!type->mDirty))
return BfIRValue(); return BfIRValue();
@ -6004,13 +6015,18 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type) && (!mIsComptimeModule)) if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type) && (!mIsComptimeModule))
{ {
CreateTypeData(typeDataSource, usedStringIdMap, false, true, needsTypeNames, true); CreateTypeData(typeDataSource, ctx, false, true, needsTypeNames, true);
} }
typeTypeData = CreateClassVDataGlobal(typeDataSource); typeTypeData = CreateClassVDataGlobal(typeDataSource);
ctx.mReflectTypeSet.Add(typeDataSource);
} }
else else
typeTypeData = CreateClassVDataGlobal(typeInstanceType->ToTypeInstance()); {
//typeTypeData = CreateClassVDataGlobal(typeInstanceType->ToTypeInstance());
typeTypeData = mBfIRBuilder->CreateConstNull();
}
BfType* longType = GetPrimitiveType(BfTypeCode_Int64); BfType* longType = GetPrimitiveType(BfTypeCode_Int64);
BfType* intType = GetPrimitiveType(BfTypeCode_Int32); BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
@ -6119,7 +6135,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
int virtSlotIdx = -1; int virtSlotIdx = -1;
if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0)) if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0))
virtSlotIdx = typeInstance->mSlotNum + 1 + mCompiler->GetDynCastVDataCount(); virtSlotIdx = typeInstance->mSlotNum + mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount();
int memberDataOffset = 0; int memberDataOffset = 0;
if (type->IsInterface()) if (type->IsInterface())
memberDataOffset = virtSlotIdx * mSystem->mPtrSize; memberDataOffset = virtSlotIdx * mSystem->mPtrSize;
@ -6316,18 +6332,13 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
String classVDataName; String classVDataName;
if (typeInstance->mSlotNum >= 0) if (typeInstance->mSlotNum >= 0)
{ {
// For interfaces we ONLY emit the slot num CreateSlotOfs(typeInstance);
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);
} }
else if ((typeInstance->IsObject()) && (!typeInstance->IsUnspecializedType()) && (needsVData)) else if ((typeInstance->IsObject()) && (!typeInstance->IsUnspecializedType()) && (needsVData))
{ {
int dynCastDataElems = 0; int dynCastDataElems = 0;
int numElements = 1; 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; numElements += mCompiler->mMaxInterfaceSlots;
if (!typeInstance->IsInterface()) if (!typeInstance->IsInterface())
{ {
@ -6342,7 +6353,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
classVDataVar = CreateClassVDataGlobal(typeInstance, &expectNumElements, &classVDataName); 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; 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 // Force override of GetHashCode so we use the pointer address as the hash code
for (auto& checkIFace : checkTypeInst->mInterfaces) for (auto& checkIFace : checkTypeInst->mInterfaces)
{ {
if (checkIFace.mStartVirtualIdx < 0)
continue;
for (int methodIdx = 0; methodIdx < (int)checkIFace.mInterfaceType->mMethodInstanceGroups.size(); methodIdx++) for (int methodIdx = 0; methodIdx < (int)checkIFace.mInterfaceType->mMethodInstanceGroups.size(); methodIdx++)
{ {
BfIRValue pushValue; BfIRValue pushValue;
@ -6976,7 +6991,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
for (auto arg : attr->mCtorArgs) for (auto arg : attr->mCtorArgs)
{ {
auto argType = ctorMethodInstance->GetParamType(argIdx); auto argType = ctorMethodInstance->GetParamType(argIdx);
EncodeAttributeData(typeInstance, argType, arg, data, usedStringIdMap); EncodeAttributeData(typeInstance, argType, arg, data, ctx.mUsedStringIdMap);
argIdx++; argIdx++;
} }
@ -7494,7 +7509,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
} }
else else
{ {
vDataIdx = 1 + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots; vDataIdx = mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
if ((mCompiler->mOptions.mHasVDataExtender) && (mCompiler->IsHotCompile())) if ((mCompiler->mOptions.mHasVDataExtender) && (mCompiler->IsHotCompile()))
{ {
auto typeInst = defaultMethod->mMethodInstanceGroup->mOwner; 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)); BfIRType interfaceDataPtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapType(reflectInterfaceDataType));
Array<bool> wantsIfaceMethod; Array<bool> wantsIfaceMethod;
bool wantsIfaceMethods = false; bool wantsIfaceMethods = false;
if (typeInstance->mInterfaces.IsEmpty()) if ((typeInstance->mInterfaces.IsEmpty()) || (!needsTypeData))
interfaceDataPtr = mBfIRBuilder->CreateConstNull(interfaceDataPtrType); interfaceDataPtr = mBfIRBuilder->CreateConstNull(interfaceDataPtrType);
else else
{ {
@ -7802,7 +7817,22 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
{ {
BF_ASSERT(!classVDataName.IsEmpty()); 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 classVDataConstDataType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)vData.size());
auto classVDataConstData = mBfIRBuilder->CreateConstAgg_Value(classVDataConstDataType, vData); auto classVDataConstData = mBfIRBuilder->CreateConstAgg_Value(classVDataConstDataType, vData);
@ -10459,18 +10489,24 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
mBfIRBuilder->CreateObjectAccessCheck(typedVal.mValue, !IsOptimized()); mBfIRBuilder->CreateObjectAccessCheck(typedVal.mValue, !IsOptimized());
} }
void BfModule::EmitEnsureInstructionAt() bool BfModule::WantsDebugHelpers()
{ {
if (mBfIRBuilder->mIgnoreWrites) if (mBfIRBuilder->mIgnoreWrites)
return; return false;
if (mIsComptimeModule) if (mIsComptimeModule)
{ {
// Always add // Always add
} }
else if ((mProject == NULL) || (!mHasFullDebugInfo) || (IsOptimized()) || (mCompiler->mOptions.mOmitDebugHelpers)) else if ((mProject == NULL) || (!mHasFullDebugInfo) || (IsOptimized()) || (mCompiler->mOptions.mOmitDebugHelpers))
return; return false;
return true;
}
void BfModule::EmitEnsureInstructionAt()
{
if (!WantsDebugHelpers())
return;
mBfIRBuilder->CreateEnsureInstructionAt(); mBfIRBuilder->CreateEnsureInstructionAt();
} }
@ -10549,7 +10585,7 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
targetType = GetWrappedStructType(targetType); targetType = GetWrappedStructType(targetType);
AddDependency(targetType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference); 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->CreateAdd(vDataPtr, irb->CreateConst(BfTypeCode_IntPtr, inheritanceIdOfs));
vDataPtr = irb->CreateIntToPtr(vDataPtr, irb->MapType(int32PtrType)); vDataPtr = irb->CreateIntToPtr(vDataPtr, irb->MapType(int32PtrType));
BfIRValue objInheritanceId = irb->CreateLoad(vDataPtr); BfIRValue objInheritanceId = irb->CreateLoad(vDataPtr);
@ -11107,6 +11143,9 @@ BfModuleMethodInstance BfModule::GetMethodInstanceAtIdx(BfTypeInstance* typeInst
PopulateType(typeInstance, BfPopulateType_DataAndMethods); PopulateType(typeInstance, BfPopulateType_DataAndMethods);
if (methodIdx >= typeInstance->mMethodInstanceGroups.mSize)
return BfModuleMethodInstance();
auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault; auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault;
BfMethodDef* methodDef = NULL; BfMethodDef* methodDef = NULL;
@ -14003,7 +14042,7 @@ BfModule* BfModule::GetOrCreateMethodModule(BfMethodInstance* methodInstance)
return declareModule; 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) if (methodDef->mMethodType == BfMethodType_Init)
return BfModuleMethodInstance(); return BfModuleMethodInstance();
@ -14129,6 +14168,8 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
instModule->mReifyQueued = true; 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 // This ensures that the method will actually be created when it gets reified
BfMethodSpecializationRequest* specializationRequest = mContext->mMethodSpecializationWorkList.Alloc(); BfMethodSpecializationRequest* specializationRequest = mContext->mMethodSpecializationWorkList.Alloc();
specializationRequest->mFromModule = typeInst->mModule; specializationRequest->mFromModule = typeInst->mModule;
@ -14154,7 +14195,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
// Not extern // Not extern
// Create the instance in the proper module and then create a reference in this one // 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) if (!moduleMethodInst)
return moduleMethodInst; return moduleMethodInst;
tryModuleMethodLookup = true; tryModuleMethodLookup = true;
@ -14549,8 +14590,18 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
/*if ((!mCompiler->mIsResolveOnly) && (!isReified)) /*if ((!mCompiler->mIsResolveOnly) && (!isReified))
BF_ASSERT(!methodInstance->mIsReified);*/ 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) if (methodInstance->mIsReified != isReified)
{
BfLogSysM("GetMethodInstance %p Decl_AwaitingReference setting reified to %d\n", methodInstance, isReified); BfLogSysM("GetMethodInstance %p Decl_AwaitingReference setting reified to %d\n", methodInstance, isReified);
}
if ((!isReified) && if ((!isReified) &&
((methodInstance->mDeclModule == NULL) || (!methodInstance->mDeclModule->mIsModuleMutable))) ((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); globalValue = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External, value, slotVarName);
mInterfaceSlotRefs[ifaceType] = globalValue; mInterfaceSlotRefs[ifaceType] = globalValue;
// Make sure we reify
PopulateType(ifaceType, BfPopulateType_Declaration);
AddDependency(ifaceType, mCurTypeInstance, BfDependencyMap::DependencyFlag_StaticValue);
} }
return mBfIRBuilder->CreateAlignedLoad(globalValue/*, "slotOfs"*/, 4); return mBfIRBuilder->CreateAlignedLoad(globalValue/*, "slotOfs"*/, 4);
@ -20087,6 +20141,26 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
if (mAwaitingInitFinish) if (mAwaitingInitFinish)
FinishInit(); 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) if (!methodInstance->mIsReified)
BF_ASSERT(!mIsReified); BF_ASSERT(!mIsReified);
@ -22047,12 +22121,15 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
if ((retVal) && (!retVal.mType->IsVar()) && (expectingType != NULL)) if ((retVal) && (!retVal.mType->IsVar()) && (expectingType != NULL))
{ {
mCurMethodState->mHadReturn = true; mCurMethodState->mHadReturn = true;
if (!mCurMethodState->mLeftBlockUncond)
{
retVal = LoadOrAggregateValue(retVal); retVal = LoadOrAggregateValue(retVal);
EmitReturn(retVal); EmitReturn(retVal);
} }
} }
} }
} }
}
BF_ASSERT(mCurMethodState->mCurScope == &mCurMethodState->mHeadScope); BF_ASSERT(mCurMethodState->mCurScope == &mCurMethodState->mHeadScope);
@ -23719,6 +23796,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
BfTypeState typeState(mCurTypeInstance); BfTypeState typeState(mCurTypeInstance);
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState); SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
BfModule* resolveModule = mContext->mUnreifiedModule;
if (mCompiler->IsAutocomplete()) if (mCompiler->IsAutocomplete())
prevIsCapturingMethodMatchInfo.Init(mCompiler->mResolvePassData->mAutoComplete->mIsCapturingMethodMatchInfo, false); prevIsCapturingMethodMatchInfo.Init(mCompiler->mResolvePassData->mAutoComplete->mIsCapturingMethodMatchInfo, false);
@ -23963,7 +24042,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
mIgnoreErrors = false; 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)) if ((((methodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) || (methodInstance->mIsAutocompleteMethod))
&& (methodDef->mReturnTypeRef->IsA<BfVarTypeReference>())) && (methodDef->mReturnTypeRef->IsA<BfVarTypeReference>()))
@ -24055,14 +24134,14 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
{ {
BfTypeUtils::SplatIterate([&](BfType* checkType) BfTypeUtils::SplatIterate([&](BfType* checkType)
{ {
PopulateType(checkType, BfPopulateType_Data); resolveModule->PopulateType(checkType, BfPopulateType_Data);
}, thisType); }, thisType);
} }
} }
else else
{ {
thisType = mCurTypeInstance; thisType = mCurTypeInstance;
PopulateType(thisType, BfPopulateType_Declaration); resolveModule->PopulateType(thisType, BfPopulateType_Declaration);
} }
} }
@ -24137,7 +24216,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
bool wasGenericParam = false; bool wasGenericParam = false;
if (resolvedParamType == NULL) 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) if (paramDef->mParamKind == BfParamKind_ExplicitThis)
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_NoWarnOnMut); resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_NoWarnOnMut);
resolvedParamType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, resolveFlags); resolvedParamType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, resolveFlags);
@ -24388,7 +24467,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
} }
int argIdx = 0; int argIdx = 0;
PopulateType(methodInstance->mReturnType, BfPopulateType_Data); resolveModule->PopulateType(methodInstance->mReturnType, BfPopulateType_Data);
if ((!methodDef->mIsStatic) && (!methodDef->mHasExplicitThis)) if ((!methodDef->mIsStatic) && (!methodDef->mHasExplicitThis))
{ {
int thisIdx = methodDef->mHasExplicitThis ? 0 : -1; int thisIdx = methodDef->mHasExplicitThis ? 0 : -1;
@ -24428,7 +24507,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
} }
else if ((checkType->IsComposite()) && (methodInstance->AllowsSplatting(paramIdx))) else if ((checkType->IsComposite()) && (methodInstance->AllowsSplatting(paramIdx)))
{ {
PopulateType(checkType, BfPopulateType_Data); resolveModule->PopulateType(checkType, BfPopulateType_Data);
if (checkType->IsSplattable()) if (checkType->IsSplattable())
{ {
bool isSplat = false; bool isSplat = false;
@ -24569,7 +24648,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
{ {
auto paramType = methodInstance->GetParamType(paramIdx); auto paramType = methodInstance->GetParamType(paramIdx);
if (paramType->IsComposite()) if (paramType->IsComposite())
PopulateType(paramType, BfPopulateType_Data); resolveModule->PopulateType(paramType, BfPopulateType_Data);
if (!methodInstance->IsParamSkipped(paramIdx)) if (!methodInstance->IsParamSkipped(paramIdx))
{ {
@ -24588,7 +24667,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
if (methodInstance->mIsUnspecializedVariation) if (methodInstance->mIsUnspecializedVariation)
return; return;
PopulateType(resolvedReturnType, BfPopulateType_Data); resolveModule->PopulateType(resolvedReturnType, BfPopulateType_Data);
auto retLLVMType = mBfIRBuilder->MapType(resolvedReturnType); auto retLLVMType = mBfIRBuilder->MapType(resolvedReturnType);
if (resolvedReturnType->IsValuelessType()) if (resolvedReturnType->IsValuelessType())
retLLVMType = mBfIRBuilder->GetPrimitiveType(BfTypeCode_None); retLLVMType = mBfIRBuilder->GetPrimitiveType(BfTypeCode_None);
@ -26023,6 +26102,8 @@ void BfModule::DbgFinish()
if (mBfIRBuilder->DbgHasInfo()) if (mBfIRBuilder->DbgHasInfo())
{ {
bool needForceLinking = false; bool needForceLinking = false;
if (WantsDebugHelpers())
{
for (auto& ownedType : mOwnedTypeInstances) for (auto& ownedType : mOwnedTypeInstances)
{ {
bool hasConfirmedReference = false; bool hasConfirmedReference = false;
@ -26039,6 +26120,7 @@ void BfModule::DbgFinish()
if ((!hasConfirmedReference) || (ownedType->IsBoxed())) if ((!hasConfirmedReference) || (ownedType->IsBoxed()))
needForceLinking = true; needForceLinking = true;
} }
}
if ((needForceLinking) && (mProject->mCodeGenOptions.mAsmKind == BfAsmKind_None)) if ((needForceLinking) && (mProject->mCodeGenOptions.mAsmKind == BfAsmKind_None))
{ {
@ -26153,7 +26235,7 @@ bool BfModule::Finish()
codeGenOptions.mWriteLLVMIR = mCompiler->mOptions.mWriteIR; codeGenOptions.mWriteLLVMIR = mCompiler->mOptions.mWriteIR;
codeGenOptions.mWriteObj = mCompiler->mOptions.mGenerateObj; codeGenOptions.mWriteObj = mCompiler->mOptions.mGenerateObj;
codeGenOptions.mWriteBitcode = mCompiler->mOptions.mGenerateBitcode; 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; codeGenOptions.mDynSlotOfs = mSystem->mPtrSize - mCompiler->GetDynCastVDataCount() * 4;
mCompiler->mStats.mIRBytes += mBfIRBuilder->mStream.GetSize(); mCompiler->mStats.mIRBytes += mBfIRBuilder->mStream.GetSize();

View file

@ -158,6 +158,12 @@ enum BfLocalVarAssignKind : int8
BfLocalVarAssignKind_Unconditional = 2 BfLocalVarAssignKind_Unconditional = 2
}; };
struct BfCreateTypeDataContext
{
Dictionary<int, int> mUsedStringIdMap;
HashSet<BfTypeInstance*> mReflectTypeSet;
};
class BfLocalVariable class BfLocalVariable
{ {
public: public:
@ -1740,6 +1746,7 @@ public:
bool HasExecutedOutput(); bool HasExecutedOutput();
void SkipObjectAccessCheck(BfTypedValue typedVal); void SkipObjectAccessCheck(BfTypedValue typedVal);
void EmitObjectAccessCheck(BfTypedValue typedVal); void EmitObjectAccessCheck(BfTypedValue typedVal);
bool WantsDebugHelpers();
void EmitEnsureInstructionAt(); void EmitEnsureInstructionAt();
void EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* targetType, BfIRBlock trueBlock, BfIRBlock falseBlock, bool nullSucceeds = false); void EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* targetType, BfIRBlock trueBlock, BfIRBlock falseBlock, bool nullSucceeds = false);
void EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull); void EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull);
@ -1966,7 +1973,7 @@ public:
bool ValidateTypeWildcard(BfAstNode* typeRef, bool isAttributeRef); bool ValidateTypeWildcard(BfAstNode* typeRef, bool isAttributeRef);
void GetDelegateTypeRefAttributes(BfDelegateTypeRef* delegateTypeRef, BfCallingConvention& callingConvention); void GetDelegateTypeRefAttributes(BfDelegateTypeRef* delegateTypeRef, BfCallingConvention& callingConvention);
BfType* ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, int numGenericArgs = 0); 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_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* 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); BfType* ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);
@ -2062,7 +2069,7 @@ public:
void SetMethodDependency(BfMethodInstance* methodInstance); void SetMethodDependency(BfMethodInstance* methodInstance);
BfModuleMethodInstance ReferenceExternalMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None); BfModuleMethodInstance ReferenceExternalMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);
BfModule* GetOrCreateMethodModule(BfMethodInstance* methodInstance); 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); BfModuleMethodInstance GetMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);
BfMethodInstance* GetOuterMethodInstance(BfMethodInstance* methodInstance); // Only useful for local methods BfMethodInstance* GetOuterMethodInstance(BfMethodInstance* methodInstance); // Only useful for local methods
void SetupMethodIdHash(BfMethodInstance* methodInstance); void SetupMethodIdHash(BfMethodInstance* methodInstance);
@ -2075,7 +2082,8 @@ public:
BfIRValue CreateTypeDataRef(BfType* type); BfIRValue CreateTypeDataRef(BfType* type);
void EncodeAttributeData(BfTypeInstance* typeInstance, BfType* argType, BfIRValue arg, SizedArrayImpl<uint8>& data, Dictionary<int, int>& usedStringIdMap); void EncodeAttributeData(BfTypeInstance* typeInstance, BfType* argType, BfIRValue arg, SizedArrayImpl<uint8>& data, Dictionary<int, int>& usedStringIdMap);
BfIRValue CreateFieldData(BfFieldInstance* fieldInstance, int customAttrIdx); 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); BfIRValue FixClassVData(BfIRValue value);
public: public:

View file

@ -410,7 +410,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, mIgnoreErrors || ignoreErrors); SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, mIgnoreErrors || ignoreErrors);
genericTypeInst->mGenericTypeInfo->mValidatedGenericConstraints = true; genericTypeInst->mGenericTypeInfo->mValidatedGenericConstraints = true;
if (!genericTypeInst->mGenericTypeInfo->mFinishedGenericParams) if (!genericTypeInst->mGenericTypeInfo->mFinishedGenericParams)
PopulateType(genericTypeInst, BfPopulateType_Interfaces_All); mContext->mUnreifiedModule->PopulateType(genericTypeInst, BfPopulateType_Interfaces_All);
if (genericTypeInst->IsTypeAlias()) if (genericTypeInst->IsTypeAlias())
{ {
@ -418,7 +418,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
if ((underlyingType != NULL) && (underlyingType->IsGenericTypeInstance())) if ((underlyingType != NULL) && (underlyingType->IsGenericTypeInstance()))
{ {
auto underlyingGenericType = underlyingType->ToGenericTypeInstance(); auto underlyingGenericType = underlyingType->ToGenericTypeInstance();
PopulateType(underlyingType, BfPopulateType_Declaration); mContext->mUnreifiedModule->PopulateType(underlyingType, BfPopulateType_Declaration);
bool result = ValidateGenericConstraints(typeRef, underlyingGenericType, ignoreErrors); bool result = ValidateGenericConstraints(typeRef, underlyingGenericType, ignoreErrors);
if (underlyingGenericType->mGenericTypeInfo->mHadValidateErrors) if (underlyingGenericType->mGenericTypeInfo->mHadValidateErrors)
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true; genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
@ -441,7 +441,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
{ {
startGenericParamIdx = typeDef->mOuterType->mGenericParamDefs.mSize + typeDef->mOuterType->mExternalConstraints.mSize; startGenericParamIdx = typeDef->mOuterType->mGenericParamDefs.mSize + typeDef->mOuterType->mExternalConstraints.mSize;
auto outerType = GetOuterType(genericTypeInst); auto outerType = GetOuterType(genericTypeInst);
PopulateType(outerType, BfPopulateType_Declaration); mContext->mUnreifiedModule->PopulateType(outerType, BfPopulateType_Declaration);
if ((outerType->mGenericTypeInfo != NULL) && (outerType->mGenericTypeInfo->mHadValidateErrors)) if ((outerType->mGenericTypeInfo != NULL) && (outerType->mGenericTypeInfo->mHadValidateErrors))
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true; genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
} }
@ -802,6 +802,11 @@ void BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType)
return; 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); 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 // 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; 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) if (canFastReify)
{ {
BfLogSysM("Setting reified type %p in module %p in PopulateType on module awaiting finish\n", resolvedTypeRef, typeModule); 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<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, 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; bool isNew = resolvedTypeRef->mDefineState == BfTypeDefineState_Undefined;
if (isNew) if (isNew)
@ -8268,7 +8291,7 @@ BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType
auto typeDefTypeRef = mContext->mTypeDefTypeRefPool.Get(); auto typeDefTypeRef = mContext->mTypeDefTypeRefPool.Get();
typeDefTypeRef->mTypeDef = typeDef; typeDefTypeRef->mTypeDef = typeDef;
auto resolvedtypeDefType = ResolveTypeRef(typeDefTypeRef, populateType); auto resolvedtypeDefType = ResolveTypeRef(typeDefTypeRef, populateType, resolveFlags);
if (resolvedtypeDefType == NULL) if (resolvedtypeDefType == NULL)
{ {
mContext->mTypeDefTypeRefPool.GiveBack(typeDefTypeRef); 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); 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)) if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(typeRef))
{ {
@ -12648,7 +12671,7 @@ BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, B
BfTypeVector typeVector; BfTypeVector typeVector;
for (int i = 0; i < (int)genericTypeDef->mGenericParamDefs.size(); i++) for (int i = 0; i < (int)genericTypeDef->mGenericParamDefs.size(); i++)
typeVector.push_back(GetGenericParamType(BfGenericParamKind_Type, 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())) if ((result != NULL) && (genericTypeRef->mCommas.size() + 1 != genericTypeDef->mGenericParamDefs.size()))
{ {
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, result->ToTypeInstance()); SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, result->ToTypeInstance());

View file

@ -1270,11 +1270,12 @@ bool BfMethodInstance::WasGenericParam(int paramIdx)
bool BfMethodInstance::IsParamSkipped(int paramIdx) bool BfMethodInstance::IsParamSkipped(int paramIdx)
{ {
auto resolveModule = GetModule()->mContext->mUnreifiedModule;
if (paramIdx == -1) if (paramIdx == -1)
return false; return false;
BfType* paramType = GetParamType(paramIdx); BfType* paramType = GetParamType(paramIdx);
if ((paramType->CanBeValuelessType()) && (paramType->IsDataIncomplete())) if ((paramType->CanBeValuelessType()) && (paramType->IsDataIncomplete()))
GetModule()->PopulateType(paramType, BfPopulateType_Data); resolveModule->PopulateType(paramType, BfPopulateType_Data);
if ((paramType->IsValuelessType()) && (!paramType->IsMethodRef())) if ((paramType->IsValuelessType()) && (!paramType->IsMethodRef()))
return true; return true;
return false; return false;
@ -1344,7 +1345,7 @@ int BfMethodInstance::DbgGetVirtualMethodNum()
module->HadSlotCountDependency(); module->HadSlotCountDependency();
int vDataIdx = -1; int vDataIdx = -1;
vDataIdx = 1 + module->mCompiler->mMaxInterfaceSlots; vDataIdx = module->mCompiler->GetVDataPrefixDataCount() + module->mCompiler->mMaxInterfaceSlots;
vDataIdx += module->mCompiler->GetDynCastVDataCount(); vDataIdx += module->mCompiler->GetDynCastVDataCount();
if ((module->mCompiler->mOptions.mHasVDataExtender) && (module->mCompiler->IsHotCompile())) 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) 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 loweredReturnTypeCode = BfTypeCode_None;
BfTypeCode loweredReturnTypeCode2 = BfTypeCode_None; BfTypeCode loweredReturnTypeCode2 = BfTypeCode_None;
@ -1459,7 +1462,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
else else
{ {
if ((checkType->IsComposite()) && (checkType->IsIncomplete())) if ((checkType->IsComposite()) && (checkType->IsIncomplete()))
module->PopulateType(checkType, BfPopulateType_Data); resolveModule->PopulateType(checkType, BfPopulateType_Data);
if (checkType->IsMethodRef()) if (checkType->IsMethodRef())
{ {
@ -1492,7 +1495,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
} }
if (checkType->CanBeValuelessType()) if (checkType->CanBeValuelessType())
module->PopulateType(checkType, BfPopulateType_Data); resolveModule->PopulateType(checkType, BfPopulateType_Data);
if ((checkType->IsValuelessType()) && (!checkType->IsMethodRef())) if ((checkType->IsValuelessType()) && (!checkType->IsMethodRef()))
continue; continue;

View file

@ -6714,7 +6714,8 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
PopulateType(itrInterface, BfPopulateType_Full_Force); PopulateType(itrInterface, BfPopulateType_Full_Force);
getNextMethodInst = GetMethodByName(itrInterface, "GetNext"); getNextMethodInst = GetMethodByName(itrInterface, "GetNext");
} }
BF_ASSERT(getNextMethodInst); if (getNextMethodInst)
{
nextResult = BfTypedValue(CreateAlloca(getNextMethodInst.mMethodInstance->mReturnType), getNextMethodInst.mMethodInstance->mReturnType, true); nextResult = BfTypedValue(CreateAlloca(getNextMethodInst.mMethodInstance->mReturnType), getNextMethodInst.mMethodInstance->mReturnType, true);
if (nextResult.mType->IsGenericTypeInstance()) if (nextResult.mType->IsGenericTypeInstance())
@ -6722,6 +6723,11 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
nextEmbeddedType = ((BfTypeInstance*)nextResult.mType)->mGenericTypeInfo->mTypeGenericArguments[0]; nextEmbeddedType = ((BfTypeInstance*)nextResult.mType)->mGenericTypeInfo->mTypeGenericArguments[0];
} }
} }
else
{
InternalError("Failed to find GetNext");
}
}
if (nextEmbeddedType == NULL) if (nextEmbeddedType == NULL)
nextEmbeddedType = GetPrimitiveType(BfTypeCode_Var); nextEmbeddedType = GetPrimitiveType(BfTypeCode_Var);

View file

@ -3865,8 +3865,8 @@ addr_ce CeContext::GetReflectType(int typeId)
if (bfType->mDefineState != BfTypeDefineState_CETypeInit) if (bfType->mDefineState != BfTypeDefineState_CETypeInit)
ceModule->PopulateType(bfType, BfPopulateType_DataAndMethods); ceModule->PopulateType(bfType, BfPopulateType_DataAndMethods);
Dictionary<int, int> usedStringMap; BfCreateTypeDataContext createTypeDataCtx;
auto irData = ceModule->CreateTypeData(bfType, usedStringMap, true, true, true, false); auto irData = ceModule->CreateTypeData(bfType, createTypeDataCtx, true, true, true, false);
BeValue* beValue = NULL; BeValue* beValue = NULL;
if (auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(irData)) if (auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(irData))

View file

@ -833,6 +833,11 @@ bool DbgSubprogram::IsLambda()
return StringView(mName).Contains('$'); return StringView(mName).Contains('$');
} }
int DbgSubprogram::GetByteCount()
{
return (int)(mBlock.mHighPC - mBlock.mLowPC);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
DbgSubprogram::~DbgSubprogram() DbgSubprogram::~DbgSubprogram()
@ -5783,7 +5788,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
Array<PESectionHeader> sectionHeaders; Array<PESectionHeader> sectionHeaders;
sectionHeaders.Resize(ntHdr.mFileHeader.mNumberOfSections); sectionHeaders.Resize(ntHdr.mFileHeader.mNumberOfSections);
mSectionRVAs.Resize(sectionHeaders.size() + 1); mSectionHeaders.Resize(sectionHeaders.size() + 1);
Array<String> sectionNames; Array<String> sectionNames;
sectionNames.Resize(ntHdr.mFileHeader.mNumberOfSections); 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++) for (int sectNum = 0; sectNum < ntHdr.mFileHeader.mNumberOfSections; sectNum++)
{ {
mSectionRVAs[sectNum] = sectionHeaders[sectNum].mVirtualAddress; mSectionHeaders[sectNum] = sectionHeaders[sectNum];
} }
int tlsSection = -1; int tlsSection = -1;
@ -5827,6 +5832,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
} }
DbgSection dwSection; DbgSection dwSection;
dwSection.mName = name;
dwSection.mIsExecutable = (sectHdr.mCharacteristics & IMAGE_SCN_MEM_EXECUTE) != 0; dwSection.mIsExecutable = (sectHdr.mCharacteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
dwSection.mAddrStart = sectHdr.mVirtualAddress; dwSection.mAddrStart = sectHdr.mVirtualAddress;
dwSection.mAddrLength = BF_MAX(sectHdr.mSizeOfRawData, sectHdr.mVirtualSize); dwSection.mAddrLength = BF_MAX(sectHdr.mSizeOfRawData, sectHdr.mVirtualSize);
@ -6290,7 +6296,7 @@ bool DbgModule::ReadCOFF(DataStream* stream, DbgModuleKind moduleKind)
} }
} }
else else
targetAddr = mSectionRVAs[symInfo->mSectionNum - 1] + symInfo->mValue; targetAddr = mSectionHeaders[symInfo->mSectionNum - 1].mVirtualAddress + symInfo->mValue;
if (((targetAddr != 0) || (isTLS)) && if (((targetAddr != 0) || (isTLS)) &&
(name[0] != '.')) (name[0] != '.'))

View file

@ -442,6 +442,7 @@ public:
bool IsGenericMethod(); bool IsGenericMethod();
bool ThisIsSplat(); bool ThisIsSplat();
bool IsLambda(); bool IsLambda();
int GetByteCount();
DbgSubprogram* GetRootInlineParent() DbgSubprogram* GetRootInlineParent()
{ {
@ -823,6 +824,7 @@ public:
addr_target mAddress; addr_target mAddress;
int mCompileUnitId; int mCompileUnitId;
int mLength; int mLength;
int mSection;
}; };
class DbgCompileUnit class DbgCompileUnit
@ -874,6 +876,7 @@ public:
class DbgSection class DbgSection
{ {
public: public:
String mName;
addr_target mAddrStart; addr_target mAddrStart;
addr_target mAddrLength; addr_target mAddrLength;
bool mWritingEnabled; bool mWritingEnabled;
@ -1183,7 +1186,7 @@ public:
bool mIsDwarf64; bool mIsDwarf64;
HashSet<DbgSrcFile*> mSrcFileDeferredRefs; HashSet<DbgSrcFile*> mSrcFileDeferredRefs;
Array<addr_target> mSectionRVAs; Array<PESectionHeader> mSectionHeaders;
SLIList<DbgSymbol*> mDeferredSymbols; SLIList<DbgSymbol*> mDeferredSymbols;
Beefy::OwnedVector<DbgDeferredHotResolve> mDeferredHotResolveList; Beefy::OwnedVector<DbgDeferredHotResolve> mDeferredHotResolveList;
Array<DbgHotTargetSection*> mHotTargetSections; Array<DbgHotTargetSection*> mHotTargetSections;

View file

@ -1548,6 +1548,13 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetModulesInfo()
return outString.c_str(); 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() BF_EXPORT void BF_CALLTYPE Debugger_CancelSymSrv()
{ {
gDebugger->CancelSymSrv(); gDebugger->CancelSymSrv();

View file

@ -343,6 +343,7 @@ public:
virtual String FindLineCallAddresses(intptr address) = 0; virtual String FindLineCallAddresses(intptr address) = 0;
virtual String GetCurrentException() = 0; virtual String GetCurrentException() = 0;
virtual String GetModulesInfo() = 0; virtual String GetModulesInfo() = 0;
virtual String GetModuleInfo(const StringImpl& moduleName) { return ""; }
virtual void SetAliasPath(const StringImpl& origPath, const StringImpl& localPath) = 0; virtual void SetAliasPath(const StringImpl& origPath, const StringImpl& localPath) = 0;
virtual void CancelSymSrv() = 0; virtual void CancelSymSrv() = 0;
virtual bool HasPendingDebugLoads() = 0; virtual bool HasPendingDebugLoads() = 0;

View file

@ -8,6 +8,8 @@ USING_NS_BF_DBG;
DbgHotScanner::DbgHotScanner(WinDebugger* debugger) DbgHotScanner::DbgHotScanner(WinDebugger* debugger)
{ {
mDebugger = debugger; mDebugger = debugger;
mBfTypesInfoAddr = 0;
mDbgGCData = { 0 };
} }
NS_BF_DBG_BEGIN NS_BF_DBG_BEGIN
@ -255,7 +257,11 @@ void DbgHotScanner::ScanSpan(TCFake::Span* span, int expectedStartPage, int memK
int* typeIdPtr = NULL; int* typeIdPtr = NULL;
if (mFoundClassVDataAddrs.TryAdd(classVDataAddr, NULL, &typeIdPtr)) 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; Fake_Type_Data typeData;
mDebugger->ReadMemory(typeAddr + objectSize, sizeof(typeData), &typeData); mDebugger->ReadMemory(typeAddr + objectSize, sizeof(typeData), &typeData);
@ -272,6 +278,7 @@ void DbgHotScanner::ScanSpan(TCFake::Span* span, int expectedStartPage, int memK
} }
} }
} }
}
else else
{ {
_MarkTypeUsed(*typeIdPtr, elementSize); _MarkTypeUsed(*typeIdPtr, elementSize);
@ -358,6 +365,7 @@ void DbgHotScanner::Scan(DbgHotResolveFlags flags)
{ {
if ((module->mFilePath.Contains("Beef")) && (module->mFilePath.Contains("Dbg"))) if ((module->mFilePath.Contains("Beef")) && (module->mFilePath.Contains("Dbg")))
{ {
module->ParseTypeData();
module->ParseSymbolData(); module->ParseSymbolData();
auto entry = module->mSymbolNameMap.Find("gGCDbgData"); auto entry = module->mSymbolNameMap.Find("gGCDbgData");
if ((entry != NULL) && (entry->mValue != NULL)) 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) if (gcDbgDataAddr == 0)
return; return;

View file

@ -84,6 +84,7 @@ class DbgHotScanner
public: public:
WinDebugger* mDebugger; WinDebugger* mDebugger;
DbgGCData mDbgGCData; DbgGCData mDbgGCData;
addr_target mBfTypesInfoAddr;
Beefy::Dictionary<addr_target, int> mFoundClassVDataAddrs; Beefy::Dictionary<addr_target, int> mFoundClassVDataAddrs;
Beefy::Dictionary<addr_target, int> mFoundRawAllocDataAddrs; Beefy::Dictionary<addr_target, int> mFoundRawAllocDataAddrs;
Beefy::Dictionary<addr_target, int> mFoundTypeAddrs; Beefy::Dictionary<addr_target, int> mFoundTypeAddrs;

View file

@ -8,6 +8,9 @@ StartupProject = "Tests"
[Configs.Debug.Win64] [Configs.Debug.Win64]
IntermediateType = "ObjectAndIRCode" IntermediateType = "ObjectAndIRCode"
[Configs.Debug.Win32]
IntermediateType = "ObjectAndIRCode"
[Configs.Test.Win64] [Configs.Test.Win64]
IntermediateType = "ObjectAndIRCode" IntermediateType = "ObjectAndIRCode"
COptimizationLevel = "O2" COptimizationLevel = "O2"

View file

@ -12872,6 +12872,210 @@ String WinDebugger::GetModulesInfo()
return str; 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() void WinDebugger::CancelSymSrv()
{ {
AutoCrit autoCrit(mDebugManager->mCritSect); AutoCrit autoCrit(mDebugManager->mCritSect);

View file

@ -656,6 +656,7 @@ public:
virtual String GetCurrentException() override; virtual String GetCurrentException() override;
virtual void SetAliasPath(const StringImpl& origPath, const StringImpl& localPath) override; virtual void SetAliasPath(const StringImpl& origPath, const StringImpl& localPath) override;
virtual String GetModulesInfo() override; virtual String GetModulesInfo() override;
virtual String GetModuleInfo(const StringImpl& moduleName) override;
virtual void CancelSymSrv() override; virtual void CancelSymSrv() override;
virtual bool HasPendingDebugLoads() override; virtual bool HasPendingDebugLoads() override;
virtual int LoadImageForModule(const StringImpl& moduleName, const StringImpl& debugFileName) override; virtual int LoadImageForModule(const StringImpl& moduleName, const StringImpl& debugFileName) override;

View file

@ -1,4 +1,3 @@
@ECHO --------------------------- Beef Test_Build.Bat Version 1 --------------------------- @ECHO --------------------------- Beef Test_Build.Bat Version 1 ---------------------------
@SET P4_CHANGELIST=%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 IDE\dist\BeefBuild_d -proddir=BeefLibs\corlib -test
@IF %ERRORLEVEL% NEQ 0 GOTO HADERROR @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 @ECHO Building BeefIDE_d with BeefBuild_d
bin\RunAndWait IDE\dist\BeefPerf.exe -cmd="Nop()" bin\RunAndWait IDE\dist\BeefPerf.exe -cmd="Nop()"
@IF %ERRORLEVEL% NEQ 0 GOTO FAILPERF_START @IF %ERRORLEVEL% NEQ 0 GOTO FAILPERF_START