Explorar el Código

CTFE updates, including heap support

Brian Fiete hace 4 años
padre
commit
6bb363fb4b

+ 2 - 0
BeefLibs/corlib/src/Diagnostics/Debug.bf

@@ -36,6 +36,8 @@ namespace System.Diagnostics
 
 		[CallingConvention(.Cdecl)]
 		static extern void Write(char8* str, int strLen);
+		[CallingConvention(.Cdecl)]
+		static extern void Write(int val);
 
 		public static void Write(String line)
 		{

+ 2 - 0
BeefySysLib/BeefySysLib.vcxproj

@@ -1932,6 +1932,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
     <ClCompile Include="util\CubicFuncSpline.cpp" />
     <ClCompile Include="util\CubicSpline.cpp" />
     <ClCompile Include="util\Hash.cpp" />
+    <ClCompile Include="util\Heap.cpp" />
     <ClCompile Include="util\MappedFile.cpp" />
     <ClCompile Include="util\Matrix4.cpp" />
     <ClCompile Include="util\PerfTimer.cpp" />
@@ -2159,6 +2160,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"</Co
     <ClInclude Include="util\DLIList.h" />
     <ClInclude Include="util\Hash.h" />
     <ClInclude Include="util\HashSet.h" />
+    <ClInclude Include="util\Heap.h" />
     <ClInclude Include="util\MappedFile.h" />
     <ClInclude Include="util\Matrix4.h" />
     <ClInclude Include="util\MultiHashSet.h" />

+ 6 - 0
BeefySysLib/BeefySysLib.vcxproj.filters

@@ -704,6 +704,9 @@
     <ClCompile Include="platform\win\DInputManager.cpp">
       <Filter>src\platform\win</Filter>
     </ClCompile>
+    <ClCompile Include="util\Heap.cpp">
+      <Filter>src\util</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Common.h">
@@ -1069,6 +1072,9 @@
     <ClInclude Include="platform\win\DInputManager.h">
       <Filter>src\platform\win</Filter>
     </ClInclude>
+    <ClInclude Include="util\Heap.h">
+      <Filter>src\util</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">

+ 2 - 0
BeefySysLib/BeefySysLib_static.vcxproj

@@ -868,6 +868,7 @@
     <ClCompile Include="util\CubicSpline.cpp" />
     <ClCompile Include="util\FileEnumerator.cpp" />
     <ClCompile Include="util\Hash.cpp" />
+    <ClCompile Include="util\Heap.cpp" />
     <ClCompile Include="util\Json.cpp" />
     <ClCompile Include="util\MappedFile.cpp" />
     <ClCompile Include="util\Matrix4.cpp" />
@@ -1029,6 +1030,7 @@
     <ClInclude Include="util\CubicSpline.h" />
     <ClInclude Include="util\FileEnumerator.h" />
     <ClInclude Include="util\Hash.h" />
+    <ClInclude Include="util\Heap.h" />
     <ClInclude Include="util\Json.h" />
     <ClInclude Include="util\MappedFile.h" />
     <ClInclude Include="util\Matrix4.h" />

+ 6 - 0
BeefySysLib/BeefySysLib_static.vcxproj.filters

@@ -569,6 +569,9 @@
       <Filter>src\util</Filter>
     </ClCompile>
     <ClCompile Include="util\ThreadPool.cpp" />
+    <ClCompile Include="util\Heap.cpp">
+      <Filter>src\util</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Common.h">
@@ -871,6 +874,9 @@
     <ClInclude Include="util\ThreadPool.h">
       <Filter>src\util</Filter>
     </ClInclude>
+    <ClInclude Include="util\Heap.h">
+      <Filter>src\util</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">

+ 3 - 0
BeefySysLib/platform/win/CrashCatcher.cpp

@@ -1156,6 +1156,9 @@ void CrashCatcher::Crash(const StringImpl& str)
 	{
 
 	}*/
+		
+	for (auto func : CrashCatcher::Get()->mCrashInfoFuncs)
+		func();	
 
 	exit(1);
 }

+ 28 - 1
BeefySysLib/util/AllocDebug.h

@@ -2,6 +2,8 @@
 
 //#define BP_ALLOC_TRACK
 
+#include <cstdint>
+
 #ifdef BF_PLATFORM_WINDOWS
 
 #define _CRTDBG_MAP_ALLOC
@@ -87,4 +89,29 @@ void BpDump();
 #endif
 
 void* StompAlloc(int size);
-void StompFree(void* addr);
+void StompFree(void* addr);
+
+template <typename T>
+class AllocatorStomp
+{
+public:
+	T* allocate(intptr_t count)
+	{
+		return (T*)StompAlloc((int)(sizeof(T) * count));
+	}
+
+	void deallocate(T* ptr)
+	{
+		StompFree(ptr);
+	}
+
+	void* rawAllocate(intptr_t size)
+	{
+		return StompAlloc((int)size);
+	}
+
+	void rawDeallocate(void* ptr)
+	{
+		StompFree(ptr);
+	}
+};

+ 335 - 0
BeefySysLib/util/Heap.cpp

