1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Extensive runtime refactor to reduce generated executable sizes

This commit is contained in:
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 const int32 number = 0x00010803;
#if BF_64_BIT
public const String dll = "fmod64.dll";
#else
public const int32 number = 0x00020220;
public const String dll = "fmod.dll";
#endif
}
public class CONSTANTS
@ -1385,7 +1381,7 @@ namespace FMOD
public int fileuserdata; /* [w] Optional. Specify 0 to ignore. User data to be passed into the file callbacks. */
public int32 filebuffersize; /* [w] Optional. Specify 0 to ignore. Buffer size for reading the file, -1 to disable buffering, or 0 for system default. */
public CHANNELORDER channelorder; /* [w] Optional. Specify 0 to ignore. Use this to differ the way fmod maps multichannel sounds to speakers. See FMOD_CHANNELORDER for more. */
public CHANNELMASK channelmask; /* [w] Optional. Specify 0 to ignore. Use this to differ the way fmod maps multichannel sounds to speakers. See FMOD_CHANNELMASK for more. */
//public CHANNELMASK channelmask; /* [w] Optional. Specify 0 to ignore. Use this to differ the way fmod maps multichannel sounds to speakers. See FMOD_CHANNELMASK for more. */
public int initialsoundgroup; /* [w] Optional. Specify 0 to ignore. Specify a sound group if required, to put sound in as it is created. */
public uint32 initialseekposition; /* [w] Optional. Specify 0 to ignore. For streams. Specify an initial position to seek the stream to. */
public TIMEUNIT initialseekpostype; /* [w] Optional. Specify 0 to ignore. For streams. Specify the time unit for the position set in initialseekposition. */
@ -1587,7 +1583,7 @@ namespace FMOD
RESULT result = RESULT.OK;
int rawPtr = 0;
result = FMOD_System_Create(out rawPtr);
result = FMOD_System_Create(out rawPtr, VERSION.number);
if (result != RESULT.OK)
{
return result;
@ -1602,7 +1598,7 @@ namespace FMOD
#region importfunctions
[Import(VERSION.dll), CLink, CallingConvention(.Stdcall)]
private static extern RESULT FMOD_System_Create (out int system);
private static extern RESULT FMOD_System_Create (out int system, uint headerversion);
#endregion
}
@ -2008,6 +2004,7 @@ namespace FMOD
stringData = name.CStr();
exinfo.cbsize = (int32)sizeof(CREATESOUNDEXINFO);
//int offset = offsetof(CREATESOUNDEXINFO, channelmask);
int soundraw;
RESULT result = FMOD_System_CreateSound(rawPtr, stringData, mode, ref exinfo, out soundraw);

View file

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

View file

@ -13,8 +13,38 @@ namespace System
CtrlBreak
}
static Encoding InputEncoding = Encoding.ASCII;
static Encoding OutputEncoding = Encoding.ASCII;
public struct CancelInfo
{
public static Event<delegate void (CancelKind cancelKind, ref bool terminate)> sOnCancel ~ _.Dispose();
public static bool sCancelEventRegistered;
}
static Encoding sInputEncoding;
static Encoding sOutputEncoding;
static Encoding InputEncoding
{
get
{
return sInputEncoding ?? Encoding.ASCII;
}
set
{
sInputEncoding = value;
}
}
static Encoding OutputEncoding
{
get
{
return sOutputEncoding ?? Encoding.ASCII;
}
set
{
SetupOutStringEx();
sOutputEncoding = value;
}
}
static ConsoleColor sForegroundColor = .White;
static ConsoleColor sBackgroundColor = .Black;
@ -22,9 +52,6 @@ namespace System
static readonly ConsoleColor sOriginalForegroundColor = sForegroundColor;
static readonly ConsoleColor sOriginalBackgroundColor = sBackgroundColor;
static Event<delegate void (CancelKind cancelKind, ref bool terminate)> sOnCancel ~ _.Dispose();
static bool sCancelEventRegistered;
public static ConsoleColor ForegroundColor
{
get { return sForegroundColor; }
@ -56,18 +83,39 @@ namespace System
{
}
static void SetupOutStringEx()
{
OutString = => OutString_Ex;
}
static function void(StringView str) OutString = => OutString_Simple;
[CLink, CallingConvention(.Cdecl)]
static extern void putchar(char8 c);
static void OutString_Simple(StringView str)
{
for (var c in str.RawChars)
putchar(c);
}
static void OutString_Ex(StringView str)
{
Out.Write(str).IgnoreError();
}
public static ref Event<delegate void (CancelKind cancelKind, ref bool terminate)> OnCancel
{
get
{
if (!sCancelEventRegistered)
if (!CancelInfo.sCancelEventRegistered)
{
sCancelEventRegistered = true;
CancelInfo.sCancelEventRegistered = true;
#if BF_PLATFORM_WINDOWS
SetConsoleCtrlHandler(=> ConsoleCtrlHandler, true);
#endif
}
return ref sOnCancel;
return ref CancelInfo.sOnCancel;
}
}
@ -77,7 +125,7 @@ namespace System
{
bool terminate = true;
if ((ctrlType == 0) || (ctrlType == 1))
sOnCancel((.)ctrlType, ref terminate);
CancelInfo.sOnCancel((.)ctrlType, ref terminate);
return terminate ? false : true;
}
@ -286,7 +334,7 @@ namespace System
public static void Write(StringView line)
{
Out.Write(line).IgnoreError();
OutString(line);
}
public static void Write(StringView fmt, params Object[] args)
@ -308,12 +356,13 @@ namespace System
public static void WriteLine()
{
Out.Write("\n").IgnoreError();
OutString("\n");
}
public static void WriteLine(StringView line)
{
Out.WriteLine(line).IgnoreError();
OutString(line);
OutString("\n");
}
public static void WriteLine(StringView fmt, params Object[] args)

View file

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

View file

@ -9,10 +9,16 @@ namespace System.Diagnostics
{
if (!condition)
{
if (Runtime.CheckErrorHandlers(scope Runtime.AssertError(.Debug, error, filePath, line)) == .Ignore)
if ((Runtime.CheckAssertError != null) && (Runtime.CheckAssertError(.Debug, error, filePath, line) == .Ignore))
return;
String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath);
#if !BF_RUNTIME_REDUCED
String failStr = scope .()..Append("Assert failed: ", error, " at line ");
line.ToString(failStr);
failStr.Append(" in ", filePath);
Internal.FatalError(failStr, 1);
#else
Internal.FatalError("Assert failed", 1);
#endif
}
}
@ -21,7 +27,9 @@ namespace System.Diagnostics
#endif
public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
{
String failStr = scope .()..AppendF("{} at line {} in {}", msg, line, filePath);
String failStr = scope .()..Append(msg, " at line ");
line.ToString(failStr);
failStr.Append(" in ", filePath);
Internal.FatalError(failStr, 1);
}
@ -87,7 +95,7 @@ namespace System.Diagnostics
}
static bool gIsDebuggerPresent = IsDebuggerPresent;
[LinkName("IsDebuggerPresent"), CallingConvention(.Stdcall)]
[LinkName("IsDebuggerPresent"), CallingConvention(.Stdcall), Import("kernel32.lib")]
static extern int32 Internal_IsDebuggerPresent();
public static bool IsDebuggerPresent

View file

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

View file

@ -1,6 +1,7 @@
using System.IO;
using System.Collections;
using System.Text;
using System.Threading;
namespace System
{
@ -12,7 +13,23 @@ namespace System
public static readonly String NewLine = "\n";
#endif // BF_PLATFORM_WINDOWS
public static OperatingSystem OSVersion = new OperatingSystem() ~ delete _;
static OperatingSystem sOSVersion ~ delete _;
public static OperatingSystem OSVersion
{
get
{
var osVersion = new OperatingSystem();
let prevValue = Interlocked.CompareExchange(ref sOSVersion, null, osVersion);
if (prevValue != null)
{
// This was already set - race condition
delete osVersion;
return prevValue;
}
return osVersion;
}
}
public static void* ModuleHandle => Internal.[Friend]sModuleHandle;

View file

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

View file

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

View file

@ -13,6 +13,14 @@ namespace System
case InvalidChar(int partialResult);
}
public struct Simple : int
{
public override void ToString(String strBuffer)
{
((int)this).ToString(strBuffer);
}
}
public const int MaxValue = (sizeof(int) == 8) ? 0x7FFFFFFFFFFFFFFFL : 0x7FFFFFFF;
public const int MinValue = (sizeof(int) == 8) ? -0x8000000000000000L : -0x80000000;

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)
{
if(format == null || format.IsEmpty)

View file

@ -81,12 +81,6 @@ namespace System
public static extern Object UnsafeCastToObject(void* ptr);
[Intrinsic("cast")]
public static extern void* UnsafeCastToPtr(Object obj);
[CallingConvention(.Cdecl), NoReturn]
public static extern void ThrowIndexOutOfRange(int stackOffset = 0);
[CallingConvention(.Cdecl), NoReturn]
public static extern void ThrowObjectNotInitialized(int stackOffset = 0);
[CallingConvention(.Cdecl), NoReturn]
public static extern void FatalError(String error, int stackOffset = 0);
[Intrinsic("memcpy")]
public static extern void MemCpy(void* dest, void* src, int length, int32 align = 1, bool isVolatile = false);
[Intrinsic("memmove")]
@ -103,6 +97,32 @@ namespace System
public static extern void StdFree(void* ptr);
[Intrinsic("returnaddress")]
public static extern void* GetReturnAddress(int32 level = 0);
[CallingConvention(.Cdecl)]
static extern void Test_Init(char8* testData);
[CallingConvention(.Cdecl)]
static extern void Test_Error(char8* error);
[CallingConvention(.Cdecl)]
static extern void Test_Write(char8* str);
[CallingConvention(.Cdecl)]
static extern int32 Test_Query();
[CallingConvention(.Cdecl)]
static extern void Test_Finish();
static void* sModuleHandle;
[AlwaysInclude]
static void SetModuleHandle(void* handle)
{
sModuleHandle = handle;
}
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Cdecl), NoReturn]
public static extern void ThrowIndexOutOfRange(int stackOffset = 0);
[CallingConvention(.Cdecl), NoReturn]
public static extern void ThrowObjectNotInitialized(int stackOffset = 0);
[CallingConvention(.Cdecl), NoReturn]
public static extern void FatalError(String error, int stackOffset = 0);
[CallingConvention(.Cdecl)]
public static extern void* VirtualAlloc(int size, bool canExecute, bool canWrite);
[CallingConvention(.Cdecl)]
@ -160,25 +180,236 @@ namespace System
[CallingConvention(.Cdecl)]
public static extern void Dbg_RawFree(void* ptr);
[CallingConvention(.Cdecl), AlwaysInclude]
static extern void Shutdown();
[CallingConvention(.Cdecl)]
static extern void Test_Init(char8* testData);
[CallingConvention(.Cdecl)]
static extern void Test_Error(char8* error);
[CallingConvention(.Cdecl)]
static extern void Test_Write(char8* str);
[CallingConvention(.Cdecl)]
static extern int32 Test_Query();
[CallingConvention(.Cdecl)]
static extern void Test_Finish();
static extern void Shutdown_Internal();
static void* sModuleHandle;
[AlwaysInclude]
static void SetModuleHandle(void* handle)
[CallingConvention(.Cdecl), AlwaysInclude]
static void Shutdown()
{
sModuleHandle = handle;
Shutdown_Internal();
Runtime.Shutdown();
}
#else
enum BfObjectFlags : uint8
{
None = 0,
Mark1 = 0x01,
Mark2 = 0x02,
Mark3 = 0x03,
Allocated = 0x04,
StackAlloc = 0x08,
AppendAlloc = 0x10,
AllocInfo = 0x20,
AllocInfo_Short = 0x40,
Deleted = 0x80
};
[NoReturn]
static void Crash()
{
char8* ptr = null;
*ptr = 'A';
}
[AlwaysInclude, NoReturn]
public static void ThrowIndexOutOfRange(int stackOffset = 0)
{
Crash();
}
[AlwaysInclude, NoReturn]
public static void ThrowObjectNotInitialized(int stackOffset = 0)
{
Crash();
}
[AlwaysInclude, NoReturn]
public static void FatalError(String error, int stackOffset = 0)
{
Crash();
}
[AlwaysInclude]
public static void* VirtualAlloc(int size, bool canExecute, bool canWrite)
{
return null;
}
public static int32 CStrLen(char8* charPtr)
{
int32 len = 0;
while (charPtr[len] != 0)
len++;
return len;
}
public static int64 GetTickCountMicro()
{
return 0;
}
[AlwaysInclude]
public static void BfDelegateTargetCheck(void* target)
{
}
[AlwaysInclude]
public static void* LoadSharedLibrary(char8* filePath)
{
return null;
}
[AlwaysInclude]
public static void LoadSharedLibraryInto(char8* filePath, void** libDest)
{
}
[AlwaysInclude]
public static void* GetSharedProcAddress(void* libHandle, char8* procName)
{
return null;
}
[AlwaysInclude]
public static void GetSharedProcAddressInto(void* libHandle, char8* procName, void** procDest)
{
}
[AlwaysInclude]
public static char8* GetCommandLineArgs()
{
return "";
}
public static void ProfilerCmd(char8* str)
{
}
public static void ReportMemory()
{
}
public static void ObjectDynCheck(Object obj, int32 typeId, bool allowNull)
{
}
public static void ObjectDynCheckFailed(Object obj, int32 typeId)
{
}
[DisableChecks, DisableObjectAccessChecks]
public static void Dbg_ObjectCreated(Object obj, int size, ClassVData* classVData)
{
}
[DisableChecks, DisableObjectAccessChecks]
public static void Dbg_ObjectCreatedEx(Object obj, int size, ClassVData* classVData)
{
}
[DisableChecks, DisableObjectAccessChecks]
public static void Dbg_ObjectAllocated(Object obj, int size, ClassVData* classVData)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
obj.[Friend]mClassVData = (.)(void*)classVData;
obj.[Friend]mDbgAllocInfo = (.)GetReturnAddress(0);
#else
obj.[Friend]mClassVData = classVData;
#endif
}
[DisableChecks, DisableObjectAccessChecks]
public static void Dbg_ObjectAllocatedEx(Object obj, int size, ClassVData* classVData)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
obj.[Friend]mClassVData = (.)(void*)classVData;
obj.[Friend]mDbgAllocInfo = (.)GetReturnAddress(0);
#else
obj.[Friend]mClassVData = classVData;
#endif
}
public static int Dbg_PrepareStackTrace(int baseAllocSize, int maxStackTraceDepth)
{
return 0;
}
[DisableChecks, DisableObjectAccessChecks]
public static void Dbg_ObjectStackInit(Object obj, ClassVData* classVData)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
obj.[Friend]mClassVData = (.)(void*)classVData;
obj.[Friend]mClassVData |= (.)BfObjectFlags.StackAlloc;
obj.[Friend]mDbgAllocInfo = (.)GetReturnAddress(0);
#else
obj.[Friend]mClassVData = classVData;
#endif
}
public static Object Dbg_ObjectAlloc(TypeInstance typeInst, int size)
{
return null;
}
public static Object Dbg_ObjectAlloc(ClassVData* classVData, int size, int align, int maxStackTraceDepth)
{
return null;
}
public static void Dbg_ObjectPreDelete(Object obj)
{
}
public static void Dbg_ObjectPreCustomDelete(Object obj)
{
}
public static void Dbg_MarkObjectDeleted(Object obj)
{
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
obj.[Friend]mClassVData |= (.)BfObjectFlags.Deleted;
#endif
}
public static void* Dbg_RawAlloc(int size)
{
return null;
}
public static void* Dbg_RawObjectAlloc(int size)
{
return null;
}
public static void* Dbg_RawAlloc(int size, DbgRawAllocData* rawAllocData)
{
return null;
}
public static void Dbg_RawFree(void* ptr)
{
}
[AlwaysInclude]
static void Shutdown()
{
}
#endif
[AlwaysInclude]
static void AddRtFlags(int32 flags)
{
@ -254,9 +485,9 @@ namespace System
}
}
[AlwaysInclude]
public static String[] CreateParamsArray()
{
#if !BF_RUNTIME_DISABLE
char8* cmdLine = GetCommandLineArgs();
//Windows.MessageBoxA(default, scope String()..AppendF("CmdLine: {0}", StringView(cmdLine)), "HI", 0);
@ -357,9 +588,11 @@ namespace System
}
return strVals;
#else
return new String[0];
#endif
}
[AlwaysInclude]
public static void DeleteStringArray(String[] arr)
{
for (var str in arr)
@ -367,8 +600,10 @@ namespace System
delete arr;
}
#if !BF_RUNTIME_DISABLE
extern static this();
extern static ~this();
#endif
}
struct CRTAlloc