@@ -0,0 +1,335 @@
+#include "Heap.h"
+#include "DLIList.h"
+
+USING_NS_BF;
+
+//////////////////////////////////////////////////////////////////////////
+
+#define CH_REL_TO_ABS(VAL) ((ChBlock*)((uint8*)mMetadata + (VAL)))
+#define CH_REL_TO_ABS(VAL) ((ChBlock*)((uint8*)mMetadata + (VAL)))
+#define CH_ABS_TO_REL(VAL) (int)((uint8*)(VAL) - (uint8*)mMetadata)
+
+enum ChBlockKind
+{
+	ChBlockKind_Bad = 0xBEEF0BAD,
+	ChBlockKind_Unused = 0xBEEF1212,
+	ChBlockKind_Used = 0xBEEF2323,
+	ChBlockKind_Merged = 0xBEEF3434,
+};
+
+struct ChBlock
+{
+	ContiguousHeap::AllocRef mPrev;
+	ContiguousHeap::AllocRef mNext;
+	int mSize;
+	ChBlockKind mKind;
+
+	ChBlock()
+	{
+		mPrev = -1;
+		mNext = -1;
+		mSize = 0;
+		mKind = ChBlockKind_Bad;
+	}
+};
+
+class ChList
+{
+public:
+	void* mMetadata;
+	int32 mHead;
+	int32 mTail;
+
+public:
+	ChList()
+	{
+		mHead = -1;
+		mTail = -1;
+	}
+
+	void Size()
+	{
+		int size = 0;
+		int checkNode = mHead;
+		while (checkNode != NULL)
+		{
+			size++;
+			checkNode = CH_REL_TO_ABS(checkNode)->mNext;
+		}
+	}
+
+	void PushBack(int node)
+	{
+		BF_ASSERT(CH_REL_TO_ABS(node)->mNext == -1);
+
+		if (mHead == -1)
+			mHead = node;
+		else
+		{
+			CH_REL_TO_ABS(mTail)->mNext = node;
+			CH_REL_TO_ABS(node)->mPrev = mTail;
+		}
+		mTail = node;
+	}
+
+	void AddAfter(int refNode, int newNode)
+	{
+	 	int32 prevNext = CH_REL_TO_ABS(refNode)->mNext;
+	 	CH_REL_TO_ABS(refNode)->mNext = newNode;
+		CH_REL_TO_ABS(newNode)->mPrev = refNode;
+		CH_REL_TO_ABS(newNode)->mNext = prevNext;
+	 	if (prevNext != -1)
+			CH_REL_TO_ABS(prevNext)->mPrev = newNode;
+	 	if (refNode == mTail)
+	 		mTail = newNode;
+	}
+	
+	void Remove(int node)
+	{
+		if (CH_REL_TO_ABS(node)->mPrev == -1)
+		{
+			mHead = CH_REL_TO_ABS(node)->mNext;
+			if (mHead != -1)
+				CH_REL_TO_ABS(mHead)->mPrev = -1;
+		}
+		else
+			CH_REL_TO_ABS(CH_REL_TO_ABS(node)->mPrev)->mNext = CH_REL_TO_ABS(node)->mNext;
+
+		if (CH_REL_TO_ABS(node)->mNext == -1)
+		{
+			mTail = CH_REL_TO_ABS(node)->mPrev;
+			if (mTail != -1)
+				CH_REL_TO_ABS(mTail)->mNext = -1;
+		}
+		else
+			CH_REL_TO_ABS(CH_REL_TO_ABS(node)->mNext)->mPrev = CH_REL_TO_ABS(node)->mPrev;
+
+		CH_REL_TO_ABS(node)->mPrev = -1;
+		CH_REL_TO_ABS(node)->mNext = -1;
+	}
+
+	bool IsEmpty()
+	{
+		return mHead == -1;
+	}
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+ContiguousHeap::ContiguousHeap()
+{	
+	mMetadata = NULL;
+	mMemorySize = 0;
+	mBlockDataOfs = 0;
+	mFreeIdx = 0;
+}
+
+ContiguousHeap::~ContiguousHeap()
+{
+	free(mMetadata);
+}
+
+void ContiguousHeap::Clear(int maxAllocSize)
+{
+	if (mBlockDataOfs == 0)
+		return;
+
+	mBlockDataOfs = 0;
+	mFreeList.Clear();
+	if ((mMemorySize != -1) && (mMemorySize > maxAllocSize))
+	{
+		free(mMetadata);
+		mMetadata = NULL;
+		mMemorySize = 0;
+		return;
+	}
+
+	auto blockList = (ChList*)mMetadata;
+	if (blockList->mHead != -1)
+	{	
+		auto block = CH_REL_TO_ABS(blockList->mHead);
+		while (block != NULL)
+		{
+			block->mKind = ChBlockKind_Bad;
+			block = CH_REL_TO_ABS(block->mNext);
+		}
+	}	
+	blockList->mHead = -1;
+	blockList->mTail = -1;		
+}
+
+ContiguousHeap::AllocRef ContiguousHeap::Alloc(int size)
+{
+	if (size == 0)
+		return 0;
+
+	size = BF_ALIGN(size, 16);
+
+	auto blockList = (ChList*)mMetadata;
+
+	while (true)
+	{
+		for (int itr = 0; itr < (int)mFreeList.size(); itr++)
+		{
+			auto block = (ChBlock*)((uint8*)mMetadata + mFreeList[mFreeIdx]);
+			
+			if (block->mKind == ChBlockKind_Merged)
+			{
+				itr--;
+				if (mFreeIdx >= mFreeList.mSize)
+					mFreeIdx = 0;
+				block->mKind = (ChBlockKind)0;
+				mFreeList.RemoveAtFast(mFreeIdx);
+				continue;
+			}
+
+			BF_ASSERT(block->mKind == ChBlockKind_Unused);
+
+			if (block->mSize >= size)
+			{
+				mFreeList.RemoveAtFast(mFreeIdx);
+				if (block->mSize >= size + 64)
+				{
+					// Split block
+					auto newBlock = new ((uint8*)block + size) ChBlock();
+					newBlock->mSize = block->mSize - size;
+					newBlock->mKind = ChBlockKind_Unused;
+					blockList->AddAfter(CH_ABS_TO_REL(block), CH_ABS_TO_REL(newBlock));
+					block->mSize = size;
+
+					mFreeList.Add(CH_ABS_TO_REL(newBlock));
+				}
+
+				block->mKind = ChBlockKind_Used;
+				return CH_ABS_TO_REL(block);
+			}
+
+			mFreeIdx = (mFreeIdx + 1) % mFreeList.mSize;
+		}
+
+		int wantSize = BF_MAX(mMemorySize + mMemorySize / 2, mMemorySize + BF_MAX(size, 64 * 1024));
+		mMetadata = realloc(mMetadata, wantSize);
+			
+		memset((uint8*)mMetadata + mMemorySize, 0, wantSize - mMemorySize);
+
+		blockList = (ChList*)mMetadata;
+		mMemorySize = wantSize;
+
+		if (mBlockDataOfs == 0)
+		{
+			blockList = new (mMetadata) ChList();			
+			mBlockDataOfs = sizeof(ChList);
+		}
+		blockList->mMetadata = mMetadata;
+
+		auto block = new ((uint8*)mMetadata + mBlockDataOfs) ChBlock();		
+		block->mSize = mMemorySize - mBlockDataOfs;
+		block->mKind = ChBlockKind_Unused;
+		mBlockDataOfs += block->mSize;
+		blockList->PushBack(CH_ABS_TO_REL(block));
+
+		mFreeList.Add(CH_ABS_TO_REL(block));
+	}
+}
+
+bool ContiguousHeap::Free(AllocRef ref)
+{
+	if ((ref < 0) || (ref > mMemorySize - sizeof(ChBlock)))
+		return false;
+
+	auto blockList = (ChList*)mMetadata;
+ 	auto block = CH_REL_TO_ABS(ref);
+ 	
+	if (block->mKind != ChBlockKind_Used)
+		return false;
+	
+	int headAccSize = 0;
+	auto mergeHead = block;
+	while (mergeHead->mPrev != -1)
+	{
+		auto checkBlock = CH_REL_TO_ABS(mergeHead->mPrev);
+		if (checkBlock->mKind != ChBlockKind_Unused)
+			break;
+		headAccSize += mergeHead->mSize;
+		// Mark PREVIOUS as merged, only leave the current alive
+		mergeHead->mKind = ChBlockKind_Merged;
+		blockList->Remove(CH_ABS_TO_REL(mergeHead));
+		mergeHead = checkBlock;
+	}
+
+	int tailAccSize = 0;
+	if (mergeHead->mNext != -1)
+	{		
+		auto mergeTail = CH_REL_TO_ABS(mergeHead->mNext);
+		while (mergeTail->mKind == ChBlockKind_Unused)
+		{
+			ChBlock* nextBlock = NULL;
+			if (mergeTail->mNext != -1)
+				nextBlock = CH_REL_TO_ABS(mergeTail->mNext);
+			tailAccSize += mergeTail->mSize;
+			mergeTail->mKind = ChBlockKind_Merged;
+			blockList->Remove(CH_ABS_TO_REL(mergeTail));
+			if (nextBlock == NULL)
+				break;
+			mergeTail = nextBlock;
+		}
+	}
+
+	mergeHead->mSize += tailAccSize + headAccSize;
+	if ((mergeHead->mKind != ChBlockKind_Unused) && (mergeHead->mKind != ChBlockKind_Merged))
+	{
+		// If it were MERGED that means it's still in the free list
+		mFreeList.Add(CH_ABS_TO_REL(mergeHead));
+	}
+	mergeHead->mKind = ChBlockKind_Unused;
+	return true;
+}
+
+void ContiguousHeap::DebugDump()
+{
+	String str = "Heap Dump:\n";
+
+	auto blockList = (ChList*)mMetadata;
+
+	if (blockList->mHead != -1)
+	{
+		int totalSize = 0;
+
+		auto block = CH_REL_TO_ABS(blockList->mHead);
+		while (block != NULL)
+		{
+			str += StrFormat("@%d: %d ", CH_ABS_TO_REL(block), block->mSize);
+			switch (block->mKind)
+			{
+			case ChBlockKind_Unused:
+				str += "Unused";
+				break;
+			case ChBlockKind_Used:
+				str += "Used";
+				break;
+			case ChBlockKind_Merged:
+				str += "Merged";
+				break;
+			default:
+				str += "??????";				
+			}
+
+			str += "\n";
+
+			totalSize += block->mSize;
+
+			if (block->mNext == -1)
+				break;
+			block = CH_REL_TO_ABS(block->mNext);
+		}
+
+		str += StrFormat("Sum: %d Allocated: %d\n", totalSize, mMemorySize);
+	}
+
+	str += "\nFree List:\n";
+	for (auto val : mFreeList)
+		str += StrFormat("@%d\n", val);
+	str += "\n";
+
+	OutputDebugStrF(str.c_str());
+}

+ 32 - 0
BeefySysLib/util/Heap.h

@@ -0,0 +1,32 @@
+#pragma once
+
+#include "../Common.h"
+
+NS_BF_BEGIN
+
+class ContiguousHeap
+{
+public:
+	typedef int AllocRef;
+	
+public:	
+	void* mMetadata;
+
+	int mMemorySize;
+	int mBlockDataOfs;
+	Array<AllocRef> mFreeList;
+	int mFreeIdx;
+
+public:
+	ContiguousHeap();
+	virtual ~ContiguousHeap();
+	
+	void Clear(int maxAllocSize = -1);
+
+	AllocRef Alloc(int size);
+	bool Free(AllocRef ref);	
+
+	void DebugDump();	
+};
+
+NS_BF_END

+ 1 - 1
IDE/src/Compiler/BfPassInstance.bf

@@ -141,7 +141,7 @@ namespace IDE.Compiler
 		{
 			char8* fileName = null;
 			char8* errorStr = BfPassInstance_Error_GetMoreInfoData(mNativeBfPassInstance, errorIdx, moreInfoIdx, out fileName, out bfError.mSrcStart, out bfError.mSrcEnd,
-				getLine ? &bfError.mLine : null, getLine ? &bfError.mColumn : null);
+				&bfError.mLine, &bfError.mColumn);
 			Debug.Assert(bfError.mFilePath == null);
 			if (fileName != null)
 				bfError.mFilePath = new String(fileName);

+ 13 - 1
IDE/src/IDEApp.bf

@@ -1054,13 +1054,25 @@ namespace IDE
 				if (var sourceViewPanel = GetActiveSourceViewPanel(true))
 					sourceViewPanel.RecordHistoryLocation();
 
-				int32 charIdx = int32.Parse(cmds[2]).GetValueOrDefault();
+				StringView loc = cmds[2];
+				int32 charIdx = int32.Parse(loc).GetValueOrDefault();
 				if (charIdx < 0)
 					return;
 				var sourceViewPanel = ShowSourceFile(cmds[1], null, SourceShowType.Temp);
 				if (sourceViewPanel == null)
 				    return;
 				var editWidgetContent = sourceViewPanel.mEditWidget.mEditWidgetContent;
+
+				int colonIdx = loc.IndexOf(':');
+				if (colonIdx != -1)
+				{
+					int line = int.Parse(loc.Substring(0, colonIdx)).GetValueOrDefault();
+					int column = int.Parse(loc.Substring(colonIdx + 1)).GetValueOrDefault();
+					charIdx = (.)editWidgetContent.GetTextIdx(line, column);
+				}
+				if (charIdx < 0)
+					return;
+
 				int line;
 				int lineChar;
 				editWidgetContent.GetLineCharAtIdx(charIdx, out line, out lineChar);

+ 6 - 1
IDE/src/ui/SourceViewPanel.bf

@@ -4966,7 +4966,12 @@ namespace IDE.ui
 							{
 								for (var moreInfo in bestError.mMoreInfo)
 								{
-									showMouseoverString.AppendF("\n@{0}\t{1}\t{2}", moreInfo.mFilePath, moreInfo.mSrcStart, moreInfo.mError);
+									if ((moreInfo.mSrcStart == -1) && (moreInfo.mSrcStart == -1) && (moreInfo.mLine != -1))
+									{
+										showMouseoverString.AppendF("\n@{}\t{}:{}\t{}", moreInfo.mFilePath, moreInfo.mLine, moreInfo.mColumn, moreInfo.mError);
+									}
+									else
+										showMouseoverString.AppendF("\n@{0}\t{1}\t{2}", moreInfo.mFilePath, moreInfo.mSrcStart, moreInfo.mError);
 								}
 							}
 	                    }

+ 63 - 1
IDEHelper/Backend/BeIRCodeGen.cpp

@@ -889,6 +889,9 @@ void BeIRCodeGen::Read(BeValue*& beValue)
 		beValue = result.mBeValue;
 		BE_MEM_END("ParamType_StreamId");
 	}	
+
+	if (beValue != NULL)
+		beValue->mRefCount++;
 }
 
 void BeIRCodeGen::Read(BeConstant*& llvmConstant)
@@ -922,6 +925,8 @@ void BeIRCodeGen::Read(BeFunction*& beFunc)
 	BF_ASSERT(BeValueDynCast<BeFunction>(result.mBeValue));
 	beFunc = (BeFunction*)result.mBeValue;
 	BE_MEM_END("BeFunction");
+
+	beFunc->mRefCount++;
 }
 
 void BeIRCodeGen::Read(BeBlock*& beBlock)
@@ -932,6 +937,8 @@ void BeIRCodeGen::Read(BeBlock*& beBlock)
 	BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Block);
 	beBlock = (BeBlock*)result.mBeType;
 	BE_MEM_END("BeBlock");
+
+	beBlock->mRefCount++;
 }
 
 void BeIRCodeGen::Read(BeMDNode*& llvmMD)
@@ -947,6 +954,8 @@ void BeIRCodeGen::Read(BeMDNode*& llvmMD)
 	BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Metadata);
 	llvmMD = result.mBeMetadata;
 	BE_MEM_END("BeMDNode");
+
+	llvmMD->mRefCount++;
 }
 
 void BeIRCodeGen::HandleNextCmd()
@@ -2522,9 +2531,62 @@ void BeIRCodeGen::HandleNextCmd()
 			auto inst = mBeModule->AllocInst<BeObjectAccessCheckInst>();
 			inst->mValue = val;
 
-			SetResult(curId, mBeModule->GetInsertBlock());			
+			SetResult(curId, mBeModule->GetInsertBlock());
+		}
+		break;
+	case BfIRCmd_ConstEval_GetBfType:
+		{
+			CMD_PARAM(int32, typeId);
+			CMD_PARAM(BeType*, resultType);
+
+			auto inst = mBeModule->AllocInst<BeConstEvalGetType>();
+			inst->mTypeId = typeId;
+			inst->mResultType = resultType;
+			SetResult(curId, inst);
+		}
+		break;
+	case BfIRCmd_ConstEval_DynamicCastCheck:
+		{
+			CMD_PARAM(BeValue*, value);
+			CMD_PARAM(int32, typeId);
+			CMD_PARAM(BeType*, resultType);
+
+			auto inst = mBeModule->AllocInst<BeConstEvalDynamicCastCheck>();
+			inst->mValue = value;
+			inst->mTypeId = typeId;
+			inst->mResultType = resultType;
+			SetResult(curId, inst);
+		}
+		break;
+	case BfIRCmd_ConstEval_GetVirtualFunc:
+		{
+			CMD_PARAM(BeValue*, value);
+			CMD_PARAM(int32, virtualTableIdx);
+			CMD_PARAM(BeType*, resultType);
+
+			auto inst = mBeModule->AllocInst<BeConstEvalGetVirtualFunc>();
+			inst->mValue = value;
+			inst->mVirtualTableIdx = virtualTableIdx;
+			inst->mResultType = resultType;
+			SetResult(curId, inst);
 		}
 		break;
+	case BfIRCmd_ConstEval_GetInterfaceFunc:
+		{
+			CMD_PARAM(BeValue*, value);
+			CMD_PARAM(int32, ifaceTypeId);
+			CMD_PARAM(int32, virtualTableIdx);
+			CMD_PARAM(BeType*, resultType);
+
+			auto inst = mBeModule->AllocInst<BeConstEvalGetInterfaceFunc>();
+			inst->mValue = value;
+			inst->mIFaceTypeId = ifaceTypeId;
+			inst->mVirtualTableIdx = virtualTableIdx;
+			inst->mResultType = resultType;
+			SetResult(curId, inst);
+		}
+		break;
+
 	case BfIRCmd_DbgInit:
 		{
 			/*mDIBuilder = new BeDIBuilder(*mBeModule);			*/

+ 11 - 0
IDEHelper/Backend/BeModule.cpp

@@ -1723,6 +1723,13 @@ void BeDbgFile::ToString(String& str)
 			str = '\\';
 }
 
+void BeDbgFile::GetFilePath(String& outStr)
+{
+	outStr.Append(mDirectory);
+	outStr.Append(DIR_SEP_CHAR);
+	outStr.Append(mFileName);
+}
+
 //////////////////////////////////////////////////////////////////////////
 
 BeModule::BeModule(const StringImpl& moduleName, BeContext* context)
@@ -2442,6 +2449,10 @@ String BeModule::ToString(BeFunction* wantFunc)
 						}
 					}
 					break;
+				DISPLAY_INST1(BeConstEvalGetType, "ConstEvalGetType", mTypeId);
+				DISPLAY_INST2(BeConstEvalDynamicCastCheck, "ConstEvalDynamicCastCheck", mValue, mTypeId);
+				DISPLAY_INST2(BeConstEvalGetVirtualFunc, "ConstEvalGetVirtualFunc", mValue, mVirtualTableIdx);
+				DISPLAY_INST3(BeConstEvalGetInterfaceFunc, "ConstEvalGetInterfaceFunc", mValue, mIFaceTypeId, mVirtualTableIdx);
 				default:
 					BF_FATAL("Notimpl");
 					str += "<UNKNOWN INST>";

+ 115 - 0
IDEHelper/Backend/BeModule.h

@@ -208,10 +208,12 @@ public:
 #ifdef _DEBUG
 	bool mLifetimeEnded;
 	bool mWasRemoved;
+	int mRefCount;
 	BeValue()
 	{
 		mLifetimeEnded = false;
 		mWasRemoved = false;
+		mRefCount = 0;
 	}
 #endif
 
@@ -264,6 +266,16 @@ T* BeValueDynCast(BeValue* value)
 	return (T*)result;
 }
 
+template <typename T>
+T* BeValueDynCastExact(BeValue* value)
+{
+	if (value == NULL)
+		return NULL;
+	if (value->GetTypeId() != T::TypeId)
+		return NULL;
+	return (T*)value;
+}
+
 class BeBlock;
 class BeInst;
 class BeModule;
@@ -1320,6 +1332,106 @@ public:
 	}
 };
 