View file

@ -224,6 +224,7 @@ namespace System
return intPart;
}
#if !BF_RUNTIME_DISABLE
public static extern float Sqrt(float f);
public static extern double Sqrt(double d);
public static extern float Cbrt(float f);
@ -236,6 +237,20 @@ namespace System
public static extern double Exp(double d);
public static extern float Pow(float x, float y);
public static extern double Pow(double x, double y);
#else
public static float Sqrt(float f) => Runtime.NotImplemented();
public static double Sqrt(double d) => Runtime.NotImplemented();
public static float Cbrt(float f) => Runtime.NotImplemented();
public static double Cbrt(double d) => Runtime.NotImplemented();
public static float Log(float f) => Runtime.NotImplemented();
public static double Log(double d) => Runtime.NotImplemented();
public static float Log10(float f) => Runtime.NotImplemented();
public static double Log10(double d) => Runtime.NotImplemented();
public static float Exp(float f) => Runtime.NotImplemented();
public static double Exp(double d) => Runtime.NotImplemented();
public static float Pow(float x, float y) => Runtime.NotImplemented();
public static double Pow(double x, double y) => Runtime.NotImplemented();
#endif
public static float IEEERemainder(float x, float y)
{

View file

@ -1130,12 +1130,14 @@ namespace System
// Hexadecimal digits representation.
private static uint32 FastToDecHex (int32 val)
{
var decHexDigits = DecHexDigits;
if (val < 100)
return (uint32)DecHexDigits [val];
return (uint32)decHexDigits[val];
// Uses 2^19 (524288) to compute val / 100 for val < 10000.
int32 v = (val * 5243) >> 19;
return (uint32)((DecHexDigits [v] << 8) | DecHexDigits [val - v * 100]);
return (uint32)((decHexDigits[v] << 8) | decHexDigits[val - v * 100]);
}
// Helper to translate an int in the range 0 .. 99999999 to its
@ -1741,6 +1743,31 @@ namespace System
inst.IntegerToString(format, fp, outString);
}
public static void AddrToString (uint value, String outString)
{
const int bufLen = 18;
char8* strChars = scope:: char8[bufLen]* (?);
int32 curLen = 0;
uint64 valLeft = (.)value;
while (valLeft > 0)
{
if (curLen == 8)
strChars[bufLen - curLen++ - 1] = '\'';
strChars[bufLen - curLen++ - 1] = DigitUpperTable[(int)(valLeft & 0xF)];
valLeft >>= 4;
}
while (curLen < 10)
{
if (curLen == 8)
strChars[bufLen - curLen++ - 1] = '\'';
strChars[bufLen - curLen++ - 1] = '0';
}
char8* char8Ptr = &strChars[bufLen - curLen];
outString.Append(char8Ptr, curLen);
}
public static void NumberToString (StringView format, int32 value, IFormatProvider fp, String outString)
{
NumberFormatter inst = GetInstance!(fp);

View file

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

View file

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

View file

@ -34,15 +34,29 @@ namespace System
NotEmpty
};
public struct BfpCritSect {}
public struct BfpSpawn {}
public struct BfpFile {}
public struct BfpFindFileData {}
public struct BfpDynLib {}
public struct BfpEvent {};
public struct BfpFileWatcher {}
public struct BfpProcess {}
public struct BfpTLS;
#if !BF_RUNTIME_DISABLE
public struct BfpCritSect {}
public struct BfpEvent {};
#else
public struct BfpCritSect
{
public int mEmpty;
}
public struct BfpEvent
{
public bool mSet;
public bool mAuto;
};
#endif
public enum BfpSystemResult : int32
{
@ -51,6 +65,7 @@ namespace System
TempFileError = (int)Result.TempFileError
}
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink]
public static extern uint32 BfpSystem_TickCount();
[CallingConvention(.Stdcall), CLink]
@ -107,6 +122,62 @@ namespace System
public static extern void BfpTLS_SetValue(BfpTLS* tls, void* value);
[CallingConvention(.Stdcall), CLink]
public static extern void* BfpTLS_GetValue(BfpTLS* tls);
#else
public static uint32 BfpSystem_TickCount() => Runtime.NotImplemented();
public static uint32 BfpSystem_SetCrashRelaunchCmd(char8* cmd) => Runtime.NotImplemented();
public static BfpTimeStamp BfpSystem_GetTimeStamp() => Runtime.NotImplemented();
public static uint8 BfpSystem_InterlockedExchange8(uint8* ptr, uint8 val) => Runtime.NotImplemented();
public static uint16 BfpSystem_InterlockedExchange16(uint16* ptr, uint16 val) => Runtime.NotImplemented();
public static uint32 BfpSystem_InterlockedExchange32(uint32* ptr, uint32 val) => Runtime.NotImplemented();
public static uint64 BfpSystem_InterlockedExchange64(uint64* ptr, uint64 val) => Runtime.NotImplemented();
public static uint8 BfpSystem_InterlockedExchangeAdd8(uint8* ptr, uint8 val) => Runtime.NotImplemented();
public static uint16 BfpSystem_InterlockedExchangeAdd16(uint16* ptr, uint16 val) => Runtime.NotImplemented(); /// Returns the initial value in 'ptr'
public static uint32 BfpSystem_InterlockedExchangeAdd32(uint32* ptr, uint32 val) => Runtime.NotImplemented(); /// Returns the initial value in 'ptr'
public static uint64 BfpSystem_InterlockedExchangeAdd64(uint64* ptr, uint64 val) => Runtime.NotImplemented();
public static uint8 BfpSystem_InterlockedCompareExchange8(uint8* ptr, uint8 oldVal, uint8 newVal) => Runtime.NotImplemented();
public static uint16 BfpSystem_InterlockedCompareExchange16(uint16* ptr, uint16 oldVal, uint16 newVal) => Runtime.NotImplemented();
public static uint32 BfpSystem_InterlockedCompareExchange32(uint32* ptr, uint32 oldVal, uint32 newVal) => Runtime.NotImplemented();
public static uint64 BfpSystem_InterlockedCompareExchange64(uint64* ptr, uint64 oldVal, uint64 newVal) => Runtime.NotImplemented();
public static void BfpSystem_GetExecutablePath(char8* outStr, int32* inOutStrSize, BfpSystemResult* outResult) => Runtime.NotImplemented();
public static void BfpSystem_GetEnvironmentStrings(char8* outStr, int32* inOutStrSize, BfpSystemResult* outResult) => Runtime.NotImplemented();
public static int32 BfpSystem_GetNumLogicalCPUs(BfpSystemResult* outResult) => Runtime.NotImplemented();
public static int64 BfpSystem_GetCPUTick() => Runtime.NotImplemented();
public static int64 BfpSystem_GetCPUTickFreq() => Runtime.NotImplemented();
public static void BfpSystem_CreateGUID(Guid* outGuid) => Runtime.NotImplemented();
public static void BfpSystem_GetComputerName(char8* outStr, int32* inOutStrSize, BfpSystemResult* outResult) => Runtime.NotImplemented();
public static int BfpThread_GetCurrentId() => Runtime.NotImplemented();
public static BfpTLS* BfpTLS_Create(function [CallingConvention(.Stdcall)] void(void*) exitProc) => Runtime.NotImplemented();
public static void BfpTLS_Release(BfpTLS* tls) => Runtime.NotImplemented();
public static void BfpTLS_SetValue(BfpTLS* tls, void* value) => Runtime.NotImplemented();
public static void* BfpTLS_GetValue(BfpTLS* tls) => Runtime.NotImplemented();
#endif
public enum BfpFileWatcherFlags : int32
{
@ -125,10 +196,16 @@ namespace System
public function void BfpDirectoryChangeFunc(BfpFileWatcher* watcher, void* userData, BfpFileChangeKind changeKind, char8* directory, char8* fileName, char8* oldName);
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink]
public static extern BfpFileWatcher* BfpFileWatcher_WatchDirectory(char8* path, BfpDirectoryChangeFunc callback, BfpFileWatcherFlags flags, void* userData, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink]
public static extern void BfpFileWatcher_Release(BfpFileWatcher* fileWatcher);
#else
public static BfpFileWatcher* BfpFileWatcher_WatchDirectory(char8* path, BfpDirectoryChangeFunc callback, BfpFileWatcherFlags flags, void* userData, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpFileWatcher_Release(BfpFileWatcher* fileWatcher) => Runtime.NotImplemented();
#endif
public enum BfpProcessResult : int32
{
@ -136,6 +213,7 @@ namespace System
InsufficientBuffer = (int)Result.InsufficientBuffer
}
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink]
public static extern bool BfpProcess_IsRemoteMachine(char8* machineName);
[CallingConvention(.Stdcall), CLink]
@ -150,6 +228,22 @@ namespace System
public static extern void BfpProcess_GetProcessName(BfpProcess* process, char8* outName, int32* inOutNameSize, BfpProcessResult* outResult);
[CallingConvention(.Stdcall), CLink]
public static extern int32 BfpProcess_GetProcessId(BfpProcess* process);
#else
public static bool BfpProcess_IsRemoteMachine(char8* machineName) => Runtime.NotImplemented();
public static BfpProcess* BfpProcess_GetById(char8* machineName, int32 processId, BfpProcessResult* outResult) => Runtime.NotImplemented();
public static void BfpProcess_Enumerate(char8* machineName, BfpProcess** outProcesses, int32* inOutProcessesSize, BfpProcessResult* outResult) => Runtime.NotImplemented();
public static void BfpProcess_Release(BfpProcess* process) => Runtime.NotImplemented();
public static void BfpProcess_GetMainWindowTitle(BfpProcess* process, char8* outTitle, int32* inOutTitleSize, BfpProcessResult* outResult) => Runtime.NotImplemented();
public static void BfpProcess_GetProcessName(BfpProcess* process, char8* outName, int32* inOutNameSize, BfpProcessResult* outResult) => Runtime.NotImplemented();
public static int32 BfpProcess_GetProcessId(BfpProcess* process) => Runtime.NotImplemented();
#endif
public enum BfpSpawnFlags : int32
{
@ -181,6 +275,7 @@ namespace System
UnknownError = (int)Result.UnknownError
};
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink]
public static extern BfpSpawn* BfpSpawn_Create(char8* targetPath, char8* args, char8* workingDir, char8* env, BfpSpawnFlags flags, BfpSpawnResult* outResult);
[CallingConvention(.Stdcall), CLink]
@ -205,6 +300,47 @@ namespace System
public static extern bool BfpCritSect_TryEnter(BfpCritSect* critSect, int32 waitMS);
[CallingConvention(.Stdcall), CLink]
public static extern void BfpCritSect_Leave(BfpCritSect* critSect);
#else
public static BfpSpawn* BfpSpawn_Create(char8* targetPath, char8* args, char8* workingDir, char8* env, BfpSpawnFlags flags, BfpSpawnResult* outResult)
{
*outResult = .UnknownError;
return null;
}
public static void BfpSpawn_Release(BfpSpawn* spawn) => Runtime.NotImplemented();
public static void BfpSpawn_Kill(BfpSpawn* spawn, int32 exitCode, BfpKillFlags killFlags, BfpSpawnResult* outResult) => Runtime.NotImplemented();
public static bool BfpSpawn_WaitFor(BfpSpawn* spawn, int waitMS, int* outExitCode, BfpSpawnResult* outResult) => Runtime.NotImplemented();
public static void BfpSpawn_GetStdHandles(BfpSpawn* spawn, BfpFile** outStdIn, BfpFile** outStdOut, BfpFile** outStdErr) => Runtime.NotImplemented();
public static int BfpProcess_GetCurrentId() => Runtime.NotImplemented();
public static BfpCritSect* BfpCritSect_Create() => new BfpCritSect();
public static void BfpCritSect_Release(BfpCritSect* critSect)
{
delete critSect;
}
public static void BfpCritSect_Enter(BfpCritSect* critSect)
{
}
public static bool BfpCritSect_TryEnter(BfpCritSect* critSect, int32 waitMS)
{
return true;
}
public static void BfpCritSect_Leave(BfpCritSect* critSect)
{
}
#endif
public enum BfpEventFlags : int32
{
@ -221,6 +357,7 @@ namespace System
BfpEventResult_NotSupported = (int)Result.NotSupported
};
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink]
public static extern BfpEvent* BfpEvent_Create(BfpEventFlags flags);
[CallingConvention(.Stdcall), CLink]
@ -231,6 +368,46 @@ namespace System
public static extern void BfpEvent_Reset(BfpEvent* event, BfpEventResult* outResult);
[CallingConvention(.Stdcall), CLink]
public static extern bool BfpEvent_WaitFor(BfpEvent* event, int32 waitMS);
#else
public static BfpEvent* BfpEvent_Create(BfpEventFlags flags)
{
var result = new BfpEvent();
result.mSet = flags.HasFlag(.InitiallySet_Auto) | flags.HasFlag(.InitiallySet_Manual);
result.mAuto = flags.HasFlag(.InitiallySet_Auto);
return result;
}
public static void BfpEvent_Release(BfpEvent* event)
{
delete event;
}
public static void BfpEvent_Set(BfpEvent* event, bool requireManualReset)
{
event.mSet = true;
event.mAuto = !requireManualReset;
}
public static void BfpEvent_Reset(BfpEvent* event, BfpEventResult* outResult)
{
event.mSet = false;
event.mAuto = false;
*outResult = .BfpEventResult_Ok;
}
public static bool BfpEvent_WaitFor(BfpEvent* event, int32 waitMS)
{
if (!event.mSet)
return false;
if (event.mAuto)
{
event.mSet = false;
event.mAuto = false;
}
return true;
}
#endif
public enum BfpLibResult : int32
{
@ -239,6 +416,7 @@ namespace System
InsufficientBuffer = (int)Result.InsufficientBuffer
};
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink]
public static extern BfpDynLib* BfpDynLib_Load(char8* fileName);
[CallingConvention(.Stdcall), CLink]
@ -247,6 +425,16 @@ namespace System
public static extern void BfpDynLib_GetFilePath(BfpDynLib* lib, char8* outPath, int32* inOutPathSize, BfpLibResult* outResult);
[CallingConvention(.Stdcall), CLink]
public static extern void* BfpDynLib_GetProcAddress(BfpDynLib* lib, char8* name);
#else
public static BfpDynLib* BfpDynLib_Load(char8* fileName) => Runtime.NotImplemented();
public static void BfpDynLib_Release(BfpDynLib* lib) => Runtime.NotImplemented();
public static void BfpDynLib_GetFilePath(BfpDynLib* lib, char8* outPath, int32* inOutPathSize, BfpLibResult* outResult) => Runtime.NotImplemented();
public static void* BfpDynLib_GetProcAddress(BfpDynLib* lib, char8* name) => Runtime.NotImplemented();
#endif
public enum BfpFileResult : int32
{
@ -265,6 +453,7 @@ namespace System
NotEmpty = (int)Result.NotEmpty,
};
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink]
public static extern void BfpDirectory_Create(char8* name, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink]
@ -279,6 +468,22 @@ namespace System
public static extern bool BfpDirectory_Exists(char8* path);
[CallingConvention(.Stdcall), CLink]
public static extern void BfpDirectory_GetSysDirectory(BfpSysDirectoryKind sysDirKind, char8* outPath, int32* inOutPathLen, BfpFileResult* outResult);
#else
public static void BfpDirectory_Create(char8* name, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpDirectory_Rename(char8* oldName, char8* newName, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpDirectory_Delete(char8* name, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpDirectory_GetCurrent(char8* outPath, int32* inOutPathSize, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpDirectory_SetCurrent(char8* path, BfpFileResult* outResult) => Runtime.NotImplemented();
public static bool BfpDirectory_Exists(char8* path) => Runtime.NotImplemented();
public static void BfpDirectory_GetSysDirectory(BfpSysDirectoryKind sysDirKind, char8* outPath, int32* inOutPathLen, BfpFileResult* outResult) => Runtime.NotImplemented();
#endif
public enum BfpFileCreateKind : int32
{
@ -347,6 +552,7 @@ namespace System
In
}
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink]
public static extern BfpFile* BfpFile_Create(char8* name, BfpFileCreateKind createKind, BfpFileCreateFlags createFlags, BfpFileAttributes createdFileAttrs, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink]
@ -389,6 +595,50 @@ namespace System
public static extern void BfpFile_GetFullPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink]
public static extern void BfpFile_GetActualPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult);
#else
public static BfpFile* BfpFile_Create(char8* name, BfpFileCreateKind createKind, BfpFileCreateFlags createFlags, BfpFileAttributes createdFileAttrs, BfpFileResult* outResult) => Runtime.NotImplemented();
public static BfpFile* BfpFile_GetStd(BfpFileStdKind kind, BfpFileResult* outResult) => Runtime.NotImplemented();
public static int BfpFile_GetSystemHandle(BfpFile* file) => Runtime.NotImplemented();
public static void BfpFile_Release(BfpFile* file) => Runtime.NotImplemented();
public static int BfpFile_Write(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult) => Runtime.NotImplemented();
public static int BfpFile_Read(BfpFile* file, void* buffer, int size, int timeoutMS, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpFile_Flush(BfpFile* file) => Runtime.NotImplemented();
public static int64 BfpFile_GetFileSize(BfpFile* file) => Runtime.NotImplemented();
public static int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind) => Runtime.NotImplemented();
public static void BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult) => Runtime.NotImplemented();
public static BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path) => Runtime.NotImplemented();
public static BfpFileAttributes BfpFile_GetAttributes(char8* path, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpFile_SetAttributes(char8* path, BfpFileAttributes attribs, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpFile_Copy(char8* oldPath, char8* newPath, BfpFileCopyKind copyKind, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpFile_Rename(char8* oldPath, char8* newPath, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpFile_Delete(char8* path, BfpFileResult* outResult) => Runtime.NotImplemented();
public static bool BfpFile_Exists(char8* path) => Runtime.NotImplemented();
public static void BfpFile_GetTempPath(char8* outPath, int32* inOutPathSize, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpFile_GetTempFileName(char8* outName, int32* inOutNameSize, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpFile_GetFullPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult) => Runtime.NotImplemented();
public static void BfpFile_GetActualPath(char8* inPath, char8* outPath, int32* inOutPathSize, BfpFileResult* outResult) => Runtime.NotImplemented();
#endif
public enum BfpFindFileFlags : int32
{
@ -397,6 +647,7 @@ namespace System
Directories = 2,
};
#if !BF_RUNTIME_DISABLE
[CallingConvention(.Stdcall), CLink]
public static extern BfpFindFileData* BfpFindFileData_FindFirstFile(char8* path, BfpFindFileFlags flags, BfpFileResult* outResult);
[CallingConvention(.Stdcall), CLink]
@ -415,6 +666,26 @@ namespace System
public static extern int64 BfpFindFileData_GetFileSize(BfpFindFileData* findData);
[CallingConvention(.Stdcall), CLink]
public static extern void BfpFindFileData_Release(BfpFindFileData* findData);
#else
public static BfpFindFileData* BfpFindFileData_FindFirstFile(char8* path, BfpFindFileFlags flags, BfpFileResult* outResult) => Runtime.NotImplemented();
public static bool BfpFindFileData_FindNextFile(BfpFindFileData* findData) => Runtime.NotImplemented();
public static void BfpFindFileData_GetFileName(BfpFindFileData* findData, char8* outName, int32* inOutNameSize, BfpFileResult* outResult) => Runtime.NotImplemented();
public static BfpTimeStamp BfpFindFileData_GetTime_LastWrite(BfpFindFileData* findData) => Runtime.NotImplemented();
public static BfpTimeStamp BfpFindFileData_GetTime_Created(BfpFindFileData* findData) => Runtime.NotImplemented();
public static BfpTimeStamp BfpFindFileData_GetTime_Access(BfpFindFileData* findData) => Runtime.NotImplemented();
public static BfpFileAttributes BfpFindFileData_GetFileAttributes(BfpFindFileData* findData) => Runtime.NotImplemented();
public static int64 BfpFindFileData_GetFileSize(BfpFindFileData* findData) => Runtime.NotImplemented();
public static void BfpFindFileData_Release(BfpFindFileData* findData) => Runtime.NotImplemented();
#endif
public enum BfpSysDirectoryKind : int32
{

View file

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

View file

@ -1,9 +1,11 @@
using System.Threading;
using System.Collections;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS || BF_DEBUG_ALLOC
#if (BF_ENABLE_OBJECT_DEBUG_FLAGS || BF_DEBUG_ALLOC) && !BF_RUNTIME_DISABLE
#define BF_DBG_RUNTIME
#endif
using internal System.Threading.Thread;
namespace System
{
struct RuntimeFeatures
@ -17,7 +19,7 @@ namespace System
{
const int32 cVersion = 10;
[CRepr, AlwaysInclude]
[CRepr]
struct BfDebugMessageData
{
enum MessageType : int32
@ -104,7 +106,7 @@ namespace System
struct BfRtCallbacks
{
public static BfRtCallbacks sCallbacks = .();
public static BfRtCallbacks sCallbacks;
function void* (int size) mAlloc;
function void (void* ptr) mFree;
@ -115,7 +117,7 @@ namespace System
function Object (Object obj, int32 typeId) mObject_DynamicCastToTypeId;
function void (Type type, String str) mType_GetFullName;
function String () mString_Alloc;
function char8* (String str) mString_ToCStr;
function StringView (String str) mString_ToStringView;
function Object () mThread_Alloc;
function Object () mThread_GetMainThread;
function void (Object thread) mThread_ThreadProc;
@ -178,7 +180,7 @@ namespace System
static void Type_GetFullName(Type type, String str)
{
#if BF_DBG_RUNTIME
type.GetFullName(str);
type.ToString(str);
#else
//
#endif
@ -189,9 +191,9 @@ namespace System
return new String();
}
static char8* String_ToCStr(String str)
static StringView String_ToStringView(String str)
{
return str.CStr();
return str;
}
static void GC_MarkAllStaticMembers()
@ -219,39 +221,37 @@ namespace System
static void DebugMessageData_SetupError(char8* str, int32 stackWindbackCount)
{
#if !BF_RUNTIME_REDUCED
BfDebugMessageData.gBfDebugMessageData.SetupError(str, stackWindbackCount);
#endif
}
static void DebugMessageData_SetupProfilerCmd(char8* str)
{
#if !BF_RUNTIME_REDUCED
BfDebugMessageData.gBfDebugMessageData.SetupProfilerCmd(str);
#endif
}
static void DebugMessageData_Fatal()
{
#if !BF_RUNTIME_REDUCED
BfDebugMessageData.gBfDebugMessageData.Fatal();
#endif
}
static void DebugMessageData_Clear()
{
#if !BF_RUNTIME_REDUCED
BfDebugMessageData.gBfDebugMessageData.Clear();
#endif
}
static int32 CheckErrorHandler(char8* kind, char8* arg1, char8* arg2, int arg3)
static int32 CheckErrorHandle(char8* kind, char8* arg1, char8* arg2, int arg3)
{
Error error = null;
switch (StringView(kind))
{
case "FatalError":
error = scope:: FatalError() { mError = new .(arg1) };
case "LoadSharedLibrary":
error = scope:: LoadSharedLibraryError() { mPath = new .(arg1) };
case "GetSharedProcAddress":
error = scope:: GetSharedProcAddressError() { mPath = new .(arg1), mProcName = new .(arg2) };
}
if (error == null)
if (Runtime.CheckErrorHandler != null)
return Runtime.CheckErrorHandler(kind, arg1, arg2, arg3);
return 0;
return (int32)Runtime.CheckErrorHandlers(error);
}
public void Init() mut
@ -264,7 +264,7 @@ namespace System
mObject_DynamicCastToTypeId = => Object_DynamicCastToTypeId;
mType_GetFullName = => Type_GetFullName;
mString_Alloc = => String_Alloc;
mString_ToCStr = => String_ToCStr;
mString_ToStringView = => String_ToStringView;
mGC_MarkAllStaticMembers = => GC_MarkAllStaticMembers;
mGC_CallRootCallbacks = => GC_CallRootCallbacks;
mGC_Shutdown = => GC_Shutdown;
@ -277,12 +277,23 @@ namespace System
}
};
#if !BF_RUNTIME_DISABLE
private static extern void Init(int32 version, int32 flags, BfRtCallbacks* callbacks);
private static extern void InitCrashCatcher(int32 flags);
private static extern void ShutdownCrashCatcher();
private static extern void AddCrashInfoFunc(void* func);
private static extern void Dbg_Init(int32 version, int32 flags, BfRtCallbacks* callbacks);
private static extern void SetErrorString(char8* error);
private static extern void* Dbg_GetCrashInfoFunc();
public static extern void SetCrashReportKind(RtCrashReportKind crashReportKind);
#else
private static void Init(int32 version, int32 flags, BfRtCallbacks* callbacks) {}
private static void AddCrashInfoFunc(void* func) {}
private static void Dbg_Init(int32 version, int32 flags, BfRtCallbacks* callbacks) {}
private static void SetErrorString(char8* error) {}
private static void* Dbg_GetCrashInfoFunc() => null;
public static void SetCrashReportKind(RtCrashReportKind crashReportKind) {}
#endif
public enum RtCrashReportKind : int32
{
@ -359,18 +370,23 @@ namespace System
Fail
}
static struct ErrorHandlerData
{
public delegate ErrorHandlerResult ErrorHandler(ErrorStage stage, Error error);
public static AllocWrapper<Monitor> sMonitor ~ _.Dispose();
public static List<ErrorHandler> sErrorHandlers ~ DeleteContainerAndItems!(_);
public static bool sInsideErrorHandler;
}
static RtFlags sExtraFlags;
static AllocWrapper<Monitor> sMonitor ~ _.Dispose();
static List<ErrorHandler> sErrorHandlers ~ DeleteContainerAndItems!(_);
static bool sInsideErrorHandler;
static bool sQueriedFeatures = false;
static RuntimeFeatures sFeatures;
static function void() sThreadInit;
public static this()
{
#if !BF_RUNTIME_DISABLE
BfRtCallbacks.sCallbacks.Init();
RtFlags flags = sExtraFlags;
@ -384,23 +400,36 @@ namespace System
flags |= .DebugAlloc;
#endif
Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks);
#if !BF_RUNTIME_REDUCED && BF_PLATFORM_WINDOWS
InitCrashCatcher((int32)flags);
#endif
#if BF_DBG_RUNTIME
Dbg_Init(cVersion, (int32)flags, &BfRtCallbacks.sCallbacks);
#endif
Thread.[Friend]Init();
if (sThreadInit != null)
sThreadInit();
#endif
}
[NoReturn]
public static void FatalError(String msg = "Fatal error encountered", String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
{
String failStr = scope .()..AppendF("{} at line {} in {}", msg, line, filePath);
#if !BF_RUNTIME_REDUCED
String failStr = scope .()..Append(msg, " at line ");
line.ToString(failStr);
failStr.Append(" in ", filePath);
Internal.FatalError(failStr, 1);
#else
Internal.FatalError("Fatal error", 1);
#endif
}
[NoReturn]
public static void NotImplemented(String filePath = Compiler.CallerFilePath, int line = Compiler.CallerLineNum)
{
String failStr = scope .()..AppendF("Not Implemented at line {} in {}", line, filePath);
String failStr = scope .()..Append("Not implemented at line ");
line.ToString(failStr);
failStr.Append(" in ", filePath);
Internal.FatalError(failStr, 1);
}
@ -408,60 +437,97 @@ namespace System
{
if (!condition)
{
if (Runtime.CheckErrorHandlers(scope Runtime.AssertError(.Runtime, error, filePath, line)) == .Ignore)
if ((Runtime.CheckAssertError != null) && (Runtime.CheckAssertError(.Runtime, error, filePath, line) == .Ignore))
return;
String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath);
#if !BF_RUNTIME_REDUCED
String failStr = scope .()..Append("Assert failed: ", error, " at line ");
line.ToString(failStr);
failStr.Append(" in ", filePath);
Internal.FatalError(failStr, 1);
#else
Internal.FatalError("Assert failed", 1);
#endif
}
}
public static void AddErrorHandler(ErrorHandler handler)
public static void AddErrorHandler(ErrorHandlerData.ErrorHandler handler)
{
if (Compiler.IsComptime)
return;
using (sMonitor.Val.Enter())
using (ErrorHandlerData.sMonitor.Val.Enter())
{
if (sErrorHandlers == null)
sErrorHandlers = new .();
sErrorHandlers.Add(handler);
if (CheckAssertError == null)
{
CheckAssertError = => CheckAssertError_Impl;
CheckErrorHandler = => CheckErrorHandler_Impl;
}
if (ErrorHandlerData.sErrorHandlers == null)
ErrorHandlerData.sErrorHandlers = new .();
ErrorHandlerData.sErrorHandlers.Add(handler);
}
}
public static Result<void> RemoveErrorHandler(ErrorHandler handler)
public static Result<void> RemoveErrorHandler(ErrorHandlerData.ErrorHandler handler)
{
if (Compiler.IsComptime)
return .Ok;
using (sMonitor.Val.Enter())
using (ErrorHandlerData.sMonitor.Val.Enter())
{
if (sErrorHandlers.RemoveStrict(handler))
if (ErrorHandlerData.sErrorHandlers.RemoveStrict(handler))
return .Ok;
}
return .Err;
}
public static ErrorHandlerResult CheckErrorHandlers(Error error)
public static function ErrorHandlerResult(AssertError.Kind kind, String error, String filePath, int lineNum) CheckAssertError;
public static function int32(char8* kind, char8* arg1, char8* arg2, int arg3) CheckErrorHandler;
static ErrorHandlerResult CheckAssertError_Impl(AssertError.Kind kind, String error, String filePath, int lineNum)
{
return CheckErrorHandlers(scope AssertError(kind, error, filePath, lineNum));
}
static int32 CheckErrorHandler_Impl(char8* kind, char8* arg1, char8* arg2, int arg3)
{
Error error = null;
switch (StringView(kind))
{
case "FatalError":
error = scope:: FatalError() { mError = new .(arg1) };
case "LoadSharedLibrary":
error = scope:: LoadSharedLibraryError() { mPath = new .(arg1) };
case "GetSharedProcAddress":
error = scope:: GetSharedProcAddressError() { mPath = new .(arg1), mProcName = new .(arg2) };
}
if (error == null)
return 0;
return (int32)CheckErrorHandlers(error);
}
static ErrorHandlerResult CheckErrorHandlers(Error error)
{
if (Compiler.IsComptime)
return .ContinueFailure;
using (sMonitor.Val.Enter())
using (ErrorHandlerData.sMonitor.Val.Enter())
{
if (sInsideErrorHandler)
if (ErrorHandlerData.sInsideErrorHandler)
return .ContinueFailure;
sInsideErrorHandler = true;
defer { sInsideErrorHandler = false; }
ErrorHandlerData.sInsideErrorHandler = true;
defer { ErrorHandlerData.sInsideErrorHandler = false; }
for (int pass = 0; pass < 2; pass++)
{
int idx = (sErrorHandlers?.Count).GetValueOrDefault() - 1;
int idx = (ErrorHandlerData.sErrorHandlers?.Count).GetValueOrDefault() - 1;
while (idx >= 0)
{
if (idx < sErrorHandlers.Count)
if (idx < ErrorHandlerData.sErrorHandlers.Count)
{
var handler = sErrorHandlers[idx];
var handler = ErrorHandlerData.sErrorHandlers[idx];
var result = handler((pass == 0) ? .PreFail : .Fail, error);
if (result == .Ignore)
{
@ -562,5 +628,122 @@ namespace System
[Intrinsic("xgetbv")]
private static extern uint64 xgetbv(uint32 xcr);
#endif
public static void Shutdown()
{
#if !BF_RUNTIME_REDUCED && BF_PLATFORM_WINDOWS
ShutdownCrashCatcher();
#endif
}
}
}
#if BF_RUNTIME_DISABLE
namespace System
{
[AlwaysInclude, StaticInitPriority(1000)]
static class MinRuntime
{
static function void*(int) sMallocFunc;
static function void(void*) sFreeFunc;
static this()
{
var lib = Windows.LoadLibraryA("msvcrt.dll");
sMallocFunc = (.)Windows.GetProcAddress(lib, "malloc");
sFreeFunc = (.)Windows.GetProcAddress(lib, "free");
}
/*[LinkName(.C), AlwaysInclude]
static void __chkstk()
{
}*/
[LinkName(.C), AlwaysInclude]
static void* malloc(int size)
{
return sMallocFunc(size);
}
[LinkName(.C), AlwaysInclude]
static void free(void* ptr)
{
sFreeFunc(ptr);
}
[LinkName(.C), AlwaysInclude]
static void memset(void* dest, uint8 val, int size)
{
uint8* outPtr = (.)dest;
for (int i < size)
*(outPtr++) = val;
}
[LinkName(.C), AlwaysInclude]
static void memcpy(void* dest, void* src, int size)
{
uint8* destPtr = (.)dest;
uint8* srcPtr = (.)src;
if (destPtr < srcPtr)
{
for (int i < size)
*(destPtr++) = *(srcPtr++);
}
else
{
destPtr += size;
srcPtr += size;
for (int i < size)
*(--destPtr) = *(--srcPtr);
}
}
[LinkName(.C), AlwaysInclude]
static void memmove(void* dest, void* src, int size)
{
uint8* destPtr = (.)dest;
uint8* srcPtr = (.)src;
if (destPtr < srcPtr)
{
for (int i < size)
*(destPtr++) = *(srcPtr++);
}
else
{
destPtr += size;
srcPtr += size;
for (int i < size)
*(--destPtr) = *(--srcPtr);
}
}
[LinkName(.C), AlwaysInclude]
static double strtod(char8* str, char8** endPtr)
{
return 0;
}
[LinkName(.C), AlwaysInclude]
static extern void WinMain(void* module, void* prevModule, char8* args, int32 showCmd);
[LinkName(.C), AlwaysInclude]
static extern int32 main(int argc, char8** argv);
[LinkName(.C), AlwaysInclude]
static void mainCRTStartup()
{
//WinMain(null, null, "hi", 1);
main(0, null);
}
[LinkName(.C), Export]
static int32 _tls_index;
[LinkName(.C), Export]
static bool _fltused;
}
}
#endif

View file

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

View file

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

View file

@ -70,7 +70,7 @@ namespace System
{
if (!condition)
{
if (Runtime.CheckErrorHandlers(scope Runtime.AssertError(.Test, error, filePath, line)) == .Ignore)
if ((Runtime.CheckAssertError != null) && (Runtime.CheckAssertError(.Test, error, filePath, line) == .Ignore))
return;
String failStr = scope .()..AppendF("Assert failed: {} at line {} in {}", error, line, filePath);
Internal.[Friend]Test_Error(failStr);

View file

@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Threading;
namespace System.Text
{
[StaticInitPriority(100)]
@ -15,11 +16,39 @@ namespace System.Text
case PartialEncode(int inChars, int encodedBytes);
}
public static readonly ASCIIEncoding ASCII = new ASCIIEncoding() ~ delete _;
public static readonly UTF8Encoding UTF8 = new UTF8Encoding() ~ delete _;
public static readonly UTF8EncodingWithBOM UTF8WithBOM = new UTF8EncodingWithBOM() ~ delete _;
public static readonly UTF16Encoding UTF16 = new UTF16Encoding() ~ delete _;
public static readonly UTF16EncodingWithBOM UTF16WithBOM = new UTF16EncodingWithBOM() ~ delete _;
static Encoding sASCII ~ delete _;
static Encoding sUTF8 ~ delete _;
static Encoding sUTF8WithBOM ~ delete _;
static Encoding sUTF16 ~ delete _;
static Encoding sUTF16WithBOM ~ delete _;
static T GetEncoding<T>(ref Encoding encoding) where T : Encoding, new, delete
{
if (encoding != null)
return (.)encoding;
var newEncoding = new T();
if (Compiler.IsComptime)
{
encoding = newEncoding;
return newEncoding;
}
let prevValue = Interlocked.CompareExchange(ref encoding, null, newEncoding);
if (prevValue != null)
{
// This was already set - race condition
delete newEncoding;
return (.)prevValue;
}
return newEncoding;
}
public static ASCIIEncoding ASCII => GetEncoding<ASCIIEncoding>(ref sASCII);
public static UTF8Encoding UTF8 => GetEncoding<UTF8Encoding>(ref sUTF8);
public static UTF8EncodingWithBOM UTF8WithBOM => GetEncoding<UTF8EncodingWithBOM>(ref sUTF8WithBOM);
public static UTF16Encoding UTF16 => GetEncoding<UTF16Encoding>(ref sUTF16);
public static UTF16EncodingWithBOM UTF16WithBOM => GetEncoding<UTF16EncodingWithBOM>(ref sUTF16WithBOM);
public abstract int GetCharUnitSize();
public abstract int GetEncodedLength(char32 c);

View file

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

View file

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

View file

@ -11,6 +11,14 @@ namespace System
case InvalidChar(uint partialResult);
}
public struct Simple : uint
{
public override void ToString(String strBuffer)
{
((uint)this).ToString(strBuffer);
}
}
public const uint MaxValue = (sizeof(uint) == 8) ? 0xFFFFFFFFFFFFFFFFUL : 0xFFFFFFFFL;
public const uint MinValue = 0;

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)
{
if(format == null || format.IsEmpty)

View file

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

View file

@ -52,6 +52,7 @@
USING_NS_BF;
static Beefy::StringT<0> gCmdLineString;
bool gCmdLineStringHandled;
bf::System::Runtime::BfRtCallbacks gBfRtCallbacks;
BfRtFlags gBfRtFlags = (BfRtFlags)0;
@ -65,7 +66,10 @@ static int gTestMethodIdx = -1;
static uint32 gTestStartTick = 0;
static bool gTestBreakOnFailure = false;
typedef void(*ClientPipeErrorFunc)(const Beefy::StringView& error, int stackOffset);
static BfpFile* gClientPipe = NULL;
static ClientPipeErrorFunc gClientPipeErrorFunc;
static Beefy::String gTestInBuffer;
namespace bf
@ -85,7 +89,7 @@ namespace bf
BFRT_EXPORT static void BfStaticCtor();
BFRT_EXPORT static void BfStaticDtor();
BFRT_EXPORT static void Shutdown();
BFRT_EXPORT static void Shutdown_Internal();
public:
BFRT_EXPORT static Object* UnsafeCastToObject(void* inPtr);
BFRT_EXPORT static void* UnsafeCastToPtr(Object* obj);
@ -224,18 +228,8 @@ static void Internal_FatalError(const char* error)
if (gBfRtCallbacks.CheckErrorHandler != NULL)
gBfRtCallbacks.CheckErrorHandler("FatalError", error, NULL, 0);
if ((gClientPipe != NULL) && (!gTestBreakOnFailure))
{
Beefy::String str = ":TestFatal\t";
str += error;
str.Replace('\n', '\r');
str += "\n";
TestString(str);
Beefy::String result;
TestReadCmd(result);
exit(1);
}
if (gClientPipeErrorFunc != NULL)
gClientPipeErrorFunc(error, 0);
else
BfpSystem_FatalError(error, "BEEF FATAL ERROR");
}
@ -304,57 +298,22 @@ void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
if ((flags & 4) != 0)
sysInitFlags = (BfpSystemInitFlags)(sysInitFlags | BfpSystemInitFlag_SilentCrash);
BfpSystem_Init(BFP_VERSION, sysInitFlags);
BfpSystem_AddCrashInfoFunc(GetCrashInfo);
if (gBfRtCallbacks.Alloc != NULL)
{
Internal_FatalError(StrFormat("BeefRT already initialized. Multiple executable modules in the same process cannot dynamically link to the Beef runtime.").c_str());
Internal_FatalError("BeefRT already initialized. Multiple executable modules in the same process cannot dynamically link to the Beef runtime.");
}
if (version != BFRT_VERSION)
{
BfpSystem_FatalError(StrFormat("BeefRT build version '%d' does not match requested version '%d'", BFRT_VERSION, version).c_str(), "BEEF FATAL ERROR");
char error[256];
sprintf(error, "BeefRT build version '%d' does not match requested version '%d'", BFRT_VERSION, version);
BfpSystem_FatalError(error, "BEEF FATAL ERROR");
}
gBfRtCallbacks = *callbacks;
gBfRtFlags = (BfRtFlags)flags;
Beefy::String cmdLine;
BfpSystemResult result;
BFP_GETSTR_HELPER(cmdLine, result, BfpSystem_GetCommandLine(__STR, __STRLEN, &result));
char* cmdLineStr = (char*)cmdLine.c_str();
//::MessageBoxA(NULL, cmdLineStr, "BFRT", 0);
char* useCmdLineStr = cmdLineStr;
if (cmdLineStr[0] != 0)
{
bool nameQuoted = cmdLineStr[0] == '\"';
Beefy::String passedName;
int i;
for (i = (nameQuoted ? 1 : 0); cmdLineStr[i] != 0; i++)
{
wchar_t c = cmdLineStr[i];
if (((nameQuoted) && (c == '"')) ||
((!nameQuoted) && (c == ' ')))
{
i++;
break;
}
passedName += cmdLineStr[i];
}
useCmdLineStr += i;
while (*useCmdLineStr == L' ')
useCmdLineStr++;
}
gCmdLineString = useCmdLineStr;
#ifdef BF_PLATFORM_WINDOWS
gBfTLSKey = FlsAlloc(TlsFreeFunc);
#else
@ -362,6 +321,20 @@ void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
#endif
}
void bf::System::Runtime::InitCrashCatcher(int flags)
{
BfpSystemInitFlags sysInitFlags = BfpSystemInitFlag_InstallCrashCatcher;
if ((flags & 4) != 0)
sysInitFlags = (BfpSystemInitFlags)(sysInitFlags | BfpSystemInitFlag_SilentCrash);
BfpSystem_InitCrashCatcher(sysInitFlags);
BfpSystem_AddCrashInfoFunc(GetCrashInfo);
}
void bf::System::Runtime::ShutdownCrashCatcher()
{
BfpSystem_ShutdownCrashCatcher();
}
void bf::System::Runtime::SetErrorString(char* errorStr)
{
::SetErrorString(errorStr);
@ -379,7 +352,7 @@ void bf::System::Runtime::SetCrashReportKind(bf::System::Runtime::RtCrashReportK
//////////////////////////////////////////////////////////////////////////
void Internal::Shutdown()
void Internal::Shutdown_Internal()
{
BfInternalThread::WaitForAllDone();
if (gBfRtCallbacks.GC_Shutdown != NULL)
@ -419,20 +392,9 @@ void* Internal::UnsafeCastToPtr(Object* obj)
void Internal::ThrowIndexOutOfRange(intptr stackOffset)
{
if (gClientPipe != NULL)
{
if (gTestBreakOnFailure)
{
SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
BF_DEBUG_BREAK();
}
Beefy::String str = ":TestFail\tIndex out of range\n";
TestString(str);
exit(1);
}
if ((stackOffset != -1) && (::IsDebuggerPresent()))
if (gClientPipeErrorFunc != NULL)
gClientPipeErrorFunc("Index out of range", 0);
else if ((stackOffset != -1) && (::IsDebuggerPresent()))
{
SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
BF_DEBUG_BREAK();
@ -443,20 +405,9 @@ void Internal::ThrowIndexOutOfRange(intptr stackOffset)
void Internal::ThrowObjectNotInitialized(intptr stackOffset)
{
if (gClientPipe != NULL)
{
if (gTestBreakOnFailure)
{
SETUP_ERROR("Object not initialized", (int)(2 + stackOffset));
BF_DEBUG_BREAK();
}
Beefy::String str = ":TestFail\tObject not initialized\n";
TestString(str);
exit(1);
}
if ((stackOffset != -1) && (::IsDebuggerPresent()))
if (gClientPipeErrorFunc != NULL)
gClientPipeErrorFunc("Object not initialized", 0);
else if ((stackOffset != -1) && (::IsDebuggerPresent()))
{
SETUP_ERROR("Object not initialized", (int)(2 + stackOffset));
BF_DEBUG_BREAK();
@ -467,29 +418,17 @@ void Internal::ThrowObjectNotInitialized(intptr stackOffset)
void Internal::FatalError(bf::System::String* error, intptr stackOffset)
{
if (gClientPipe != NULL)
{
if (gTestBreakOnFailure)
{
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
BF_DEBUG_BREAK();
}
Beefy::String str = ":TestFail\t";
str += error->CStr();
str.Replace('\n', '\r');
str += "\n";
TestString(str);
exit(1);
}
Beefy::StringView errorStringView = error->ToStringView();
Beefy::StringSimple errorString = errorStringView;
if (gClientPipeErrorFunc != NULL)
gClientPipeErrorFunc(errorStringView, 0);
if ((stackOffset != -1) && (::IsDebuggerPresent()))
{
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
SETUP_ERROR(errorString.c_str(), (int)(2 + stackOffset));
BF_DEBUG_BREAK();
}
Internal_FatalError(error->CStr());
Internal_FatalError(errorString.c_str());
}
void Internal::MemCpy(void* dest, void* src, intptr length)
@ -630,6 +569,46 @@ void Internal::GetSharedProcAddressInto(void* libHandle, char* procName, void**
char* Internal::GetCommandLineArgs()
{
if (!gCmdLineStringHandled)
{
Beefy::String cmdLine;
BfpSystemResult result;
BFP_GETSTR_HELPER(cmdLine, result, BfpSystem_GetCommandLine(__STR, __STRLEN, &result));
char* cmdLineStr = (char*)cmdLine.c_str();
//::MessageBoxA(NULL, cmdLineStr, "BFRT", 0);
char* useCmdLineStr = cmdLineStr;
if (cmdLineStr[0] != 0)
{
bool nameQuoted = cmdLineStr[0] == '\"';
Beefy::String passedName;
int i;
for (i = (nameQuoted ? 1 : 0); cmdLineStr[i] != 0; i++)
{
wchar_t c = cmdLineStr[i];
if (((nameQuoted) && (c == '"')) ||
((!nameQuoted) && (c == ' ')))
{
i++;
break;
}
passedName += cmdLineStr[i];
}
useCmdLineStr += i;
while (*useCmdLineStr == L' ')
useCmdLineStr++;
}
gCmdLineString = useCmdLineStr;
gCmdLineStringHandled = true;
}
return (char*)gCmdLineString.c_str();
}
@ -697,6 +676,27 @@ static void TestReadCmd(Beefy::String& str)
}
}
void TestFailed(const Beefy::StringView& error, int stackOffset)
{
if (gClientPipe != NULL)
{
Beefy::String errorString = error;
if (gTestBreakOnFailure)
{
SETUP_ERROR(errorString.c_str(), (int)(2 + stackOffset));
BF_DEBUG_BREAK();
}
Beefy::String str = ":TestFail\t";
str += errorString.c_str();
str.Replace('\n', '\r');
str += "\n";
TestString(str);
exit(1);
}
}
void Internal::Test_Init(char* testData)
{
BfpSystem_SetCrashReportKind(BfpCrashReportKind_None);
@ -708,6 +708,8 @@ void Internal::Test_Init(char* testData)
if (fileResult != BfpFileResult_Ok)
BF_FATAL("Test_Init failed to create pipe to test manager");
gClientPipeErrorFunc = TestFailed;
Beefy::String outStr;
outStr += ":TestInit\n";
outStr += testData;
@ -853,7 +855,6 @@ void Internal::ObjectDynCheck(bf::System::Object* object, int typeId, bool allow
if (result == NULL)
{
Beefy::String errorStr = "Attempting invalid cast on object";
//errorStr += StrFormat("\x1LEAK\t0x%@\n (%s)0x%@\n", object, object->GetTypeName().c_str(), object);
errorStr += StrFormat("\x1LEAK\t0x%@\n (%s)0x%@\n", object, "System.Object", object);
SETUP_ERROR(errorStr.c_str(), 2);
BF_DEBUG_BREAK();

View file

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

View file

@ -318,7 +318,10 @@ int Thread::GetThreadStateNative()
void Thread::InformThreadNameChange(String* name)
{
BfpThread_SetName(GetInternalThread()->mThreadHandle, (name != NULL) ? name->CStr() : "", NULL);
Beefy::String nameStr;
if (name != NULL)
nameStr = name->ToStringView();
BfpThread_SetName(GetInternalThread()->mThreadHandle, nameStr.c_str(), NULL);
}
void Thread::MemoryBarrier()

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_InitCrashCatcher(BfpSystemInitFlags flags);
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCommandLine(int argc, char** argv);
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashReportKind(BfpCrashReportKind crashReportKind);
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfoFunc(BfpCrashInfoFunc crashInfoFunc);
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfo(const char* str); // Can do at any time, or during CrashInfoFunc callbacks
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashRelaunchCmd(const char* str);
BFP_EXPORT void BFP_CALLTYPE BfpSystem_Shutdown();
BFP_EXPORT void BFP_CALLTYPE BfpSystem_ShutdownCrashCatcher();
BFP_EXPORT uint32 BFP_CALLTYPE BfpSystem_TickCount();
BFP_EXPORT BfpTimeStamp BFP_CALLTYPE BfpSystem_GetTimeStamp();
BFP_EXPORT uint16 BFP_CALLTYPE BfpSystem_EndianSwap16(uint16 val);

View file

@ -52,7 +52,6 @@ static SYMGETMODULEBASEPROC gSymGetModuleBase = NULL;
static SYMGETSYMFROMADDRPROC gSymGetSymFromAddr = NULL;
static SYMGETLINEFROMADDR gSymGetLineFromAddr = NULL;
static bool CreateMiniDump(EXCEPTION_POINTERS* pep, const StringImpl& filePath);
static bool LoadImageHelp()
@ -117,47 +116,6 @@ static bool LoadImageHelp()
return true;
}
struct
{
DWORD dwExceptionCode;
char *szMessage;
} gMsgTable[] = {
{ STATUS_SEGMENT_NOTIFICATION, "Segment Notification" },
{ STATUS_BREAKPOINT, "Breakpoint" },
{ STATUS_SINGLE_STEP, "Single step" },
{ STATUS_WAIT_0, "Wait 0" },
{ STATUS_ABANDONED_WAIT_0, "Abandoned Wait 0" },
{ STATUS_USER_APC, "User APC" },
{ STATUS_TIMEOUT, "Timeout" },
{ STATUS_PENDING, "Pending" },
{ STATUS_GUARD_PAGE_VIOLATION, "Guard Page Violation" },
{ STATUS_DATATYPE_MISALIGNMENT, "Data Type Misalignment" },
{ STATUS_ACCESS_VIOLATION, "Access Violation" },
{ STATUS_IN_PAGE_ERROR, "In Page Error" },
{ STATUS_NO_MEMORY, "No Memory" },
{ STATUS_ILLEGAL_INSTRUCTION, "Illegal Instruction" },
{ STATUS_NONCONTINUABLE_EXCEPTION, "Noncontinuable Exception" },
{ STATUS_INVALID_DISPOSITION, "Invalid Disposition" },
{ STATUS_ARRAY_BOUNDS_EXCEEDED, "Array Bounds Exceeded" },
{ STATUS_FLOAT_DENORMAL_OPERAND, "Float Denormal Operand" },
{ STATUS_FLOAT_DIVIDE_BY_ZERO, "Divide by Zero" },
{ STATUS_FLOAT_INEXACT_RESULT, "Float Inexact Result" },
{ STATUS_FLOAT_INVALID_OPERATION, "Float Invalid Operation" },
{ STATUS_FLOAT_OVERFLOW, "Float Overflow" },
{ STATUS_FLOAT_STACK_CHECK, "Float Stack Check" },
{ STATUS_FLOAT_UNDERFLOW, "Float Underflow" },
{ STATUS_INTEGER_DIVIDE_BY_ZERO, "Integer Divide by Zero" },
{ STATUS_INTEGER_OVERFLOW, "Integer Overflow" },
{ STATUS_PRIVILEGED_INSTRUCTION, "Privileged Instruction" },
{ STATUS_STACK_OVERFLOW, "Stack Overflow" },
{ STATUS_CONTROL_C_EXIT, "Ctrl+C Exit" },
{ 0xFFFFFFFF, "" }
};
static HFONT gDialogFont;
static HFONT gBoldFont;
static String gErrorTitle;
static String gErrorText;
static HWND gDebugButtonWindow = NULL;
static HWND gYesButtonWindow = NULL;
static HWND gNoButtonWindow = NULL;
@ -265,19 +223,19 @@ static void ShowErrorDialog(const StringImpl& errorTitle, const StringImpl& erro
gUseDefaultFonts = aVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT;
int aHeight = -MulDiv(8, 96, 72);
gDialogFont = ::CreateFontA(aHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
HFONT gDialogFont = ::CreateFontA(aHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, "Tahoma");
aHeight = -MulDiv(10, 96, 72);
gBoldFont = ::CreateFontA(aHeight, 0, 0, 0, FW_BOLD, FALSE, FALSE,
HFONT gBoldFont = ::CreateFontA(aHeight, 0, 0, 0, FW_BOLD, FALSE, FALSE,
false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, "Tahoma");
::SetCursor(::LoadCursor(NULL, IDC_ARROW));
gErrorTitle = errorTitle;
gErrorText = errorText;
String gErrorTitle = errorTitle;
String gErrorText = errorText;
WNDCLASSW wc;
wc.style = 0;
@ -935,6 +893,44 @@ static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
///////////////////////////
// first name the exception
struct
{
DWORD dwExceptionCode;
char* szMessage;
} gMsgTable[] = {
{ STATUS_SEGMENT_NOTIFICATION, "Segment Notification" },
{ STATUS_BREAKPOINT, "Breakpoint" },
{ STATUS_SINGLE_STEP, "Single step" },
{ STATUS_WAIT_0, "Wait 0" },
{ STATUS_ABANDONED_WAIT_0, "Abandoned Wait 0" },
{ STATUS_USER_APC, "User APC" },
{ STATUS_TIMEOUT, "Timeout" },
{ STATUS_PENDING, "Pending" },
{ STATUS_GUARD_PAGE_VIOLATION, "Guard Page Violation" },
{ STATUS_DATATYPE_MISALIGNMENT, "Data Type Misalignment" },
{ STATUS_ACCESS_VIOLATION, "Access Violation" },
{ STATUS_IN_PAGE_ERROR, "In Page Error" },
{ STATUS_NO_MEMORY, "No Memory" },
{ STATUS_ILLEGAL_INSTRUCTION, "Illegal Instruction" },
{ STATUS_NONCONTINUABLE_EXCEPTION, "Noncontinuable Exception" },
{ STATUS_INVALID_DISPOSITION, "Invalid Disposition" },
{ STATUS_ARRAY_BOUNDS_EXCEEDED, "Array Bounds Exceeded" },
{ STATUS_FLOAT_DENORMAL_OPERAND, "Float Denormal Operand" },
{ STATUS_FLOAT_DIVIDE_BY_ZERO, "Divide by Zero" },
{ STATUS_FLOAT_INEXACT_RESULT, "Float Inexact Result" },
{ STATUS_FLOAT_INVALID_OPERATION, "Float Invalid Operation" },
{ STATUS_FLOAT_OVERFLOW, "Float Overflow" },
{ STATUS_FLOAT_STACK_CHECK, "Float Stack Check" },
{ STATUS_FLOAT_UNDERFLOW, "Float Underflow" },
{ STATUS_INTEGER_DIVIDE_BY_ZERO, "Integer Divide by Zero" },
{ STATUS_INTEGER_OVERFLOW, "Integer Overflow" },
{ STATUS_PRIVILEGED_INSTRUCTION, "Privileged Instruction" },
{ STATUS_STACK_OVERFLOW, "Stack Overflow" },
{ STATUS_CONTROL_C_EXIT, "Ctrl+C Exit" },
{ 0xFFFFFFFF, "" }
};
char *szName = NULL;
for (int i = 0; gMsgTable[i].dwExceptionCode != 0xFFFFFFFF; i++)
{

View file

@ -39,9 +39,14 @@
USING_NS_BF;
static void Crash_Error(const char* msg);
typedef void(*BfpCrashErrorFunc)(const char* str);
static bool gTimerInitialized = false;
static int gTimerDivisor = 0;
CritSect gBfpCritSect;
BfpCrashErrorFunc gCrashErrorFunc = Crash_Error;
struct WindowsSharedInfo
{
@ -415,8 +420,9 @@ void Beefy::BFFatalError(const StringImpl& message, const StringImpl& file, int
gBFApp->mSysDialogCnt++;
#endif
String failMsg = StrFormat("%s in %s:%d", message.c_str(), file.c_str(), line);
BfpSystem_FatalError(failMsg.c_str(), "FATAL ERROR");
char* failMsg = new char[message.length() + file.length() + 64];
sprintf(failMsg, "%s in %s:%d", message.c_str(), file.c_str(), line);
BfpSystem_FatalError(failMsg, "FATAL ERROR");
#ifndef BF_NO_BFAPP
if (gBFApp != NULL)
@ -906,6 +912,7 @@ static void __cdecl AbortHandler(int)
static int64 gCPUFreq = -1;
static int64 gStartCPUTick = -1;
static int64 gStartQPF = -1;
static void(*sOldSIGABRTHandler)(int signal) = nullptr;
static void InitCPUFreq()
{
@ -918,10 +925,31 @@ static void InitCPUFreq()
}
}
static void(*sOldSIGABRTHandler)(int signal) = nullptr;
static void Crash_Error(const char* msg)
{
HMODULE hMod = GetModuleHandleA(NULL);
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((uint8*)hMod + pDosHdr->e_lfanew);
bool isCLI = pNtHdr->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI;
if (isCLI)
fprintf(stderr, "**** FATAL APPLICATION ERROR ****\n%s\n", msg);
else
::MessageBoxA(NULL, msg, "FATAL ERROR", MB_ICONSTOP);
_set_purecall_handler(nullptr);
_set_invalid_parameter_handler(nullptr);
signal(SIGABRT, sOldSIGABRTHandler);
abort();
}
static void Crash_Error_CrashHandler(const char* msg)
{
CrashCatcher::Get()->Crash(msg);
}
BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flags)
{
gCrashErrorFunc = Crash_Error;
InitCPUFreq();
::_set_error_mode(_OUT_TO_STDERR);
@ -935,7 +963,9 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flag
if (version != BFP_VERSION)
{
BfpSystem_FatalError(StrFormat("Bfp build version '%d' does not match requested version '%d'", BFP_VERSION, version).c_str(), "BFP FATAL ERROR");
char msg[1024];
sprintf(msg, "Bfp build version '%d' does not match requested version '%d'", BFP_VERSION, version);
BfpSystem_FatalError(msg, "BFP FATAL ERROR");
}
if ((flags & BfpSystemInitFlag_InstallCrashCatcher) != 0)
@ -953,11 +983,15 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flag
sOldSIGABRTHandler = signal(SIGABRT, &AbortHandler);
if (sOldSIGABRTHandler == SIG_ERR)
sOldSIGABRTHandler = nullptr;
}
}
BFP_EXPORT void BFP_CALLTYPE BfpSystem_InitCrashCatcher(BfpSystemInitFlags flags)
{
CrashCatcher::Get()->Init();
if ((flags & BfpSystemInitFlag_SilentCrash) != 0)
CrashCatcher::Get()->SetCrashReportKind(BfpCrashReportKind_None);
}
gCrashErrorFunc = Crash_Error_CrashHandler;
}
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCommandLine(int argc, char** argv)
@ -993,7 +1027,10 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_Shutdown()
delete gManagerTail;
gManagerTail = next;
}
}
BFP_EXPORT void BFP_CALLTYPE BfpSystem_ShutdownCrashCatcher()
{
if (CrashCatcher::Shutdown())
{
_set_purecall_handler(nullptr);
@ -1092,9 +1129,17 @@ BFP_EXPORT uint64 BFP_CALLTYPE BfpSystem_InterlockedCompareExchange64(uint64* pt
BFP_EXPORT void BFP_CALLTYPE BfpSystem_FatalError(const char* error, const char* title)
{
if (title != NULL)
CrashCatcher::Get()->Crash(String(title) + "\n" + String(error));
{
int errorLen = (int)strlen(error);
int titleLen = (int)strlen(title);
char* str = new char[errorLen + 1 + titleLen + 1];
strcpy(str, title);
strcat(str, "\n");
strcat(str, error);
gCrashErrorFunc(str);
}
else
CrashCatcher::Get()->Crash(error);
gCrashErrorFunc(error);
}
BFP_EXPORT void BFP_CALLTYPE BfpSystem_GetCommandLine(char* outStr, int* inOutStrSize, BfpSystemResult* outResult)
@ -2245,9 +2290,12 @@ static LOCATEXSTATEFEATURE pfnLocateXStateFeature = NULL;
typedef BOOL(WINAPI* SETXSTATEFEATURESMASK)(PCONTEXT Context, DWORD64 FeatureMask);
static SETXSTATEFEATURESMASK pfnSetXStateFeaturesMask = NULL;
static uint8 ContextBuffer[4096];
static uint8* ContextBuffer;
static CONTEXT* CaptureRegistersEx(HANDLE hThread, intptr*& curPtr)
{
if (ContextBuffer == NULL)
ContextBuffer = new uint8[4096];
PCONTEXT Context;
DWORD ContextSize;
DWORD64 FeatureMask;

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>
{
public:

View file

@ -24,7 +24,7 @@ OtherLinkFlags = ""
TargetDirectory = "$(WorkspaceDir)/dist"
TargetName = "BeefIDE_d"
OtherLinkFlags = "$(LinkFlags) Comdlg32.lib kernel32.lib user32.lib advapi32.lib shell32.lib IDEHelper64_d.lib"
DebugCommandArguments = "-proddir=\"$(WorkspaceDir)\\..\\IDE\""
DebugCommandArguments = "-proddir=\"$(WorkspaceDir)\\..\\BeefBuild\""
DebugWorkingDirectory = "$(WorkspaceDir)\\.."
EnvironmentVars = ["_NO_DEBUG_HEAP=1"]

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

View file

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

View file

@ -62,46 +62,105 @@ namespace System
#endif
}
int IHashable.GetHashCode()
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
[NoShow]
int32 GetFlags()
{
return (int)(void*)this;
return (int32)mClassVData & 0xFF;
}
[DisableObjectAccessChecks, NoShow]
public bool IsDeleted()
{
return (int32)mClassVData & 0x80 != 0;
}
#else
[SkipCall]
public bool IsDeleted()
{
return false;
}
#endif
extern Type Comptime_GetType();
public Type GetType()
{
Type type;
if (Compiler.IsComptime)
return Comptime_GetType();
ClassVData* classVData;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
type = maskedVData.mType;
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
#else
type = mClassVData.mType;
classVData = mClassVData;
#endif
#if BF_32_BIT
Type type = Type.[Friend]GetType_((.)(classVData.mType2));
#else
Type type = Type.[Friend]GetType_((.)(classVData.mType >> 32));
#endif
if ((type.[Friend]mTypeFlags & TypeFlags.Boxed) != 0)
{
//int32 underlyingType = (int32)((TypeInstance)type).mUnderlyingType;
type = Type.[Friend]GetType(((TypeInstance)type).[Friend]mUnderlyingType);
}
return type;
}
TypeId GetTypeId()
{
ClassVData* classVData;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
#else
classVData = mClassVData;
#endif
#if BF_32_BIT
return (.)classVData.mType2;
#else
return (.)(classVData.mType >> 32);
#endif
}
[NoShow]
Type RawGetType()
{
Type type;
if (Compiler.IsComptime)
return Comptime_GetType();
ClassVData* classVData;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
type = maskedVData.mType;
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
#else
type = mClassVData.mType;
classVData = mClassVData;
#endif
#if BF_32_BIT
Type type = Type.[Friend]GetType_((.)(classVData.mType));
#else
Type type = Type.[Friend]GetType_((.)(classVData.mType & 0xFFFFFFFF));
#endif
return type;
}
TypeId RawGetTypeId()
{
ClassVData* classVData;
#if BF_ENABLE_OBJECT_DEBUG_FLAGS
classVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
#else
classVData = mClassVData;
#endif
#if BF_32_BIT
return (.)classVData.mType;
#else
return (.)(classVData.mType & 0xFFFFFFFF);
#endif
}
#if BF_DYNAMIC_CAST_CHECK || BF_ENABLE_REALTIME_LEAK_CHECK
[NoShow]
public virtual Object DynamicCastToTypeId(int32 typeId)
{
if (typeId == (int32)RawGetType().[Friend]mTypeId)
if (typeId == (.)RawGetTypeId())
return this;
return null;
}
@ -113,10 +172,15 @@ namespace System
}
#endif
int IHashable.GetHashCode()
{
return (int)Internal.UnsafeCastToPtr(this);
}
public virtual void ToString(String strBuffer)
{
//strBuffer.Set(stack string(GetType().mName));
RawGetType().GetName(strBuffer);
strBuffer.Append("Type#");
GetTypeId().ToString(strBuffer);
}
/*public virtual int GetHashCode()

View file

@ -7,7 +7,10 @@ namespace System
{
struct ClassVData
{
public Type mType;
public int mType;
#if BF_32_BIT
public int mType2;
#endif
// The rest of this structured is generated by the compiler,
// including the vtable and interface slots
}
@ -757,6 +760,7 @@ namespace System.Reflection
public int32 mCustomAttributesIdx;
}
[CRepr, AlwaysInclude]
public struct InterfaceData
{
public TypeId mInterfaceType;

View file

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

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

View file

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

View file

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

View file

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

View file

@ -8488,6 +8488,13 @@ namespace IDE
macroList.Add("BF_LARGE_COLLECTIONS");
}
if (workspaceOptions.mRuntimeKind == .Disabled)
macroList.Add("BF_RUNTIME_DISABLE");
if ((workspaceOptions.mRuntimeKind == .Reduced) || (workspaceOptions.mRuntimeKind == .Disabled))
macroList.Add("BF_RUNTIME_REDUCED");
if (workspaceOptions.mReflectKind == .Minimal)
macroList.Add("BF_REFLECT_MINIMAL");
// Only supported on Windows at the moment
bool hasLeakCheck = false;
if (workspaceOptions.LeakCheckingEnabled)

View file

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

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.Init(relWidget, x, y);
}

View file

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

View file

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

View file

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

View file

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

View file

@ -420,11 +420,18 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
didWork = true;
}
for (int populatePass = 0; populatePass < 2; populatePass++)
{
for (int workIdx = 0; workIdx < (int)mPopulateTypeWorkList.size(); workIdx++)
{
//BP_ZONE("PWL_PopulateType");
if (IsCancellingAndYield())
break;
if (!mMidCompileWorkList.IsEmpty())
{
// Let these mid-compiles occur as soon as possible
break;
}
auto workItemRef = mPopulateTypeWorkList[workIdx];
if (workItemRef == NULL)
@ -441,6 +448,11 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
continue;
}
// We want to resolve type aliases first, allowing possible mMidCompileWorkList entries
int wantPass = type->IsTypeAlias() ? 0 : 1;
if (populatePass != wantPass)
continue;
auto typeInst = type->ToTypeInstance();
if ((typeInst != NULL) && (resolveParser != NULL))
{
@ -470,6 +482,13 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
mCompiler->UpdateCompletion();
didWork = true;
}
}
if ((!mMidCompileWorkList.IsEmpty()) && (didWork))
{
// Let the mid-compile occur ASAP
continue;
}
for (int workIdx = 0; workIdx < (int)mTypeRefVerifyWorkList.size(); workIdx++)
{
@ -1984,6 +2003,7 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds)
}
else if (dependentTypeInst != NULL)
{
mGhostDependencies.Add(type);
// This keeps us from crashing from accessing deleted types on subsequent compiles
mFailTypes.TryAdd(dependentTypeInst, BfFailKind_Normal);
}
@ -2396,6 +2416,38 @@ void BfContext::UpdateRevisedTypes()
}
}
// Handle these "mid-compiles" now so we handle them as early-stage
BfParser* resolveParser = NULL;
if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mParsers.IsEmpty()))
resolveParser = mCompiler->mResolvePassData->mParsers[0];
for (int workIdx = 0; workIdx < (int)mMidCompileWorkList.size(); workIdx++)
{
auto workItemRef = mMidCompileWorkList[workIdx];
if (workItemRef == NULL)
{
workIdx = mMidCompileWorkList.RemoveAt(workIdx);
continue;
}
BfType* type = workItemRef->mType;
String reason = workItemRef->mReason;
auto typeInst = type->ToTypeInstance();
if ((typeInst != NULL) && (resolveParser != NULL))
{
if (!typeInst->mTypeDef->GetLatest()->HasSource(resolveParser))
{
continue;
}
}
workIdx = mMidCompileWorkList.RemoveAt(workIdx);
BfLogSysM("Handling prior-revision MidCompile on type %s in early-stage UpdateRevisedTypes\n", type);
RebuildDependentTypes(type->ToDependedType());
//RebuildDependentTypes_MidCompile(type->ToDependedType(), reason);
}
for (auto typeInst : defEmitParentCheckQueue)
{
if (typeInst->IsDeleting())
@ -2675,6 +2727,8 @@ void BfContext::UpdateRevisedTypes()
RebuildType(type);
}
}
BfLogSysM("BfContext::UpdateRevisedTypes done.\n");
}
void BfContext::VerifyTypeLookups(BfTypeInstance* typeInst)
@ -3459,6 +3513,7 @@ void BfContext::Cleanup()
}
}
mTypeGraveyard.Clear();
mGhostDependencies.Clear();
if (!mDeletingModules.IsEmpty())
{

View file

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

View file

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

View file

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

View file

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

View file

@ -410,7 +410,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, mIgnoreErrors || ignoreErrors);
genericTypeInst->mGenericTypeInfo->mValidatedGenericConstraints = true;
if (!genericTypeInst->mGenericTypeInfo->mFinishedGenericParams)
PopulateType(genericTypeInst, BfPopulateType_Interfaces_All);
mContext->mUnreifiedModule->PopulateType(genericTypeInst, BfPopulateType_Interfaces_All);
if (genericTypeInst->IsTypeAlias())
{
@ -418,7 +418,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
if ((underlyingType != NULL) && (underlyingType->IsGenericTypeInstance()))
{
auto underlyingGenericType = underlyingType->ToGenericTypeInstance();
PopulateType(underlyingType, BfPopulateType_Declaration);
mContext->mUnreifiedModule->PopulateType(underlyingType, BfPopulateType_Declaration);
bool result = ValidateGenericConstraints(typeRef, underlyingGenericType, ignoreErrors);
if (underlyingGenericType->mGenericTypeInfo->mHadValidateErrors)
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
@ -441,7 +441,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge
{
startGenericParamIdx = typeDef->mOuterType->mGenericParamDefs.mSize + typeDef->mOuterType->mExternalConstraints.mSize;
auto outerType = GetOuterType(genericTypeInst);
PopulateType(outerType, BfPopulateType_Declaration);
mContext->mUnreifiedModule->PopulateType(outerType, BfPopulateType_Declaration);
if ((outerType->mGenericTypeInfo != NULL) && (outerType->mGenericTypeInfo->mHadValidateErrors))
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
}
@ -802,6 +802,11 @@ void BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType)
return;
}
if ((typeInst != NULL) && (typeInst->mIsReified) && (!mCompiler->mIsResolveOnly))
{
BfLogSysM("REIFIED(InitType): %s Type:%p FromModule:%s FromMethod:%p\n", TypeToString(resolvedTypeRef).c_str(), resolvedTypeRef, mModuleName.c_str(), prevMethodInstance.mPrevVal);
}
BfLogSysM("%p InitType: %s Type: %p TypeDef: %p Revision:%d\n", mContext, TypeToString(resolvedTypeRef).c_str(), resolvedTypeRef, (typeInst != NULL) ? typeInst->mTypeDef : NULL, mCompiler->mRevision);
// When we're autocomplete, we can't do the method processing so we have to add this type to the type work list
@ -1212,6 +1217,14 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
canFastReify = false;
}
if (!mCompiler->mIsResolveOnly)
{
for (auto ownedTypes : typeModule->mOwnedTypeInstances)
{
BfLogSysM("REIFIED(PopulateType-Reference): %s %p FromModule:%s FromMethod: %p\n", TypeToString(ownedTypes).c_str(), ownedTypes, mModuleName.c_str(), mCurMethodInstance);
}
}
if (canFastReify)
{
BfLogSysM("Setting reified type %p in module %p in PopulateType on module awaiting finish\n", resolvedTypeRef, typeModule);
@ -1292,7 +1305,17 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL);
BF_ASSERT((resolvedTypeRef->mRebuildFlags & (BfTypeRebuildFlag_Deleted | BfTypeRebuildFlag_DeleteQueued)) == 0);
if ((resolvedTypeRef->mRebuildFlags & (BfTypeRebuildFlag_Deleted | BfTypeRebuildFlag_DeleteQueued)) != 0)
{
if (mContext->mGhostDependencies.Contains(resolvedTypeRef))
{
// Not a nice state, but we should be able to recover
return;
}
InternalError("Attempting PopulateType on deleted type");
return;
}
bool isNew = resolvedTypeRef->mDefineState == BfTypeDefineState_Undefined;
if (isNew)
@ -8268,7 +8291,7 @@ BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType
auto typeDefTypeRef = mContext->mTypeDefTypeRefPool.Get();
typeDefTypeRef->mTypeDef = typeDef;
auto resolvedtypeDefType = ResolveTypeRef(typeDefTypeRef, populateType);
auto resolvedtypeDefType = ResolveTypeRef(typeDefTypeRef, populateType, resolveFlags);
if (resolvedtypeDefType == NULL)
{
mContext->mTypeDefTypeRefPool.GiveBack(typeDefTypeRef);
@ -11347,7 +11370,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
}
}
return ResolveTypeResult(typeRef, ResolveTypeDef(typeDef, genericArgs, populateType), populateType, resolveFlags);
return ResolveTypeResult(typeRef, ResolveTypeDef(typeDef, genericArgs, populateType, resolveFlags), populateType, resolveFlags);
}
}
}
@ -12635,7 +12658,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
}
BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType, bool resolveGenericParam)
BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags, bool resolveGenericParam)
{
if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(typeRef))
{
@ -12648,7 +12671,7 @@ BfType* BfModule::ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, B
BfTypeVector typeVector;
for (int i = 0; i < (int)genericTypeDef->mGenericParamDefs.size(); i++)
typeVector.push_back(GetGenericParamType(BfGenericParamKind_Type, i));
auto result = ResolveTypeDef(genericTypeDef, typeVector, populateType);
auto result = ResolveTypeDef(genericTypeDef, typeVector, populateType, resolveFlags);
if ((result != NULL) && (genericTypeRef->mCommas.size() + 1 != genericTypeDef->mGenericParamDefs.size()))
{
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, result->ToTypeInstance());

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1548,6 +1548,13 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetModulesInfo()
return outString.c_str();
}
BF_EXPORT const char* BF_CALLTYPE Debugger_GetModuleInfo(const char* moduleName)
{
String& outString = *gTLStrReturn.Get();
outString = gDebugger->GetModuleInfo(moduleName);
return outString.c_str();
}
BF_EXPORT void BF_CALLTYPE Debugger_CancelSymSrv()
{
gDebugger->CancelSymSrv();

View file

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

View file

@ -8,6 +8,8 @@ USING_NS_BF_DBG;
DbgHotScanner::DbgHotScanner(WinDebugger* debugger)
{
mDebugger = debugger;
mBfTypesInfoAddr = 0;
mDbgGCData = { 0 };
}
NS_BF_DBG_BEGIN
@ -255,7 +257,11 @@ void DbgHotScanner::ScanSpan(TCFake::Span* span, int expectedStartPage, int memK
int* typeIdPtr = NULL;
if (mFoundClassVDataAddrs.TryAdd(classVDataAddr, NULL, &typeIdPtr))
{
addr_target typeAddr = mDebugger->ReadMemory<addr_target>(classVDataAddr);
if (mBfTypesInfoAddr > 0)
{
addr_target typeId = mDebugger->ReadMemory<int32>(classVDataAddr);
addr_target arrayAddr = mBfTypesInfoAddr + typeId * sizeof(addr_target);
addr_target typeAddr = mDebugger->ReadMemory<addr_target>(arrayAddr);
Fake_Type_Data typeData;
mDebugger->ReadMemory(typeAddr + objectSize, sizeof(typeData), &typeData);
@ -272,6 +278,7 @@ void DbgHotScanner::ScanSpan(TCFake::Span* span, int expectedStartPage, int memK
}
}
}
}
else
{
_MarkTypeUsed(*typeIdPtr, elementSize);
@ -358,6 +365,7 @@ void DbgHotScanner::Scan(DbgHotResolveFlags flags)
{
if ((module->mFilePath.Contains("Beef")) && (module->mFilePath.Contains("Dbg")))
{
module->ParseTypeData();
module->ParseSymbolData();
auto entry = module->mSymbolNameMap.Find("gGCDbgData");
if ((entry != NULL) && (entry->mValue != NULL))
@ -365,6 +373,44 @@ void DbgHotScanner::Scan(DbgHotResolveFlags flags)
}
}
auto module = mDebugger->mDebugTarget->mTargetBinary;
if (module->mBfTypesInfoAddr == 0)
{
module->mBfTypesInfoAddr = -1;
auto typeTypeEntry = module->FindType("System.Type", DbgLanguage_Beef);
if ((typeTypeEntry != NULL) && (typeTypeEntry->mValue != NULL))
{
auto typeType = typeTypeEntry->mValue;
module->mBfTypeType = typeType;
if (typeType->mNeedsGlobalsPopulated)
typeType->mCompileUnit->mDbgModule->PopulateTypeGlobals(typeType);
for (auto member : typeType->mMemberList)
{
if ((member->mIsStatic) && (member->mName != NULL) && (strcmp(member->mName, "sTypes") == 0) && (member->mLocationData != NULL))
{
DbgAddrType addrType;
module->mBfTypesInfoAddr = member->mCompileUnit->mDbgModule->EvaluateLocation(NULL, member->mLocationData, member->mLocationLen, NULL, &addrType);
}
}
if (module->mBfTypesInfoAddr <= 0)
{
auto entry = module->mSymbolNameMap.Find(
#ifdef BF_DBG_64
"?sTypes@Type@System@bf@@2PEAPEAV123@A"
#else
"?sTypes@Type@System@bf@@2PAPAV123@A"
#endif
);
if (entry)
module->mBfTypesInfoAddr = entry->mValue->mAddress;
}
}
}
mBfTypesInfoAddr = module->mBfTypesInfoAddr;
if (gcDbgDataAddr == 0)
return;

View file

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

View file

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

View file

@ -12872,6 +12872,210 @@ String WinDebugger::GetModulesInfo()
return str;
}
String WinDebugger::GetModuleInfo(const StringImpl& modulePath)
{
AutoCrit autoCrit(mDebugManager->mCritSect);
String result;
for (auto dbgModule : mDebugTarget->mDbgModules)
{
if (modulePath.Equals(dbgModule->mFilePath, StringImpl::CompareKind_OrdinalIgnoreCase))
{
dbgModule->ParseGlobalsData();
dbgModule->PopulateStaticVariableMap();
auto coff = (COFF*)dbgModule;
coff->ParseCompileUnits();
int fileSize = 0;
//
{
FileStream fs;
fs.Open(coff->mFilePath, "rb");
fileSize = fs.GetSize();
}
result += StrFormat("Path: %s FileSize:%0.2fk MemoryImage:%0.2fk\n", coff->mFilePath.c_str(), fileSize / 1024.0f, coff->mImageSize / 1024.0f);
result += "Sections:\n";
for (auto& section : coff->mSections)
{
result += StrFormat("\t%s\t%0.2fk\n", section.mName.c_str(), (section.mAddrLength) / 1024.0f);
}
result += "\n";
result += "Compile Units:\n";
for (auto compileUnit : dbgModule->mCompileUnits)
{
coff->MapCompileUnitMethods(compileUnit);
result += StrFormat("\t%s PCRange:%0.2fk\n", compileUnit->mName.c_str(), (compileUnit->mHighPC - compileUnit->mLowPC) / 1024.0f);
}
result += "\n";
Array<CvModuleInfo*> moduleInfos;
for (auto moduleInfo : coff->mCvModuleInfo)
{
if (moduleInfo->mSectionContrib.mSize > 0)
moduleInfos.Add(moduleInfo);
}
moduleInfos.Sort([](CvModuleInfo* lhs, CvModuleInfo* rhs)
{
return lhs->mSectionContrib.mSize > rhs->mSectionContrib.mSize;
});
int totalContrib = 0;
result += "CV Module Info:\n";
for (auto moduleInfo : moduleInfos)
{
auto section = coff->mSections[moduleInfo->mSectionContrib.mSection - 1];
result += StrFormat("\t%s\t%s\t%0.2fk\t%@-%@\n", moduleInfo->mModuleName, section.mName.c_str(), (moduleInfo->mSectionContrib.mSize) / 1024.0f,
coff->GetSectionAddr(moduleInfo->mSectionContrib.mSection, moduleInfo->mSectionContrib.mOffset),
coff->GetSectionAddr(moduleInfo->mSectionContrib.mSection, moduleInfo->mSectionContrib.mOffset + moduleInfo->mSectionContrib.mSize));
totalContrib += moduleInfo->mSectionContrib.mSize;
}
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
result += "\n";
addr_target minAddr = 0;
Array<DbgCompileUnitContrib*> contribs;
for (auto itr = mDebugTarget->mContribMap.begin(); itr != mDebugTarget->mContribMap.end(); ++itr)
{
auto contrib = *itr;
if (contrib->mDbgModule != coff)
continue;
if (contrib->mAddress < minAddr)
continue;
minAddr = contrib->mAddress + contrib->mLength;
auto section = &coff->mSectionHeaders[contrib->mSection - 1];
if (section->mSizeOfRawData <= 0)
continue;
contribs.Add(contrib);
}
contribs.Sort([](DbgCompileUnitContrib* lhs, DbgCompileUnitContrib* rhs)
{
return lhs->mLength > rhs->mLength;
});
totalContrib = 0;
result += "Contribs:\n";
for (auto contrib : contribs)
{
auto cvModule = coff->mCvModuleInfo[contrib->mCompileUnitId];
auto section = &coff->mSectionHeaders[contrib->mSection - 1];
result += StrFormat("\t%s\t%s\t%0.2fk\t%@\n", cvModule->mModuleName, section->mName, (contrib->mLength)/1024.0f, contrib->mAddress);
totalContrib += contrib->mLength;
}
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
result += "\n";
struct SymbolEntry
{
const char* mName;
addr_target mAddress;
int mSize;
};
Array<SymbolEntry> symbolEntries;
for (auto symbol : mDebugTarget->mSymbolMap)
{
if (symbol->mDbgModule != coff)
continue;
if (!symbolEntries.IsEmpty())
{
auto lastSymbol = &symbolEntries.back();
if (lastSymbol->mSize == 0)
lastSymbol->mSize = symbol->mAddress - lastSymbol->mAddress;
}
SymbolEntry symbolEntry;
symbolEntry.mName = symbol->mName;
symbolEntry.mAddress = symbol->mAddress;
symbolEntry.mSize = 0;
symbolEntries.Add(symbolEntry);
}
if (!symbolEntries.IsEmpty())
{
auto lastSymbol = &symbolEntries.back();
for (auto contrib : contribs)
{
if ((lastSymbol->mAddress >= contrib->mAddress) && (lastSymbol->mAddress < contrib->mAddress + contrib->mLength))
{
lastSymbol->mSize = (contrib->mAddress + contrib->mLength) - lastSymbol->mAddress;
break;
}
}
}
symbolEntries.Sort([](const SymbolEntry& lhs, const SymbolEntry& rhs)
{
return lhs.mSize > rhs.mSize;
});
totalContrib = 0;
result += "Symbols:\n";
for (auto symbolEntry : symbolEntries)
{
result += StrFormat("\t%s\t%0.2fk\t%@\n", symbolEntry.mName, (symbolEntry.mSize) / 1024.0f, symbolEntry.mAddress);
totalContrib += symbolEntry.mSize;
}
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
result += "\n";
//////////////////////////////////////////////////////////////////////////
totalContrib = 0;
result += "Static Variables:\n";
for (auto& variable : coff->mStaticVariables)
{
result += StrFormat("\t%s\t%0.2fk\n", variable->mName, (variable->mType->GetByteCount()) / 1024.0f);
totalContrib += variable->mType->GetByteCount();
}
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
result += "\n";
totalContrib = 0;
result += "Methods:\n";
Array<DbgSubprogram*> methods;
for (int typeIdx = 0; typeIdx < coff->mTypes.mSize; typeIdx++)
{
auto type = coff->mTypes[typeIdx];
type->PopulateType();
for (auto method : type->mMethodList)
methods.Add(method);
}
for (auto compileUnit : dbgModule->mCompileUnits)
{
for (auto method : compileUnit->mOrphanMethods)
methods.Add(method);
}
methods.Sort([](DbgSubprogram* lhs, DbgSubprogram* rhs)
{
return lhs->GetByteCount() > rhs->GetByteCount();
});
for (auto method : methods)
{
int methodSize = method->GetByteCount();
if (methodSize <= 0)
continue;
auto name = method->ToString();
result += StrFormat("\t%s\t%0.2fk\n", name.c_str(), methodSize / 1024.0f);
totalContrib += methodSize;
}
result += StrFormat("\tTOTAL: %0.2fk\n", (totalContrib) / 1024.0f);
result += "\n";
}
}
return result;
}
void WinDebugger::CancelSymSrv()
{
AutoCrit autoCrit(mDebugManager->mCritSect);

View file

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

View file

@ -1,4 +1,3 @@
@ECHO --------------------------- Beef Test_Build.Bat Version 1 ---------------------------
@SET P4_CHANGELIST=%1
@ -33,6 +32,20 @@ IDE\Tests\SysMSVCRT\build\Debug_Win64\SysMSVCRT\SysMSVCRT.exe 1000 234
IDE\dist\BeefBuild_d -proddir=BeefLibs\corlib -test
@IF %ERRORLEVEL% NEQ 0 GOTO HADERROR
@ECHO Building Tiny
bin\RunWithStats IDE\dist\BeefBuild -proddir=IDE\Tests\Tiny -clean -config=Release
set size=0
FOR /F "usebackq" %%A IN ('IDE\Tests\Tiny\build\Release_Win64\Tiny\Tiny.exe') DO set size=%%~zA
echo Tiny executable size: %size% (expected 13824, max 16000)
if %size% LSS 10000 (
echo TINY executable not found?
goto :HADERROR
)
if %size% GTR 16000 (
echo TINY executable is too large!
goto :HADERROR
)
@ECHO Building BeefIDE_d with BeefBuild_d
bin\RunAndWait IDE\dist\BeefPerf.exe -cmd="Nop()"
@IF %ERRORLEVEL% NEQ 0 GOTO FAILPERF_START