+//////////////////////////////////////////////////////////////////////////
+
+class BeConstEvalGetType : public BeInst
+{
+public:
+	BE_VALUE_TYPE(BeConstEvalGetType, BeInst);
+
+public:
+	int mTypeId;
+	BeType* mResultType;
+
+public:	
+	virtual BeType* GetType() override
+	{
+		return mResultType;
+	}
+
+	virtual void HashInst(BeHashContext& hashCtx) override
+	{
+		hashCtx.Mixin(TypeId);
+		hashCtx.Mixin(mTypeId);
+	}
+};
+
+class BeConstEvalDynamicCastCheck : public BeInst
+{
+public:
+	BE_VALUE_TYPE(BeConstEvalDynamicCastCheck, BeInst);
+
+public:
+	BeValue* mValue;
+	int mTypeId;
+	BeType* mResultType;
+
+public:
+	virtual BeType* GetType() override
+	{
+		return mResultType;
+	}
+
+	virtual void HashInst(BeHashContext& hashCtx) override
+	{		
+		hashCtx.Mixin(TypeId);
+		mValue->HashReference(hashCtx);
+		hashCtx.Mixin(mTypeId);
+	}
+};
+
+class BeConstEvalGetVirtualFunc : public BeInst
+{
+public:
+	BE_VALUE_TYPE(BeConstEvalGetVirtualFunc, BeInst);
+
+public:
+	BeValue* mValue;
+	int mVirtualTableIdx;
+	BeType* mResultType;
+
+public:
+	virtual BeType* GetType() override
+	{
+		return mResultType;
+	}
+
+	virtual void HashInst(BeHashContext& hashCtx) override
+	{
+		hashCtx.Mixin(TypeId);
+		mValue->HashReference(hashCtx);
+		hashCtx.Mixin(mVirtualTableIdx);
+	}
+};
+
+class BeConstEvalGetInterfaceFunc : public BeInst
+{
+public:
+	BE_VALUE_TYPE(BeConstEvalGetInterfaceFunc, BeInst);
+
+public:
+	BeValue* mValue;
+	int mIFaceTypeId;
+	int mVirtualTableIdx;
+	BeType* mResultType;
+
+public:
+	virtual BeType* GetType() override
+	{
+		return mResultType;
+	}
+
+	virtual void HashInst(BeHashContext& hashCtx) override
+	{
+		hashCtx.Mixin(TypeId);
+		mValue->HashReference(hashCtx);
+		hashCtx.Mixin(mIFaceTypeId);
+		hashCtx.Mixin(mVirtualTableIdx);
+	}
+};
+
+//////////////////////////////////////////////////////////////////////////
+
 class BeArgument : public BeValue
 {
 public:
@@ -2007,6 +2119,7 @@ public:
 	int mIdx;	
 
 	void ToString(String& str);	
+	void GetFilePath(String& outStr);
 
 	virtual void HashContent(BeHashContext& hashCtx) override
 	{
@@ -2175,6 +2288,8 @@ public:
 	BeRetInst* CreateRet(BeValue* value);	
 	BeCallInst* CreateCall(BeValue* func, const SizedArrayImpl<BeValue*>& args);
 
+	
+
 	BeConstant* GetConstant(BeType* type, double floatVal);
 	BeConstant* GetConstant(BeType* type, int64 intVal);
 	BeConstant* GetConstant(BeType* type, bool boolVal);

+ 5 - 2
IDEHelper/Compiler/BfCompiler.cpp

@@ -406,6 +406,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
 	mGenericIRefEnumeratorTypeDef = NULL;
 	mInlineAttributeTypeDef = NULL;
 	mInternalTypeDef = NULL;
+	mDiagnosticsDebugTypeDef = NULL;
 	mIDisposableTypeDef = NULL;
 	mIPrintableTypeDef = NULL;
 	mIHashableTypeDef = NULL;
@@ -452,11 +453,12 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
 
 BfCompiler::~BfCompiler()
 {		
+	delete mCEMachine;
+	mCEMachine = NULL;
 	delete mContext;
 	delete mHotData;
 	delete mHotState;	
-	delete mHotResolveData;
-	delete mCEMachine;
+	delete mHotResolveData;	
 }
 
 bool BfCompiler::IsTypeAccessible(BfType* checkType, BfProject* curProject)
@@ -6580,6 +6582,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 	mGenericIRefEnumeratorTypeDef = _GetRequiredType("System.Collections.IRefEnumerator", 1);	
 	mInlineAttributeTypeDef = _GetRequiredType("System.InlineAttribute");
 	mInternalTypeDef = _GetRequiredType("System.Internal");
+	mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug");
 	mIDisposableTypeDef = _GetRequiredType("System.IDisposable");
 	mIPrintableTypeDef = _GetRequiredType("System.IPrintable");
 	mIHashableTypeDef = _GetRequiredType("System.IHashable");

+ 1 - 0
IDEHelper/Compiler/BfCompiler.h

@@ -356,6 +356,7 @@ public:
 	BfTypeDef* mGenericIRefEnumeratorTypeDef;
 	
 	BfTypeDef* mInternalTypeDef;
+	BfTypeDef* mDiagnosticsDebugTypeDef;
 	BfTypeDef* mIDisposableTypeDef;
 	BfTypeDef* mIPrintableTypeDef;
 	BfTypeDef* mIHashableTypeDef;

+ 10 - 12
IDEHelper/Compiler/BfContext.cpp

@@ -2756,12 +2756,17 @@ void BfContext::Cleanup()
 	// Can't clean up LLVM types, they are allocated with a bump allocator
 	RemoveInvalidFailTypes();	
 
-	for (auto module : mDeletingModules)
+	// Clean up deleted BfTypes
+	// These need to get deleted before the modules because we access mModule in the MethodInstance dtors
+	for (auto type : mTypeGraveyard)
 	{
-// 		auto itr = std::find(mFinishedModuleWorkList.begin(), mFinishedModuleWorkList.end(), module);
-// 		if (itr != mFinishedModuleWorkList.end())
-// 			mFinishedModuleWorkList.erase(itr);
+		BF_ASSERT(type->mRebuildFlags & BfTypeRebuildFlag_Deleted);
+		delete type;
+	}
+	mTypeGraveyard.Clear();
 
+	for (auto module : mDeletingModules)
+	{
 		int idx = (int)mFinishedModuleWorkList.IndexOf(module);
 		if (idx != -1)		
 			mFinishedModuleWorkList.RemoveAt(idx);		
@@ -2773,14 +2778,7 @@ void BfContext::Cleanup()
 		delete module;
 	}
 	mDeletingModules.Clear();	
-
-	// Clean up deleted BfTypes
-	for (auto type : mTypeGraveyard)
-	{		
-		BF_ASSERT(type->mRebuildFlags & BfTypeRebuildFlag_Deleted);
-		delete type;
-	}
-	mTypeGraveyard.Clear();
+	
 	for (auto typeDef : mTypeDefGraveyard)
 		delete typeDef;
 	mTypeDefGraveyard.Clear();

+ 28 - 12
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -5025,18 +5025,29 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 
 			if (methodInstance->mMethodInstanceGroup->mOwner->IsInterface())
 			{
-				// IFace dispatch
-				auto ifaceTypeInst = methodInstance->mMethodInstanceGroup->mOwner;
-				BfIRValue slotOfs = mModule->GetInterfaceSlotNum(methodInstance->mMethodInstanceGroup->mOwner);
+				if (mModule->mIsConstModule)
+				{
+					funcCallInst = mModule->mBfIRBuilder->ConstEval_GetInterfaceFunc(irArgs[0], methodInstance->mMethodInstanceGroup->mOwner->mTypeId, methodInstance->mVirtualTableIdx, funcPtrType1);
+				}
+				else
+				{
+					// IFace dispatch
+					auto ifaceTypeInst = methodInstance->mMethodInstanceGroup->mOwner;
+					BfIRValue slotOfs = mModule->GetInterfaceSlotNum(methodInstance->mMethodInstanceGroup->mOwner);
 
-				auto vDataPtrPtr = mModule->mBfIRBuilder->CreateBitCast(irArgs[0], funcPtrType4);
-				auto vDataPtr = mModule->FixClassVData(mModule->mBfIRBuilder->CreateLoad(vDataPtrPtr/*, "vtable"*/));
+					auto vDataPtrPtr = mModule->mBfIRBuilder->CreateBitCast(irArgs[0], funcPtrType4);
+					auto vDataPtr = mModule->FixClassVData(mModule->mBfIRBuilder->CreateLoad(vDataPtrPtr/*, "vtable"*/));
 
-				auto ifacePtrPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(vDataPtr, slotOfs/*, "iface"*/);
-				auto ifacePtr = mModule->mBfIRBuilder->CreateLoad(ifacePtrPtr);
+					auto ifacePtrPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(vDataPtr, slotOfs/*, "iface"*/);
+					auto ifacePtr = mModule->mBfIRBuilder->CreateLoad(ifacePtrPtr);
 
-				auto funcPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(ifacePtr, methodInstance->mVirtualTableIdx/*, "vfn"*/);
-				funcCallInst = mModule->mBfIRBuilder->CreateLoad(funcPtr);
+					auto funcPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(ifacePtr, methodInstance->mVirtualTableIdx/*, "vfn"*/);
+					funcCallInst = mModule->mBfIRBuilder->CreateLoad(funcPtr);
+				}
+			}
+			else if (mModule->mIsConstModule)
+			{
+				funcCallInst = mModule->mBfIRBuilder->ConstEval_GetVirtualFunc(irArgs[0], methodInstance->mVirtualTableIdx, funcPtrType1);
 			}
 			else
 			{
@@ -6435,7 +6446,7 @@ SplatArgs(lookupVal, irArgs);
 
 			if (!argValue)
 			{
-				if ((argValues[argExprIdx].mArgFlags & BfArgFlag_StringInterpolateArg) != 0)
+				if ((argExprIdx < (int)argValues.size()) && ((argValues[argExprIdx].mArgFlags & BfArgFlag_StringInterpolateArg) != 0))
 				{					
 					BfAstNode* errorRef = NULL;
 					int checkIdx = argExprIdx - 1;
@@ -12761,7 +12772,8 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 				}
 
 				// Actually leave it alone?
-				if ((isUninit) && (mModule->IsOptimized()))
+				if ((isUninit) && 
+					((mModule->IsOptimized()) || (mModule->mIsConstModule) || (mModule->mBfIRBuilder->mIgnoreWrites)))
 					return;
 
 				bool doClear = true;
@@ -18223,7 +18235,8 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
 				}
 			}
 		}
-		else if ((mModule->HasCompiledOutput()) && (wantsChecks))
+		else if (((mModule->HasCompiledOutput()) || (mModule->mIsConstModule)) && 
+			(wantsChecks))
 		{
 			if (checkedKind == BfCheckedKind_NotSet)
 				checkedKind = mModule->GetDefaultCheckedKind();
@@ -18254,6 +18267,9 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
 						OutputDebugStrF("-OOB %d %d\n", oobFunc.mFunc.mId, oobFunc.mFunc.mFlags);
 					}*/
 
+					if (mModule->mIsConstModule)
+						mModule->mCompiler->mCEMachine->QueueMethod(oobFunc.mMethodInstance, oobFunc.mFunc);
+
 					SizedArray<BfIRValue, 1> args;
 					args.push_back(mModule->GetConstValue(0));
 					mModule->mBfIRBuilder->CreateCall(oobFunc.mFunc, args);

+ 53 - 5
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -3117,6 +3117,7 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDbgDefine)
 
 		auto& fieldInst = boxedType->mFieldInstances.back();
 		auto elementType = fieldInst.mResolvedType;
+		populateModule->PopulateType(elementType, BfPopulateType_Data);
 
 		if (!elementType->IsValuelessType())
 		{
@@ -3872,8 +3873,20 @@ BfIRValue BfIRBuilder::CreateMul(BfIRValue lhs, BfIRValue rhs)
 BfIRValue BfIRBuilder::CreateDiv(BfIRValue lhs, BfIRValue rhs, bool isSigned)
 {
 	if ((lhs.IsConst()) && (rhs.IsConst()))
-	{		
-		BINOP_APPLY(lhs, rhs, /);
+	{
+		auto constLHS = GetConstantById(lhs.mId);
+		auto constRHS = GetConstantById(rhs.mId);
+
+		if ((constLHS->mTypeCode == BfTypeCode_Float) || (constLHS->mTypeCode == BfTypeCode_Double))
+		{
+			double fVal = constLHS->mDouble / constRHS->mDouble;
+			return CreateConst(constLHS->mTypeCode, fVal);
+		}
+
+		if (constRHS->mInt64 != 0)
+		{
+			INT_BINOP_APPLY(constLHS, constRHS, /);			
+		}
 	}
 
 	auto retVal = WriteCmd(isSigned ? BfIRCmd_SDiv : BfIRCmd_UDiv, lhs, rhs);
@@ -3887,10 +3900,17 @@ BfIRValue BfIRBuilder::CreateRem(BfIRValue lhs, BfIRValue rhs, bool isSigned)
 	{	
 		auto constLHS = GetConstantById(lhs.mId);
 		auto constRHS = GetConstantById(rhs.mId);
-		INT_BINOP_APPLY(constLHS, constRHS, %);
 
-		double fVal = fmod(constLHS->mDouble, constRHS->mDouble);
-		return CreateConst(constLHS->mTypeCode, fVal);
+		if ((constLHS->mTypeCode == BfTypeCode_Float) || (constLHS->mTypeCode == BfTypeCode_Double))
+		{
+			double fVal = fmod(constLHS->mDouble, constRHS->mDouble);
+			return CreateConst(constLHS->mTypeCode, fVal);
+		}
+
+		if (constRHS->mInt64 != 0)
+		{
+			INT_BINOP_APPLY(constLHS, constRHS, %);			
+		}
 	}
 
 	auto retVal = WriteCmd(isSigned ? BfIRCmd_SRem : BfIRCmd_URem, lhs, rhs);
@@ -4779,6 +4799,34 @@ void BfIRBuilder::Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage)
 	NEW_CMD_INSERTED;
 }
 
+BfIRValue BfIRBuilder::ConstEval_GetBfType(int typeId, BfIRType resultType)
+{
+	BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_GetBfType, typeId, resultType);
+	NEW_CMD_INSERTED;
+	return retVal;
+}
+
+BfIRValue BfIRBuilder::ConstEval_DynamicCastCheck(BfIRValue value, int typeId, BfIRType resultType)
+{
+	BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_DynamicCastCheck, value, typeId, resultType);
+	NEW_CMD_INSERTED;
+	return retVal;
+}
+
+BfIRValue BfIRBuilder::ConstEval_GetVirtualFunc(BfIRValue value, int virtualTableId, BfIRType resultType)
+{
+	BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_GetVirtualFunc, value, virtualTableId, resultType);
+	NEW_CMD_INSERTED;
+	return retVal;
+}
+
+BfIRValue BfIRBuilder::ConstEval_GetInterfaceFunc(BfIRValue value, int typeId, int virtualTableId, BfIRType resultType)
+{
+	BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_GetInterfaceFunc, value, typeId, virtualTableId, resultType);
+	NEW_CMD_INSERTED;
+	return retVal;
+}
+
 void BfIRBuilder::SaveDebugLocation()
 {	
 	if (!mIgnoreWrites)

+ 10 - 0
IDEHelper/Compiler/BfIRBuilder.h

@@ -281,6 +281,11 @@ enum BfIRCmd : uint8
 	BfIRCmd_Func_SafeRename,
 	BfIRCmd_Func_SetLinkage,
 
+	BfIRCmd_ConstEval_GetBfType,
+	BfIRCmd_ConstEval_DynamicCastCheck,
+	BfIRCmd_ConstEval_GetVirtualFunc,
+	BfIRCmd_ConstEval_GetInterfaceFunc,
+
 	BfIRCmd_SaveDebugLocation,
 	BfIRCmd_RestoreDebugLocation,
 	BfIRCmd_DupDebugLocation,
@@ -1224,6 +1229,11 @@ public:
 	void Func_SafeRename(BfIRFunction func);
 	void Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage);
 	
+	BfIRValue ConstEval_GetBfType(int typeId, BfIRType resultType);
+	BfIRValue ConstEval_DynamicCastCheck(BfIRValue value, int typeId, BfIRType resultType);
+	BfIRValue ConstEval_GetVirtualFunc(BfIRValue value, int virtualTableId, BfIRType resultType);
+	BfIRValue ConstEval_GetInterfaceFunc(BfIRValue value, int typeId, int virtualTableId, BfIRType resultType);
+
 	void SaveDebugLocation();
 	void RestoreDebugLocation();
 	void DupDebugLocation();

+ 73 - 40
IDEHelper/Compiler/BfModule.cpp

@@ -24,6 +24,7 @@
 #include "BfIRCodeGen.h"
 #include "BfDefBuilder.h"
 #include "BfDeferEvalChecker.h"
+#include "CeMachine.h"
 #include <fcntl.h>
 #include <time.h>
 
@@ -1532,7 +1533,7 @@ BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId,
 		auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize;
 
 		typeValueParams.clear();
-		typeValueParams.push_back(objData);				
+		typeValueParams.push_back(objData);
 		if (lenByteCount == 4)
 		{
 			typeValueParams.push_back(GetConstValue32((int)str.length())); // mLength
@@ -1928,8 +1929,7 @@ void BfModule::AddStackAlloc(BfTypedValue val, BfIRValue arraySize, BfAstNode* r
 	//TODO: In the future we could be smarter about statically determining that our value hasn't escaped and eliding this		
 	if (mayEscape)
 	{
-
-		if ((!IsOptimized()) && (!val.mType->IsValuelessType()) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly))
+		if ((!IsOptimized()) && (!mIsConstModule) && (!val.mType->IsValuelessType()) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly))
 		{			
 			auto nullPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
 			bool isDyn = mCurMethodState->mCurScope->IsDyn(scopeData);
@@ -1945,7 +1945,10 @@ void BfModule::AddStackAlloc(BfTypedValue val, BfIRValue arraySize, BfAstNode* r
 				else
 				{
 					SizedArray<BfIRValue, 1> llvmArgs;
-					llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(nullPtrType)));
+					if (IsTargetingBeefBackend())
+						llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(nullPtrType)));
+					else
+						llvmArgs.push_back(val.mValue);
 					llvmArgs.push_back(GetConstValue(val.mType->mSize));
 					llvmArgs.push_back(GetConstValue32(val.mType->mAlign));
 					if (arraySize)
@@ -2029,7 +2032,7 @@ bool BfModule::TryLocalVariableInit(BfLocalVariable* localVar)
 					if (!fieldDef->mDeclaringType->IsExtension())
 						return false; 
 					
-					if ((fieldInstance.mDataIdx != -1) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly))
+					if ((fieldInstance.mDataIdx != -1) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly) && (!mIsConstModule))
 					{												
 						auto curInsertBlock = mBfIRBuilder->GetInsertBlock();						
 						
@@ -2724,6 +2727,12 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
 
 	//BF_ASSERT(refNode != NULL);
 
+	if (mIsConstModule)
+	{
+		mHadBuildError = true;
+		return NULL;
+	}
+
  	if (mCurMethodInstance != NULL)
 		mCurMethodInstance->mHasFailed = true;
 
@@ -4706,6 +4715,8 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou
 BfIRValue BfModule::GetClassVDataPtr(BfTypeInstance* typeInstance)
 {
 	auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef);
+	if (mIsConstModule)
+		return mBfIRBuilder->ConstEval_GetBfType(typeInstance->mTypeId, mBfIRBuilder->MapType(CreatePointerType(classVDataType)));
 	return mBfIRBuilder->CreateBitCast(CreateClassVDataGlobal(typeInstance), mBfIRBuilder->MapType(CreatePointerType(classVDataType)));
 }
 
@@ -6728,7 +6739,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 
 BfIRValue BfModule::FixClassVData(BfIRValue value)
 {
-	if (!mCompiler->mOptions.mObjectHasDebugFlags)
+	if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsConstModule))
 		return value;	
 	auto intptrValue = mBfIRBuilder->CreatePtrToInt(value, BfTypeCode_IntPtr);
 	auto maskedValue = mBfIRBuilder->CreateAnd(intptrValue, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)~0xFFULL));
@@ -8025,7 +8036,7 @@ void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, boo
 	auto destAddr = mBfIRBuilder->CreateBitCast(vObjectAddr, mBfIRBuilder->MapType(ptrPtrType));
 	if (!isAutocomplete)
 	{			
-		if (mCompiler->mOptions.mObjectHasDebugFlags)
+		if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
 		{
 			auto objectPtr = mBfIRBuilder->CreateBitCast(destAddr, mBfIRBuilder->MapType(mContext->mBfObjectType));
 
@@ -8414,8 +8425,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
 					BfIRValue allocaInst;
 					BfIRValue result;
 					if ((typeInstance == NULL) || (typeInstance->mIsCRepr))
-					{
-						sizeValue = mBfIRBuilder->CreateMul(GetConstValue(typeSize), arraySize);
+					{						
 						allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(type), arraySize);						
 						result = allocaInst;
 					}
@@ -8450,28 +8460,32 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
 						bool isConstSize = arraySize.IsConst();
 						BfIRBlock clearBlock;
 						BfIRBlock contBlock;
+						
+						bool wantsDeinit = ((!IsOptimized()) && (!mIsConstModule) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly));
 
-						if (!isConstSize)
+						if (wantsDeinit)
 						{
-							clearBlock = mBfIRBuilder->CreateBlock("clear");
-							contBlock = mBfIRBuilder->CreateBlock("clearCont");
-							mBfIRBuilder->CreateCondBr(mBfIRBuilder->CreateCmpNE(arraySize, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 0)), clearBlock, contBlock);
+							if (!isConstSize)
+							{
+								clearBlock = mBfIRBuilder->CreateBlock("clear");
+								contBlock = mBfIRBuilder->CreateBlock("clearCont");
+								mBfIRBuilder->CreateCondBr(mBfIRBuilder->CreateCmpNE(arraySize, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 0)), clearBlock, contBlock);
 
-							mBfIRBuilder->AddBlock(clearBlock);
-							mBfIRBuilder->SetInsertPoint(clearBlock);
-						}
+								mBfIRBuilder->AddBlock(clearBlock);
+								mBfIRBuilder->SetInsertPoint(clearBlock);
+							}
 
-						AddStackAlloc(typedVal, arraySize, NULL, scopeData, false, true);
+							AddStackAlloc(typedVal, arraySize, NULL, scopeData, false, true);
 
-						if (!isConstSize)
-						{
-							mBfIRBuilder->CreateBr(contBlock);
+							if (!isConstSize)
+							{
+								mBfIRBuilder->CreateBr(contBlock);
 
-							mBfIRBuilder->AddBlock(contBlock);
-							mBfIRBuilder->SetInsertPoint(contBlock);
+								mBfIRBuilder->AddBlock(contBlock);
+								mBfIRBuilder->SetInsertPoint(contBlock);
+							}
 						}
-					}
-					//InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue);
+					}					
 
 					return result;
 				}
@@ -8707,6 +8721,8 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
 			auto typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx);
 			stackCount = BfTypeOptions::Apply(stackCount, typeOptions->mAllocStackTraceDepth);
 		}
+		if (mIsConstModule)
+			stackCount = 0;
 
 		if (!sizeValue)
 			sizeValue = GetConstValue(typeInstance->mInstSize);
@@ -8777,7 +8793,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
 		{			
 			if (hasCustomAllocator)
 				result = AllocBytes(allocTarget.mRefNode, allocTarget, typeInstance, sizeValue, GetConstValue(typeInstance->mInstAlign), (BfAllocFlags)(BfAllocFlags_ZeroMemory | BfAllocFlags_NoDefaultToMalloc));				
-			else if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mCompiler->mOptions.mDebugAlloc))
+			else if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule))
 			{
 				SizedArray<BfIRValue, 4> llvmArgs;
 				llvmArgs.push_back(sizeValue);
@@ -8790,7 +8806,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
 
 		if (result)
 		{	
-			if (mCompiler->mOptions.mObjectHasDebugFlags)
+			if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
 			{
 				auto objectPtr = mBfIRBuilder->CreateBitCast(result, mBfIRBuilder->MapTypeInstPtr(mContext->mBfObjectType));
 				SizedArray<BfIRValue, 4> llvmArgs;
@@ -8828,7 +8844,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
 			auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef);			
 			auto vData = mBfIRBuilder->CreateBitCast(vDataRef, mBfIRBuilder->MapTypeInstPtr(classVDataType->ToTypeInstance()));			
 
-			if (mCompiler->mOptions.mObjectHasDebugFlags)
+			if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
 			{
 				SizedArray<BfIRValue, 4> llvmArgs;
 				llvmArgs.push_back(vData);
@@ -8844,7 +8860,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
 				SizedArray<BfIRValue, 4> llvmArgs;
 				llvmArgs.push_back(sizeValue);
 				BfIRFunction irFunc;
-				if (mCompiler->mOptions.mDebugAlloc)
+				if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule))
 				{
 					auto moduleMethodInstance = GetInternalMethod("Dbg_RawObjectAlloc", 1);
 					irFunc = moduleMethodInstance.mFunc;
@@ -9062,7 +9078,7 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue,
 		auto curThis = GetThis();
 
 		BfIRValue newFlags;
-		if (mCompiler->mOptions.mObjectHasDebugFlags)
+		if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
 		{
 			auto thisFlagsPtr = mBfIRBuilder->CreateBitCast(curThis.mValue, ptrType);
 			auto thisFlags = mBfIRBuilder->CreateLoad(thisFlagsPtr);
@@ -9078,7 +9094,7 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue,
 		auto srcVal = mBfIRBuilder->CreateBitCast(vDataRef, ptrType);
 		mBfIRBuilder->CreateStore(srcVal, destAddr);
 
-		if (mCompiler->mOptions.mObjectHasDebugFlags)
+		if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
 		{
 			auto flagsPtr = mBfIRBuilder->CreateBitCast(destAddr, ptrType);
 			mBfIRBuilder->CreateStore(newFlags, flagsPtr);
@@ -9129,7 +9145,7 @@ void BfModule::SkipObjectAccessCheck(BfTypedValue typedVal)
 	if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck))
 		return;
 
-	if (!mCompiler->mOptions.mObjectHasDebugFlags)
+	if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsConstModule))
 		return;
 	
 	if ((typedVal.mValue.mFlags & BfIRValueFlags_Value) == 0)
@@ -9143,7 +9159,7 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
 	if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck))
 		return;
 
-	if (!mCompiler->mOptions.mObjectHasDebugFlags)
+	if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsConstModule))
 		return;
 
 	if (typedVal.mValue.IsConst())
@@ -9187,8 +9203,17 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
 {	
 	if (mBfIRBuilder->mIgnoreWrites)
 		return; // Nothing needed here
-
+	
 	auto irb = mBfIRBuilder;
+
+	if (mIsConstModule)
+	{
+		auto callResult = mBfIRBuilder->ConstEval_DynamicCastCheck(targetValue.mValue, targetType->mTypeId, mBfIRBuilder->MapType(mContext->mBfObjectType));
+		auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult, GetDefaultValue(mContext->mBfObjectType));
+		irb->CreateCondBr(cmpResult, trueBlock, falseBlock);
+		return;
+	}
+
 	auto checkBB = irb->CreateBlock("as.check");
 	auto isNull = irb->CreateIsNull(targetValue.mValue);
 	mBfIRBuilder->CreateCondBr(isNull, nullSucceeds ? trueBlock : falseBlock, checkBB);
@@ -9212,7 +9237,6 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
 		irArgs.push_back(objectParam);
 		irArgs.push_back(GetConstValue32(targetType->mTypeId));
 		auto callResult = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
-		auto resultType = ResolveTypeDef(mSystem->mTypeBool);
 		auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult.mValue, GetDefaultValue(callResult.mType));
 		irb->CreateCondBr(cmpResult, trueBlock, falseBlock);
 	}
@@ -9221,7 +9245,7 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
 		AddBasicBlock(checkBB);
 		BfIRValue vDataPtr = irb->CreateBitCast(targetValue.mValue, irb->MapType(intPtrType));
 		vDataPtr = irb->CreateLoad(vDataPtr);
-		if (mCompiler->mOptions.mObjectHasDebugFlags)
+		if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
 			vDataPtr = irb->CreateAnd(vDataPtr, irb->CreateConst(BfTypeCode_IntPtr, (uint64)~0xFFULL));
 	
 		if (targetType->IsInterface())
@@ -13531,13 +13555,13 @@ BfLocalVariable* BfModule::AddLocalVariableDef(BfLocalVariable* localVarDef, boo
 		BF_ASSERT(rootMethodState->mCurLocalVarId >= 0);
 		localVarDef->mLocalVarId = rootMethodState->mCurLocalVarId++;
 	}
-	if ((localVarDef->mNameNode != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
+	if ((localVarDef->mNameNode != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) && (!mIsConstModule))
 		mCompiler->mResolvePassData->mAutoComplete->CheckLocalDef(localVarDef->mNameNode, localVarDef);
 
 	if ((localVarDef->mNameNode != NULL) && (mCurMethodInstance != NULL))
 	{		
 		bool isClosureProcessing = (mCurMethodState->mClosureState != NULL) && (!mCurMethodState->mClosureState->mCapturing);		
-		if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL))
+		if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL) && (!mIsConstModule))
 			mCompiler->mResolvePassData->HandleLocalReference(localVarDef->mNameNode, rootMethodState->mMethodInstance->GetOwner()->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVarDef->mLocalVarId);
 	}
 	
@@ -14513,7 +14537,7 @@ BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArr
 {
 	BP_ZONE("BfModule::TryConstCalcAppend");
 
-	if (mCompiler->mIsResolveOnly)
+	if ((mCompiler->mIsResolveOnly) && (!mIsConstModule))
 		return BfTypedValue();
 
 	// We want to regenerate all ctor calls when the method internals change
@@ -14798,7 +14822,7 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly)
 // This method never throws errors - it relies on the proper ctor actually throwing the errors
 void BfModule::EmitCtorCalcAppend()
 {
-	if (mCompiler->mIsResolveOnly)
+	if ((mCompiler->mIsResolveOnly) && (!mIsConstModule))
 		return;
 
 	auto methodDef = mCurMethodInstance->mMethodDef;
@@ -14939,6 +14963,8 @@ void BfModule::EmitDtorBody()
 		// Fall through to Object::~this call
 		
 		auto dtorFunc = GetMethodByName(mContext->mBfObjectType, "~this");
+		if (mIsConstModule)
+			mCompiler->mCEMachine->QueueMethod(dtorFunc.mMethodInstance, dtorFunc.mFunc);
 		auto basePtr = mBfIRBuilder->CreateBitCast(thisVal.mValue, mBfIRBuilder->MapTypeInstPtr(mContext->mBfObjectType));
 		SizedArray<BfIRValue, 1> vals = { basePtr };
 		result = mBfIRBuilder->CreateCall(dtorFunc.mFunc, vals);
@@ -15115,6 +15141,8 @@ void BfModule::EmitDtorBody()
 							auto basePtr = mBfIRBuilder->CreateBitCast(mCurMethodState->mLocals[0]->mValue, mBfIRBuilder->MapTypeInstPtr(checkBaseType));
 							SizedArray<BfIRValue, 1> vals = { basePtr };
 							auto callInst = mBfIRBuilder->CreateCall(dtorMethodInstance.mFunc, vals);
+							if (mIsConstModule)
+								mCompiler->mCEMachine->QueueMethod(dtorMethodInstance.mMethodInstance, dtorMethodInstance.mFunc);
 							mBfIRBuilder->SetCallCallingConv(callInst, GetIRCallingConvention(dtorMethodInstance.mMethodInstance));
 						}
 					}
@@ -15649,6 +15677,8 @@ void BfModule::EmitCtorBody(bool& skipBody)
 				SizedArray<BfIRValue, 1> irArgs;
 				exprEvaluator.PushThis(NULL, GetThis(), moduleMethodInstance.mMethodInstance, irArgs);
 				exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
+				if (mIsConstModule)
+					mCompiler->mCEMachine->QueueMethod(moduleMethodInstance);
 
 				calledCtorNoBody = true;
 			}
@@ -15984,6 +16014,8 @@ void BfModule::EmitCtorBody(bool& skipBody)
 				auto callingConv = GetIRCallingConvention(ctorBodyMethodInstance.mMethodInstance);
 				if (callingConv != BfIRCallingConv_CDecl)
 					mBfIRBuilder->SetCallCallingConv(callInst, callingConv);				
+				if (mIsConstModule)
+					mCompiler->mCEMachine->QueueMethod(ctorBodyMethodInstance);
 			}
 
 			if (matchedMethod == NULL)
@@ -20384,7 +20416,8 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man
 				// We can have a collision of names when we have generic methods that differ only in
 				//  their constraints, but they should only collide in their unspecialized form
 				//  since only one will be chosen for a given concrete type		
-				mCurMethodInstance->mMangleWithIdx = true;
+				if (!mIsConstModule)
+					mCurMethodInstance->mMangleWithIdx = true;
 				mangledName.Clear();
 				BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), mCurMethodInstance);
 				prevFunc = mBfIRBuilder->GetFunction(mangledName);

+ 8 - 7
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -535,6 +535,13 @@ BfMethodInfoEx::~BfMethodInfoEx()
 
 BfMethodInstance::~BfMethodInstance()
 {		
+	if (mInCEMachine)
+	{
+		auto module = GetOwner()->mModule;
+		if (module->mCompiler->mCEMachine != NULL)
+			module->mCompiler->mCEMachine->RemoveMethod(this);
+	}
+
 	if (mHasMethodRefType)
 	{				
 		auto module = GetOwner()->mModule;
@@ -557,13 +564,7 @@ BfMethodInstance::~BfMethodInstance()
 		mHotMethod->Deref();
 	}	
 
-	delete mMethodInfoEx;
-
-	if (mInCEMachine)
-	{
-		auto module = GetOwner()->mModule;
-		module->mCompiler->mCEMachine->RemoveMethod(this);
-	}
+	delete mMethodInfoEx;	
 }
 
 BfImportKind BfMethodInstance::GetImportKind()

+ 3 - 2
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -55,7 +55,8 @@ enum BfMethodNameFlags : uint8
 	BfMethodNameFlag_None = 0,
 	BfMethodNameFlag_ResolveGenericParamNames = 1,
 	BfMethodNameFlag_OmitTypeName = 2,
-	BfMethodNameFlag_IncludeReturnType = 4
+	BfMethodNameFlag_IncludeReturnType = 4,
+	BfMethodNameFlag_OmitParams = 8
 };
 
 enum BfGetMethodInstanceFlags : uint16
@@ -1416,7 +1417,7 @@ public:
 		mMethodRefFlags = BfMethodRefFlag_None;
 	}
 
-	BfMethodRef(BfMethodInstance* methodInstance);
+	BfMethodRef(BfMethodInstance* methodInstance);	
 
 	operator BfMethodInstance*() const;
 	bool IsNull() { return mTypeInstance == NULL; };

+ 3 - 2
IDEHelper/Compiler/BfStmtEvaluator.cpp

@@ -42,7 +42,8 @@ USING_NS_BF;
 
 bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfScopeData* scopeData)
 {		
-	if (((mCompiler->mIsResolveOnly) || (mBfIRBuilder->mIgnoreWrites)) && (deferredCallEntry->mDeferredBlock == NULL))
+	if ((((mCompiler->mIsResolveOnly) && (!mIsConstModule)) || 
+		(mBfIRBuilder->mIgnoreWrites)) && (deferredCallEntry->mDeferredBlock == NULL))
 	{
 		// For resolve entries, we only keep deferred blocks because we need to process them later so we can
 		//  resolve inside of them.  This is also required for lambda bind scan-pass
@@ -782,7 +783,7 @@ void BfModule::EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, Siz
 
 void BfModule::EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry, bool moveBlocks)
 {	
-	if ((mCompiler->mIsResolveOnly) && (deferredCallEntry.mHandlerCount > 0))
+	if ((mCompiler->mIsResolveOnly) && (!mIsConstModule) && (deferredCallEntry.mHandlerCount > 0))
 	{
 		// We only want to process deferred blocks once, otherwise it could significantly slow down autocompletion
 		return;

+ 30 - 19
IDEHelper/Compiler/BfSystem.cpp

@@ -928,6 +928,7 @@ bool BfProject::IsTestProject()
 
 BfErrorBase::~BfErrorBase()
 {
+	delete mLocation;
 }
 
 void BfErrorBase::SetSource(BfPassInstance* passInstance, BfSourceData* source)
@@ -1598,9 +1599,8 @@ BfError* BfPassInstance::WarnAfter(int warningNumber, const StringImpl& warning,
 	return WarnAt(warningNumber, warning, refNode->GetSourceData(), refNode->GetSrcEnd());
 }
 
-BfError* BfPassInstance::MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags)
-{	
-	String msgPrefix;
+BfMoreInfo* BfPassInstance::MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags)
+{		
 	if (!mLastWasDisplayed)
 	{
 		if (mLastWasAdded)
@@ -1612,25 +1612,20 @@ BfError* BfPassInstance::MoreInfoAt(const StringImpl& info, BfSourceData* bfSour
 			moreInfo->mSrcStart = srcIdx;
 			moreInfo->mSrcEnd = srcIdx + srcLen;
 
-			if (lastError->mIsWarning)
-				msgPrefix = ":warn";
-			else
-				msgPrefix = ":error";
-
 			lastError->mMoreInfo.push_back(moreInfo);
+			return moreInfo;
 		}
 
 		return NULL;
 	}
 
+	String msgPrefix;
 	MessageAt(msgPrefix, " > " + info, bfSource, srcIdx, srcLen, flags);
 	return NULL;
 }
 
-BfError* BfPassInstance::MoreInfo(const StringImpl& info)
-{
-	String outText;
-
+BfMoreInfo* BfPassInstance::MoreInfo(const StringImpl& info)
+{	
 	if (!mLastWasDisplayed)
 	{
 		if (mLastWasAdded)
@@ -1642,23 +1637,21 @@ BfError* BfPassInstance::MoreInfo(const StringImpl& info)
 			moreInfo->mSrcStart = -1;
 			moreInfo->mSrcEnd = -1;
 
-			if (lastError->mIsWarning)
-				outText = ":warn ";
-			else
-				outText = ":error ";
-
 			lastError->mMoreInfo.push_back(moreInfo);
+			return moreInfo;
 		}
 
 		return NULL;
 	}
 	
+	String outText;
+	outText += "  > ";
 	outText += info;
 	OutputLine(outText);
 	return NULL;
 }
 
-BfError* BfPassInstance::MoreInfo(const StringImpl& info, BfAstNode* refNode)
+BfMoreInfo* BfPassInstance::MoreInfo(const StringImpl& info, BfAstNode* refNode)
 {	
 	if (refNode == NULL)
 		return MoreInfo(info);
@@ -1666,7 +1659,7 @@ BfError* BfPassInstance::MoreInfo(const StringImpl& info, BfAstNode* refNode)
 		return MoreInfoAt(info, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength());
 }
 
-BfError* BfPassInstance::MoreInfoAfter(const StringImpl& info, BfAstNode* refNode)
+BfMoreInfo* BfPassInstance::MoreInfoAfter(const StringImpl& info, BfAstNode* refNode)
 {
 	return MoreInfoAt(info, refNode->GetSourceData(), refNode->GetSrcEnd(), 1);
 }
@@ -3486,6 +3479,14 @@ BF_EXPORT const char* BF_CALLTYPE BfPassInstance_GetErrorData(BfPassInstance* bf
 			}
 		}
 	}
+
+	if (bfError->mLocation != NULL)
+	{
+		fileName = (char*)bfError->mLocation->mFile.c_str();
+		*outLine = bfError->mLocation->mLine;
+		*outColumn = bfError->mLocation->mColumn;
+	}
+
 	outSrcStart = bfError->mSrcStart;
 	outSrcEnd = bfError->mSrcEnd;
 	outMoreInfoCount = (int)bfError->mMoreInfo.size();
@@ -3504,6 +3505,16 @@ BF_EXPORT const char* BfPassInstance_Error_GetMoreInfoData(BfPassInstance* bfPas
 			fileName = (char*)srcFileName->c_str();
 		}		
 	}
+
+	if (moreInfo->mLocation != NULL)
+	{
+		fileName = (char*)moreInfo->mLocation->mFile.c_str();
+		if (outLine != NULL)
+			*outLine = moreInfo->mLocation->mLine;
+		if (outColumn != NULL)
+			*outColumn = moreInfo->mLocation->mColumn;
+	}
+
 	srcStart = moreInfo->mSrcStart;
 	srcEnd = moreInfo->mSrcEnd;
 	return moreInfo->mInfo.c_str();

+ 15 - 5
IDEHelper/Compiler/BfSystem.h

@@ -1122,6 +1122,14 @@ enum BfWarning
 	BfWarning_C4554_PossiblePrecedenceError				= 4554
 };
 
+class BfErrorLocation
+{
+public:
+	String mFile;
+	int mLine;
+	int mColumn;
+};
+
 class BfErrorBase
 {
 public:
@@ -1129,7 +1137,8 @@ public:
 	bool mIsDeferred;
 	BfSourceData* mSource;	
 	int mSrcStart;
-	int mSrcEnd;
+	int mSrcEnd;	
+	BfErrorLocation* mLocation;
 
 public:
 	BfErrorBase()
@@ -1139,6 +1148,7 @@ public:
 		mSource = NULL;		
 		mSrcStart = -1;
 		mSrcEnd = -1;
+		mLocation = NULL;
 	}
 
 	~BfErrorBase();
@@ -1278,10 +1288,10 @@ public:
 	BfError* Warn(int warningNumber, const StringImpl& warning, BfAstNode* refNode);
 	BfError* WarnAfter(int warningNumber, const StringImpl& warning, BfAstNode* refNode);
 
-	BfError* MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags = BfFailFlag_None);
-	BfError* MoreInfo(const StringImpl& info);
-	BfError* MoreInfo(const StringImpl& info, BfAstNode* refNode);
-	BfError* MoreInfoAfter(const StringImpl& info, BfAstNode* refNode);
+	BfMoreInfo* MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags = BfFailFlag_None);
+	BfMoreInfo* MoreInfo(const StringImpl& info);
+	BfMoreInfo* MoreInfo(const StringImpl& info, BfAstNode* refNode);
+	BfMoreInfo* MoreInfoAfter(const StringImpl& info, BfAstNode* refNode);
 
 	BfError* FailAt(const StringImpl& error, BfSourceData* bfSource, int srcIdx, int srcLen = 1, BfFailFlags flags = BfFailFlag_None);
 	BfError* FailAfterAt(const StringImpl& error, BfSourceData* bfSource, int srcIdx);

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 584 - 324
IDEHelper/Compiler/CeMachine.cpp


+ 176 - 22
IDEHelper/Compiler/CeMachine.h

@@ -2,6 +2,8 @@
 
 #include "BfSystem.h"
 #include "BfModule.h"
+#include "BeefySysLib/util/Heap.h"
+#include "BeefySysLib/util/AllocDebug.h"
 
 NS_BF_BEGIN
 
@@ -19,6 +21,8 @@ class BeSwitchInst;
 class CeMachine;
 class CeFunction;
 
+typedef int addr_ce;
+
 #define CEOP_SIZED(OPNAME) \
 	CeOp_##OPNAME##_8, \
 	CeOp_##OPNAME##_16, \
@@ -32,6 +36,12 @@ class CeFunction;
 	CeOp_##OPNAME##_I32, \
 	CeOp_##OPNAME##_I64
 
+#define CEOP_SIZED_UNUMERIC(OPNAME) \
+	CeOp_##OPNAME##_U8, \
+	CeOp_##OPNAME##_U16, \
+	CeOp_##OPNAME##_U32, \
+	CeOp_##OPNAME##_U64
+
 #define CEOP_SIZED_NUMERIC_PLUSF(OPNAME) \
 	CeOp_##OPNAME##_I8, \
 	CeOp_##OPNAME##_I16, \
@@ -40,6 +50,14 @@ class CeFunction;
 	CeOp_##OPNAME##_F32, \
 	CeOp_##OPNAME##_F64
 
+enum CeErrorKind
+{
+	CeErrorKind_None,
+	CeErrorKind_GlobalVariable,
+	CeErrorKind_FunctionPointer,
+	CeErrorKind_Intrinsic
+};
+
 enum CeOp : int16
 {
 	CeOp_InvalidOp,
@@ -48,6 +66,16 @@ enum CeOp : int16
 	CeOp_JmpIf,
 	CeOp_JmpIfNot,
 
+	CeOp_Error,	
+	CeOp_DynamicCastCheck,
+	CeOp_GetString,
+	CeOp_Malloc,
+	CeOp_Free,
+	
+	CeOp_MemSet,
+	CeOp_MemSet_Const,
+	CeOp_MemCpy,
+	
 	CeOp_FrameAddr_32,
 	CeOp_FrameAddr_64,
 
@@ -60,25 +88,82 @@ enum CeOp : int16
 	CEOP_SIZED(Pop),
 
 	CeOp_AdjustSP,
+	CeOp_AdjustSPNeg,
+	CeOp_AdjustSPConst,
+	CeOp_GetSP,
+	CeOp_SetSP,
 	CeOp_Call,
-
+	CeOp_Call_Virt,
+	CeOp_Call_IFace,
+	
+	CeOp_Conv_I8_I16,
+	CeOp_Conv_I8_I32,
+	CeOp_Conv_I8_I64,
+	CeOp_Conv_I8_F32,
+	CeOp_Conv_I8_F64,
+	CeOp_Conv_I16_I32,
+	CeOp_Conv_I16_I64,
+	CeOp_Conv_I16_F32,
+	CeOp_Conv_I16_F64,
 	CeOp_Conv_I32_I64,
+	CeOp_Conv_I32_F32,
+	CeOp_Conv_I32_F64,	
+	CeOp_Conv_I64_F32,
+	CeOp_Conv_I64_F64,
+	CeOp_Conv_U8_U16,
+	CeOp_Conv_U8_U32,
+	CeOp_Conv_U8_U64,
+	CeOp_Conv_U8_F32,
+	CeOp_Conv_U8_F64,
+	CeOp_Conv_U16_U32,
+	CeOp_Conv_U16_U64,
+	CeOp_Conv_U16_F32,
+	CeOp_Conv_U16_F64,
+	CeOp_Conv_U32_U64,
+	CeOp_Conv_U32_F32,
+	CeOp_Conv_U32_F64,
+	CeOp_Conv_U64_F32,
+	CeOp_Conv_U64_F64,
+	CeOp_Conv_F32_I8,
+	CeOp_Conv_F32_I16,
+	CeOp_Conv_F32_I32,
+	CeOp_Conv_F32_I64,
+	CeOp_Conv_F32_F64,
+	CeOp_Conv_F64_I8,
+	CeOp_Conv_F64_I16,
+	CeOp_Conv_F64_I32,
+	CeOp_Conv_F64_I64,
+	CeOp_Conv_F64_F32,
 
 	CEOP_SIZED_NUMERIC_PLUSF(AddConst),
 	CEOP_SIZED_NUMERIC_PLUSF(Add),
 	CEOP_SIZED_NUMERIC_PLUSF(Sub),
 	CEOP_SIZED_NUMERIC_PLUSF(Mul),	
-	CEOP_SIZED_NUMERIC_PLUSF(SDiv),
-	CEOP_SIZED_NUMERIC(UDiv),
-	CEOP_SIZED_NUMERIC_PLUSF(SMod),
-	CEOP_SIZED_NUMERIC(UMod),
+	CEOP_SIZED_NUMERIC_PLUSF(Div),
+	CEOP_SIZED_UNUMERIC(Div),
+	CEOP_SIZED_NUMERIC_PLUSF(Mod),
+	CEOP_SIZED_UNUMERIC(Mod),
+	CEOP_SIZED_NUMERIC(And),
+	CEOP_SIZED_NUMERIC(Or),
+	CEOP_SIZED_NUMERIC(Xor),
+	CEOP_SIZED_NUMERIC(Shl),
+	CEOP_SIZED_NUMERIC(Shr),
+	CEOP_SIZED_UNUMERIC(Shr),
+
 	CEOP_SIZED_NUMERIC_PLUSF(Cmp_EQ),
+	CEOP_SIZED_NUMERIC_PLUSF(Cmp_NE),
 	CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLT),
 	CEOP_SIZED_NUMERIC(Cmp_ULT),
 	CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLE),
 	CEOP_SIZED_NUMERIC(Cmp_ULE),
+	CEOP_SIZED_NUMERIC_PLUSF(Cmp_SGT),
+	CEOP_SIZED_NUMERIC(Cmp_UGT),
+	CEOP_SIZED_NUMERIC_PLUSF(Cmp_SGE),
+	CEOP_SIZED_NUMERIC(Cmp_UGE),
 
 	CEOP_SIZED_NUMERIC_PLUSF(Neg),
+	CeOp_Not_I1,
+	CEOP_SIZED_NUMERIC(Not),
 
 	CeOp_COUNT
 };
@@ -91,43 +176,95 @@ struct CeEmitEntry
 	int mColumn;
 };
 
+class CeFunctionInfo
+{
+public:
+	String mName;
+	BfMethodInstance* mMethodInstance;
+	BfMethodRef mMethodRef;
+	CeFunction* mCeFunction;
+	int mRefCount;
+
+public:
+	CeFunctionInfo()
+	{
+		mMethodInstance = NULL;
+		mCeFunction = NULL;
+		mRefCount = 0;
+	}
+};
+
 class CeCallEntry
 {
 public:
-	String mFunctionName;
+	CeFunctionInfo* mFunctionInfo;
 	int mBindRevision;
 	CeFunction* mFunction;
 
 public:
 	CeCallEntry()
 	{
+		mFunctionInfo = NULL;
 		mBindRevision = -1;
 		mFunction = NULL;
 	}
 };
 
+class CeStringEntry
+{
+public:
+	int mStringId;
+	int mBindExecuteId;
+	addr_ce mStringAddr;
+
+public:
+	CeStringEntry()
+	{
+		mStringId = -1;
+		mBindExecuteId = -1;
+		mStringAddr = 0;
+	}
+};
+
+enum CeFunctionKind
+{
+	CeFunctionKind_Normal,
+	CeFunctionKind_Extern,
+	CeFunctionKind_OOB,
+	CeFunctionKind_FatalError,
+	CeFunctionKind_DebugWrite,
+	CeFunctionKind_DebugWrite_Int,
+};
+
 class CeFunction
 {
 public:
+	CeFunctionInfo* mCeFunctionInfo;
 	BfMethodInstance* mMethodInstance;
-	String mName;
+	CeFunctionKind mFunctionKind;
 	bool mInitialized;
 	bool mFailed;		
 	Array<uint8> mCode;	
 	Array<String> mFiles;
 	Array<CeEmitEntry> mEmitTable;
 	Array<CeCallEntry> mCallTable;
+	Array<CeStringEntry> mStringTable;
+	Array<BfType*> mTypeTable;
 	String mGenError;
-	int mFrameSize;
+	int mFrameSize;	
 
 public:
 	CeFunction()
 	{
+		mCeFunctionInfo = NULL;
+		mFunctionKind = CeFunctionKind_Normal;
 		mInitialized = false;
 		mMethodInstance = NULL;
 		mFailed = false;
 		mFrameSize = 0;
 	}	
+
+	~CeFunction();
 };
 
 enum CeEvalFlags
@@ -176,6 +313,7 @@ public:
 };
 
 #define BF_CE_STACK_SIZE 1024*1024
+#define BF_CE_MAX_MEMORY 128*1024*1024
 
 enum CeOperandInfoKind
 {
@@ -247,7 +385,7 @@ public:
 class CeBuilder
 {
 public:	
-	CeMachine* mCeMachine;
+	CeMachine* mCeMachine;	
 	CeFunction* mCeFunction;
 	BeFunction* mBeFunction;	
 	CeOperand mReturnVal;	
@@ -262,6 +400,7 @@ public:
 	int mFrameSize;
 	Dictionary<BeDbgFile*, int> mDbgFileMap;
 	Dictionary<BeFunction*, int> mFunctionMap;
+	Dictionary<int, int> mStringMap;
 	
 public:
 	CeBuilder()
@@ -277,14 +416,16 @@ public:
 	void Fail(const StringImpl& error);
 
 	CeOperand FrameAlloc(BeType* type);
+	CeOperand EmitConst(int64 val, int size);
 	CeOperand GetOperand(BeValue* value, bool allowAlloca = false, bool allowImmediate = false);
 	CeSizeClass GetSizeClass(int size);
 	int GetCodePos();
 
 	void HandleParams();
-
-	void Emit(uint8 val);	
+	
+	void Emit(uint8 val);
 	void Emit(CeOp val);
+	void EmitSizedOp(CeOp val, int size);
 	void Emit(int32 val);
 	void Emit(int64 val);
 	void Emit(bool val);
@@ -305,35 +446,42 @@ class CeFrame
 {
 public:
 	CeFunction* mFunction;
-	uint8* mStackPtr;	
-	uint8* mFramePtr;
+	addr_ce mStackAddr;
+	addr_ce mFrameAddr;
 	uint8* mInstPtr;
 
 public:
 	CeFrame()
 	{
 		mFunction = NULL;
-		mStackPtr = NULL;
-		mFramePtr = NULL;
+		mStackAddr = NULL;
+		mFrameAddr = NULL;
 		mInstPtr = NULL;
 	}
 };
 
+class CeFunctionRef
+{
+	//CeFunction* ;
+};
+
 class CeMachine
 {
 public:
-	Dictionary<BfMethodInstance*, CeFunction*> mFunctions;
-	Dictionary<String, CeFunction*> mNamedFunctionMap;
+	Dictionary<BfMethodInstance*, CeFunctionInfo*> mFunctions;
+	Dictionary<String, CeFunctionInfo*> mNamedFunctionMap;
 	BfCompiler* mCompiler;
 	BfModule* mCeModule;
 	int mRevision;
-	
-	Array<CeFrame> mCallStack;
-	Array<uint8> mMemory;	
-	uint8* mStackMin;	
+	int mExecuteId;
 
+	ContiguousHeap* mHeap;
+	Array<CeFrame> mCallStack;
+	Array<uint8> mMemory;
+	Dictionary<int, addr_ce> mStringMap;
+	
 	BfAstNode* mCurTargetSrc;
-	BfModule* mCurModule;
+	BfModule* mCurModule;	
 
 public:
 	CeMachine(BfCompiler* compiler);
@@ -342,8 +490,12 @@ public:
 	BfError* Fail(const CeFrame& curFrame, const StringImpl& error);
 
 	void Init();	
+	uint8* CeMalloc(int size);
+	bool CeFree(addr_ce addr);
+
 	BeContext* GetBeContext();
 	BeModule* GetBeModule();
+	void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo);
 	void RemoveMethod(BfMethodInstance* methodInstance);
 	int GetConstantSize(BfConstant* constant);
 	void WriteConstant(uint8* ptr, BfConstant* constant);
@@ -352,10 +504,12 @@ public:
 
 	void PrepareFunction(CeFunction* methodInstance);	
 	CeFunction* GetFunction(BfMethodInstance* methodInstance, BfIRValue func, bool& added);
+	CeFunction* GetPreparedFunction(BfMethodInstance* methodInstance);
 
 public:
 	void CompileStarted();
 	void QueueMethod(BfMethodInstance* methodInstance, BfIRValue func);
+	void QueueMethod(BfModuleMethodInstance moduleMethodInstance);
 	BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags);
 };
 

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio