瀏覽代碼

Optimizations, switching CanImplicitlyCast method, new CPU rate checker

Brian Fiete 5 年之前
父節點
當前提交
098ad1ce55

+ 4 - 4
BeefLibs/corlib/src/Event.bf

@@ -51,7 +51,7 @@ namespace System
 			{
 			{
 				if (mData & sIsEnumerating != 0)
 				if (mData & sIsEnumerating != 0)
 				{
 				{
-					Enumerator* enumerator = (Enumerator*)(mData & sDataMask);
+					Enumerator* enumerator = (Enumerator*)(void*)(mData & sDataMask);
 					return enumerator.[Friend]mTarget;
 					return enumerator.[Friend]mTarget;
 				}
 				}
 				return Internal.UnsafeCastToObject((void*)mData);
 				return Internal.UnsafeCastToObject((void*)mData);
@@ -61,7 +61,7 @@ namespace System
 			{
 			{
 				if (mData & sIsEnumerating != 0)
 				if (mData & sIsEnumerating != 0)
 				{
 				{
-					Enumerator* enumerator = (Enumerator*)(mData & sDataMask);
+					Enumerator* enumerator = (Enumerator*)(void*)(mData & sDataMask);
 					enumerator.[Friend]mTarget = value;
 					enumerator.[Friend]mTarget = value;
 				}
 				}
 				else
 				else
@@ -249,12 +249,12 @@ namespace System
 					if (mEvent.mData & sIsEnumerating == 0)
 					if (mEvent.mData & sIsEnumerating == 0)
 					{
 					{
 						mTarget = mEvent.Target;
 						mTarget = mEvent.Target;
-						mEvent.mData = (int)(&this) | sIsEnumerating;
+						mEvent.mData = (int)(void*)(&this) | sIsEnumerating;
 						mRootEnumerator = &this;
 						mRootEnumerator = &this;
 					}
 					}
 					else
 					else
 					{
 					{
-						mRootEnumerator = (Enumerator*)(mEvent.mData & Event<T>.sDataMask);
+						mRootEnumerator = (Enumerator*)(void*)(mEvent.mData & Event<T>.sDataMask);
 					}
 					}
 					mIdx = -1;
 					mIdx = -1;
 				}
 				}

+ 1 - 1
BeefLibs/corlib/src/IO/FolderBrowserDialog.bf

@@ -145,7 +145,7 @@ namespace System.IO
                     if (sCurrentThis.mSelectedPath.Length != 0) 
                     if (sCurrentThis.mSelectedPath.Length != 0) 
                     {
                     {
                         // Try to select the folder specified by selectedPath
                         // Try to select the folder specified by selectedPath
-                        Windows.SendMessageW(hWnd, Windows.BFFM_SETSELECTIONA, 1, (int)sCurrentThis.mSelectedPath.ToScopedNativeWChar!());
+                        Windows.SendMessageW(hWnd, Windows.BFFM_SETSELECTIONA, 1, (int)(void*)sCurrentThis.mSelectedPath.ToScopedNativeWChar!());
                     }
                     }
                     break;
                     break;
                 case Windows.BFFM_SELCHANGED: 
                 case Windows.BFFM_SELCHANGED: 

+ 1 - 1
BeefLibs/corlib/src/IO/OpenFileDialog.bf

@@ -438,7 +438,7 @@ namespace System.IO
 			{
 			{
 				using (sMonitor.Enter())
 				using (sMonitor.Enter())
 				{
 				{
-					var ofn = (Windows.OpenFileName*)lparam;
+					var ofn = (Windows.OpenFileName*)(void*)lparam;
 					sHookMap[(int)hWnd] = (CommonDialog)Internal.UnsafeCastToObject((void*)ofn.mCustData);
 					sHookMap[(int)hWnd] = (CommonDialog)Internal.UnsafeCastToObject((void*)ofn.mCustData);
 				}
 				}
 			}
 			}

+ 2 - 2
BeefLibs/corlib/src/Object.bf

@@ -45,7 +45,7 @@ namespace System
         {
         {
             Type type;
             Type type;
 #if BF_ENABLE_OBJECT_DEBUG_FLAGS
 #if BF_ENABLE_OBJECT_DEBUG_FLAGS
-            ClassVData* maskedVData = (ClassVData*)(mClassVData & ~(int)0xFF);
+            ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
             type = maskedVData.mType;
             type = maskedVData.mType;
 #else
 #else
             type = mClassVData.mType;
             type = mClassVData.mType;
@@ -63,7 +63,7 @@ namespace System
         {
         {
             Type type;
             Type type;
 #if BF_ENABLE_OBJECT_DEBUG_FLAGS
 #if BF_ENABLE_OBJECT_DEBUG_FLAGS
-            ClassVData* maskedVData = (ClassVData*)(mClassVData & ~(int)0xFF);
+            ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF);
             type = maskedVData.mType;
             type = maskedVData.mType;
 #else            
 #else            
             type = mClassVData.mType;
             type = mClassVData.mType;

+ 1 - 1
BeefLibs/corlib/src/Pointer.bf

@@ -23,7 +23,7 @@ namespace System
 
 
 		public int GetHashCode()
 		public int GetHashCode()
 		{
 		{
-			return (int)mVal;
+			return (int)(void*)mVal;
 		}
 		}
 	}
 	}
 }
 }

+ 1 - 1
BeefTools/BeefPerf/src/BPClient.bf

@@ -1566,7 +1566,7 @@ namespace BeefPerf
 					uint32 tickMSNow = (.)ReadSLEB128();
 					uint32 tickMSNow = (.)ReadSLEB128();
 					int64 clockRate = (.)ReadSLEB128();
 					int64 clockRate = (.)ReadSLEB128();
 
 
-					mTicksToUSScale = 1000.0 / clockRate;
+					mTicksToUSScale = 1000000.0 / clockRate;
 
 
 					/*if (mFirstTimeStamp == -1)
 					/*if (mFirstTimeStamp == -1)
 					{
 					{

+ 39 - 4
BeefySysLib/platform/win/Platform.cpp

@@ -909,8 +909,25 @@ static void __cdecl AbortHandler(int)
 	BfpSystem_FatalError("Abort handler", NULL);
 	BfpSystem_FatalError("Abort handler", NULL);
 }
 }
 
 
+static int64 gCPUFreq = -1;
+static int64 gStartCPUTick = -1;
+static int64 gStartQPF = -1;
+
+static void InitCPUFreq()
+{
+	if (gStartCPUTick == -1)
+	{		
+		gStartCPUTick = __rdtsc();
+		LARGE_INTEGER largeVal = { 0 };
+		QueryPerformanceCounter(&largeVal);
+		gStartQPF = largeVal.QuadPart;
+	}
+}
+
 BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flags)
 BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flags)
 {	
 {	
+	InitCPUFreq();
+
 	::_set_error_mode(_OUT_TO_STDERR);
 	::_set_error_mode(_OUT_TO_STDERR);
 
 
 #ifdef _DEBUG
 #ifdef _DEBUG
@@ -1123,10 +1140,28 @@ BFP_EXPORT int64 BFP_CALLTYPE BfpSystem_GetCPUTick()
 }
 }
 
 
 BFP_EXPORT int64 BFP_CALLTYPE BfpSystem_GetCPUTickFreq()
 BFP_EXPORT int64 BFP_CALLTYPE BfpSystem_GetCPUTickFreq()
-{
-	LARGE_INTEGER freq = { 0 };
-	QueryPerformanceFrequency(&freq);
-	return freq.QuadPart;
+{	
+	LARGE_INTEGER largeVal = { 0 };
+	QueryPerformanceFrequency(&largeVal);
+	int64 qpfFreq = largeVal.QuadPart;
+	
+	if (gStartCPUTick == -1)
+	{
+		InitCPUFreq();
+		Sleep(10);
+	}
+
+	int64 cpuTick1 = __rdtsc();
+	QueryPerformanceCounter(&largeVal);
+	int64 slowTick1 = largeVal.QuadPart;
+
+	int64 cpuElapsed = cpuTick1 - gStartCPUTick;
+	int64 slowElapsed = slowTick1 - gStartQPF;
+	double elapsedSeconds = slowElapsed / (double)qpfFreq;
+	int64 freq = (int64)(cpuElapsed / elapsedSeconds);
+	gCPUFreq = freq;
+
+	return gCPUFreq;
 }
 }
 
 
 BFP_EXPORT void BFP_CALLTYPE BfpSystem_CreateGUID(BfpGUID* outGuid)
 BFP_EXPORT void BFP_CALLTYPE BfpSystem_CreateGUID(BfpGUID* outGuid)

+ 2 - 2
BeefySysLib/util/Array.h

@@ -639,7 +639,7 @@ public:
 		this->mSize++;
 		this->mSize++;
 	}
 	}
 
 
-	void Insert(intptr idx, T* vals, intptr size)
+	void Insert(intptr idx, const T* vals, intptr size)
 	{
 	{
 		BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
 		BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
 		if (this->mSize + size > this->mAllocSize)
 		if (this->mSize + size > this->mAllocSize)
@@ -934,7 +934,7 @@ public:
 		this->mSize++;
 		this->mSize++;
 	}
 	}
 
 
-	void Insert(intptr idx, T* vals, intptr size)
+	void Insert(intptr idx, const T* vals, intptr size)
 	{
 	{
 		BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
 		BF_ASSERT((uintptr)idx <= (uintptr)this->mSize);
 		if (this->mSize + size > this->mAllocSize)
 		if (this->mSize + size > this->mAllocSize)

+ 1 - 1
BeefySysLib/util/BeefPerf.cpp

@@ -355,7 +355,7 @@ static int64 GetTimestamp()
 #ifdef BF_PLATFORM_WINDOWS
 #ifdef BF_PLATFORM_WINDOWS
 	return __rdtsc() / 100;
 	return __rdtsc() / 100;
 #else
 #else
-	return BfpSystem_GetCPUTick();
+	return BfpSystem_GetCPUTick() / 100;
 #endif
 #endif
 }
 }
 
 

+ 17 - 2
BeefySysLib/util/BumpAllocator.h

@@ -186,7 +186,7 @@ public:
 		return mPrevSizes + (int)((uint8*)ptr - mCurAlloc);
 		return mPrevSizes + (int)((uint8*)ptr - mCurAlloc);
 	}
 	}
 
 
-	uint8* AllocBytes(int wantSize, int alignSize, const char* dbgName = "AllocBytes")
+	uint8* AllocBytes(intptr wantSize, int alignSize, const char* dbgName = "AllocBytes")
 	{
 	{
 		mCurPtr = (uint8*)(((intptr)mCurPtr + alignSize - 1) & ~(alignSize - 1));
 		mCurPtr = (uint8*)(((intptr)mCurPtr + alignSize - 1) & ~(alignSize - 1));
 
 
@@ -194,7 +194,7 @@ public:
 		return retVal;
 		return retVal;
 	}
 	}
 
 
-	uint8* AllocBytes(int wantSize, const char* dbgName = "AllocBytes")
+	uint8* AllocBytes(intptr wantSize, const char* dbgName = "AllocBytes")
 	{
 	{
 #ifdef BUMPALLOC_TRACKALLOCS		
 #ifdef BUMPALLOC_TRACKALLOCS		
 		BumpAllocTrackedEntry* allocSizePtr;
 		BumpAllocTrackedEntry* allocSizePtr;
@@ -237,6 +237,11 @@ class AllocatorBump
 public:
 public:
 	BumpAllocator* mAlloc;
 	BumpAllocator* mAlloc;
 
 
+	AllocatorBump()
+	{
+		mAlloc = NULL;
+	}
+
 	T* allocate(intptr count)
 	T* allocate(intptr count)
 	{
 	{
 		return (T*)mAlloc->AllocBytes((int)(sizeof(T) * count), alignof(T));
 		return (T*)mAlloc->AllocBytes((int)(sizeof(T) * count), alignof(T));
@@ -245,6 +250,16 @@ public:
 	void deallocate(T* ptr)
 	void deallocate(T* ptr)
 	{		
 	{		
 	}
 	}
+
+	void* rawAllocate(intptr size)
+	{
+		return mAlloc->AllocBytes(size, 16);
+	}
+
+	void rawDeallocate(void* ptr)
+	{
+		
+	}
 };
 };
 
 
 
 

+ 36 - 0
BeefySysLib/util/ChunkedDataBuffer.cpp

@@ -107,6 +107,42 @@ void ChunkedDataBuffer::Write(uint8 byte)
 	mSize++;
 	mSize++;
 }
 }
 
 
+void ChunkedDataBuffer::Write_2(uint16 val)
+{
+	while (mWriteCurPtr + 2 > mWriteCurAlloc + ALLOC_SIZE)
+	{
+		Write((uint8*)&val, 2);
+		return;
+	}
+	*(uint16*)mWriteCurPtr = val;
+	mWriteCurPtr += 2;
+	mSize += 2;
+}
+
+void ChunkedDataBuffer::Write_3(uint32 val)
+{	
+	while (mWriteCurPtr + 3 > mWriteCurAlloc + ALLOC_SIZE)
+	{
+		Write((uint8*)&val, 3);
+		return;
+	}
+	*(uint32*)mWriteCurPtr = val;
+	mWriteCurPtr += 3;
+	mSize += 3;
+}
+
+void ChunkedDataBuffer::Write_4(uint32 val)
+{	
+	while (mWriteCurPtr + 4 > mWriteCurAlloc + ALLOC_SIZE)
+	{
+		Write((uint8*)&val, 4);
+		return;
+	}
+	*(uint32*)mWriteCurPtr = val;
+	mWriteCurPtr += 4;
+	mSize += 4;
+}
+
 int ChunkedDataBuffer::GetReadPos()
 int ChunkedDataBuffer::GetReadPos()
 {
 {
 	return mReadPoolIdx * ALLOC_SIZE + (int)(mReadCurPtr - mReadCurAlloc);
 	return mReadPoolIdx * ALLOC_SIZE + (int)(mReadCurPtr - mReadCurAlloc);

+ 3 - 0
BeefySysLib/util/ChunkedDataBuffer.h

@@ -32,6 +32,9 @@ public:
 	void GrowPool();
 	void GrowPool();
 	void Write(const void* data, int size);
 	void Write(const void* data, int size);
 	void Write(uint8 byte);
 	void Write(uint8 byte);
+	void Write_2(uint16 val);
+	void Write_3(uint32 val);
+	void Write_4(uint32 val);
 	int GetReadPos();
 	int GetReadPos();
 	void SetReadPos(int pos);
 	void SetReadPos(int pos);
 	void NextReadPool();
 	void NextReadPool();

+ 16 - 16
BeefySysLib/util/HashSet.h

@@ -1,12 +1,12 @@
 #pragma once
 #pragma once
 
 
-#include "../Common.h"
+#include "Array.h"
 #include <unordered_map>
 #include <unordered_map>
 
 
 NS_BF_BEGIN;
 NS_BF_BEGIN;
 
 
-template <typename TKey>
-class HashSet
+template <typename TKey, typename TAlloc = AllocatorCLib<TKey> >
+class HashSet : public TAlloc
 {
 {
 public:
 public:
 	typedef int int_cosize;
 	typedef int int_cosize;
@@ -254,14 +254,14 @@ private:
 		Resize(ExpandSize(mCount), false);
 		Resize(ExpandSize(mCount), false);
 	}
 	}
 
 
-	void Resize(int newSize, bool forceNewHashCodes)
+	void Resize(intptr newSize, bool forceNewHashCodes)
 	{
 	{
 		BF_ASSERT(newSize >= mAllocSize);
 		BF_ASSERT(newSize >= mAllocSize);
-		int_cosize* newBuckets = new int_cosize[newSize];
+		int_cosize* newBuckets = (int_cosize*)rawAllocate(sizeof(int_cosize) * newSize);
 		for (int_cosize i = 0; i < newSize; i++)
 		for (int_cosize i = 0; i < newSize; i++)
 			newBuckets[i] = -1;
 			newBuckets[i] = -1;
-		Entry* newEntries = new Entry[newSize];
-		//mEntries.CopyTo(newEntries, 0, 0, mCount);
+		Entry* newEntries = (Entry*)rawAllocate(sizeof(Entry)*newSize);
+		
 		for (int i = 0; i < mCount; i++)
 		for (int i = 0; i < mCount; i++)
 		{
 		{
 			auto& newEntry = newEntries[i];
 			auto& newEntry = newEntries[i];
@@ -294,12 +294,12 @@ private:
 			}
 			}
 		}
 		}
 
 
-		delete[] mBuckets;
-		delete[] mEntries;
+		rawDeallocate(mBuckets);
+		rawDeallocate(mEntries);
 
 
 		mBuckets = newBuckets;
 		mBuckets = newBuckets;
 		mEntries = newEntries;
 		mEntries = newEntries;
-		mAllocSize = newSize;
+		mAllocSize = (int_cosize)newSize;
 	}
 	}
 
 
 	int FindEntry(const TKey& key)
 	int FindEntry(const TKey& key)
@@ -332,10 +332,10 @@ private:
 	void Initialize(intptr capacity)
 	void Initialize(intptr capacity)
 	{
 	{
 		int_cosize size = GetPrimeish((int_cosize)capacity);
 		int_cosize size = GetPrimeish((int_cosize)capacity);
-		mBuckets = new int_cosize[size];
+		mBuckets = (int_cosize*)rawAllocate(sizeof(int_cosize) * size);
 		mAllocSize = size;
 		mAllocSize = size;
 		for (int_cosize i = 0; i < (int_cosize)mAllocSize; i++) mBuckets[i] = -1;
 		for (int_cosize i = 0; i < (int_cosize)mAllocSize; i++) mBuckets[i] = -1;
-		mEntries = new Entry[size];
+		mEntries = (Entry*)rawAllocate(sizeof(Entry) * size);
 		mFreeList = -1;
 		mFreeList = -1;
 	}
 	}
 
 
@@ -431,8 +431,8 @@ public:
 		}
 		}
 		else
 		else
 		{
 		{
-			mBuckets = new int_cosize[mAllocSize];
-			mEntries = new Entry[mAllocSize];
+			mBuckets = (int_cosize*)rawAllocate(sizeof(int_cosize) * mAllocSize);
+			mEntries = (Entry*)rawAllocate(sizeof(Entry) * mAllocSize);
 
 
 			for (int_cosize i = 0; i < mAllocSize; i++)
 			for (int_cosize i = 0; i < mAllocSize; i++)
 				mBuckets[i] = val.mBuckets[i];
 				mBuckets[i] = val.mBuckets[i];
@@ -476,8 +476,8 @@ public:
 			}
 			}
 		}
 		}
 
 
-		delete[] mBuckets;
-		delete[] mEntries;
+		rawDeallocate(mBuckets);
+		rawDeallocate(mEntries);
 	}
 	}
 
 
 	HashSet& operator=(const HashSet& rhs)
 	HashSet& operator=(const HashSet& rhs)

+ 22 - 7
BeefySysLib/util/SizedArray.h

@@ -217,7 +217,7 @@ public:
 		BF_ASSERT((uintptr)idx < (uintptr)this->mSize);
 		BF_ASSERT((uintptr)idx < (uintptr)this->mSize);
 		return this->mVals[idx];
 		return this->mVals[idx];
 	}
 	}
-
+	
 	bool operator==(const SizedArrayBase& arrB) const
 	bool operator==(const SizedArrayBase& arrB) const
 	{
 	{
 		if (this->mSize != arrB.mSize)
 		if (this->mSize != arrB.mSize)
@@ -288,6 +288,11 @@ public:
 		this->mSize = 0;
 		this->mSize = 0;
 	}
 	}
 
 
+	void Clear()
+	{
+		this->mSize = 0;
+	}
+
 	/*void Free()
 	/*void Free()
 	{
 	{
 	if (this->mVals != NULL)
 	if (this->mVals != NULL)
@@ -1060,17 +1065,27 @@ public:
 	}
 	}
 };
 };
 
 
+template <typename T>
+static bool operator==(const ArrayBase<T>& arrA, const SizedArrayBase<T>& arrB)
+{
+	if (arrA.mSize != arrB.mSize)
+		return false;
+	for (intptr i = 0; i < arrA.mSize; i++)
+		if (arrA.mVals[i] != arrB.mVals[i])
+			return false;
+	return true;
+}
+
 NS_BF_END;
 NS_BF_END;
 
 
-/*namespace std
+namespace std
 {
 {
 	template<typename T>
 	template<typename T>
-	struct hash<Beefy::Array<T> >
+	struct hash<Beefy::SizedArrayImpl<T> >
 	{
 	{
-		size_t operator()(const Beefy::Array<T>& val) const
+		size_t operator()(const Beefy::SizedArrayImpl<T>& val) const
 		{
 		{
-			return _Hash_seq((const uint8*)val.mVals, sizeof(T) * val.mSize);
+			return HashBytes((const uint8*)val.mVals, sizeof(T) * val.mSize);
 		}
 		}
 	};
 	};
-}*/
-
+}

+ 19 - 15
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -993,6 +993,8 @@ bool BfMethodMatcher::WantsCheckMethod(BfProtectionCheckFlags& flags, BfTypeInst
 
 
 bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* checkMethod, bool isFailurePass)
 bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* checkMethod, bool isFailurePass)
 {
 {
+	BP_ZONE("BfMethodMatcher::CheckMethod");
+
 	bool hadMatch = false;
 	bool hadMatch = false;
 
 
 	// Never consider overrides - they only get found at original method declaration
 	// Never consider overrides - they only get found at original method declaration
@@ -2905,7 +2907,9 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfIdentifierNode* identifierNode,
 		return qualifiedResult;
 		return qualifiedResult;
 	}	
 	}	
 
 
-	return LookupIdentifier(identifierNode, identifierNode->ToString(), ignoreInitialError, hadError);		
+	StringT<128> identifierStr;
+	identifierNode->ToString(identifierStr);
+	return LookupIdentifier(identifierNode, identifierStr, ignoreInitialError, hadError);		
 }
 }
 
 
 void BfExprEvaluator::Visit(BfIdentifierNode* identifierNode)
 void BfExprEvaluator::Visit(BfIdentifierNode* identifierNode)
@@ -3148,7 +3152,7 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
 
 
 				if (resolvedFieldType->IsValuelessType())
 				if (resolvedFieldType->IsValuelessType())
 				{
 				{
-					return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), resolvedFieldType, true);
+					return BfTypedValue(BfIRValue::sValueless, resolvedFieldType, true);
 				}
 				}
 
 
 				if (isConst)
 				if (isConst)
@@ -7285,8 +7289,7 @@ void BfExprEvaluator::LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode*
 void BfExprEvaluator::LookupQualifiedStaticField(BfQualifiedNameNode* nameNode, bool ignoreIdentifierNotFoundError)
 void BfExprEvaluator::LookupQualifiedStaticField(BfQualifiedNameNode* nameNode, bool ignoreIdentifierNotFoundError)
 {
 {
 	// Lookup left side as a type
 	// Lookup left side as a type
-	{
-		SetAndRestoreValue<bool> prevHadIgnoreError(mModule->mHadIgnoredError, false);
+	{		
  		BfType* type = NULL;
  		BfType* type = NULL;
 		{
 		{
 			type = mModule->ResolveTypeRef(nameNode->mLeft, NULL, BfPopulateType_Data, BfResolveTypeRefFlag_AllowRef);
 			type = mModule->ResolveTypeRef(nameNode->mLeft, NULL, BfPopulateType_Data, BfResolveTypeRefFlag_AllowRef);
@@ -7371,8 +7374,7 @@ void BfExprEvaluator::LookupQualifiedStaticField(BfQualifiedNameNode* nameNode,
 void BfExprEvaluator::LookupQualifiedStaticField(BfAstNode* nameNode, BfIdentifierNode* nameLeft, BfIdentifierNode* nameRight, bool ignoreIdentifierNotFoundError)
 void BfExprEvaluator::LookupQualifiedStaticField(BfAstNode* nameNode, BfIdentifierNode* nameLeft, BfIdentifierNode* nameRight, bool ignoreIdentifierNotFoundError)
 {
 {
 	// Lookup left side as a type
 	// Lookup left side as a type
-	{
-		SetAndRestoreValue<bool> prevHadIgnoreError(mModule->mHadIgnoredError, false);
+	{		
 		BfType* type = NULL;
 		BfType* type = NULL;
 		{
 		{
 			SetAndRestoreValue<bool> prevIgnoreErrors(mModule->mIgnoreErrors, true);
 			SetAndRestoreValue<bool> prevIgnoreErrors(mModule->mIgnoreErrors, true);
@@ -8349,6 +8351,7 @@ bool BfExprEvaluator::CanBindDelegate(BfDelegateBindExpression* delegateBindExpr
 	for (int i = 0; i < (int) methodInstance->GetParamCount(); i++)
 	for (int i = 0; i < (int) methodInstance->GetParamCount(); i++)
 	{
 	{
 		auto typedValueExpr = &typedValueExprs[i];
 		auto typedValueExpr = &typedValueExprs[i];
+		typedValueExpr->mTypedValue.mValue = BfIRValue(BfIRValueFlags_Value, -1);
 		typedValueExpr->mTypedValue.mType = methodInstance->GetParamType(i);
 		typedValueExpr->mTypedValue.mType = methodInstance->GetParamType(i);
 		typedValueExpr->mRefNode = NULL;
 		typedValueExpr->mRefNode = NULL;
 		args[i] = typedValueExpr;
 		args[i] = typedValueExpr;
@@ -8734,6 +8737,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
 	for (int i = 0; i < (int)methodInstance->GetParamCount(); i++)
 	for (int i = 0; i < (int)methodInstance->GetParamCount(); i++)
 	{
 	{
 		auto typedValueExpr = &typedValueExprs[i];
 		auto typedValueExpr = &typedValueExprs[i];
+		typedValueExpr->mTypedValue.mValue = BfIRValue(BfIRValueFlags_Value, -1);
 		typedValueExpr->mTypedValue.mType = methodInstance->GetParamType(i);
 		typedValueExpr->mTypedValue.mType = methodInstance->GetParamType(i);
 		typedValueExpr->mRefNode = NULL;
 		typedValueExpr->mRefNode = NULL;
 		args[i] = typedValueExpr;
 		args[i] = typedValueExpr;
@@ -13160,13 +13164,13 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
 	if (mayBeSkipCall)
 	if (mayBeSkipCall)
 		resolveArgsFlags = (BfResolveArgFlags)(resolveArgsFlags | BfResolveArgFlag_DeferParamValues);
 		resolveArgsFlags = (BfResolveArgFlags)(resolveArgsFlags | BfResolveArgFlag_DeferParamValues);
 
 
-// 	static int sCallIdx = 0;
-// 	sCallIdx++;
-// 	int callIdx = sCallIdx;
-// 	if (callIdx == 1557)
-// 	{
-// 		NOP;
-// 	}
+	static int sCallIdx = 0;
+	sCallIdx++;
+	int callIdx = sCallIdx;
+	if (callIdx == 1557)
+	{
+		NOP;
+	}
 	
 	
 	BfCheckedKind checkedKind = BfCheckedKind_NotSet;
 	BfCheckedKind checkedKind = BfCheckedKind_NotSet;
 	if (attributeState.mCustomAttributes != NULL)
 	if (attributeState.mCustomAttributes != NULL)
@@ -17208,8 +17212,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
 
 
 			BfPointerType* resultPointerType = (BfPointerType*)resultType;
 			BfPointerType* resultPointerType = (BfPointerType*)resultType;
 			BfType* intPtrType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
 			BfType* intPtrType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
-			convLeftValue = mModule->CastToValue(leftExpression, leftValue, intPtrType, BfCastFlags_Explicit);
-			convRightValue = mModule->CastToValue(rightExpression, rightValue, intPtrType, BfCastFlags_Explicit);
+			convLeftValue = mModule->CastToValue(leftExpression, leftValue, intPtrType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_FromCompiler));
+			convRightValue = mModule->CastToValue(rightExpression, rightValue, intPtrType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_FromCompiler));
 			BfIRValue diffValue = mModule->mBfIRBuilder->CreateSub(convLeftValue, convRightValue);
 			BfIRValue diffValue = mModule->mBfIRBuilder->CreateSub(convLeftValue, convRightValue);
 			diffValue = mModule->mBfIRBuilder->CreateDiv(diffValue, mModule->GetConstValue(resultPointerType->mElementType->mSize, intPtrType), true);
 			diffValue = mModule->mBfIRBuilder->CreateDiv(diffValue, mModule->GetConstValue(resultPointerType->mElementType->mSize, intPtrType), true);
 			mResult = BfTypedValue(diffValue, intPtrType);
 			mResult = BfTypedValue(diffValue, intPtrType);

+ 101 - 7
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -215,6 +215,8 @@ static llvm::GlobalValue::LinkageTypes LLVMMapLinkageType(BfIRLinkageType linkag
 	return llvmLinkageType;
 	return llvmLinkageType;
 }
 }
 
 
+BfIRValue BfIRValue::sValueless(BfIRValueFlags_Value, -1);
+
 bool BfIRValue::IsFake() const
 bool BfIRValue::IsFake() const
 {
 {
 	return mId < -1;
 	return mId < -1;
@@ -1452,6 +1454,98 @@ void BfIRBuilder::WriteSLEB128(int64 value)
 	while (hasMore);        
 	while (hasMore);        
 }
 }
 
 
+void BfIRBuilder::WriteSLEB128(int32 value)
+{
+	if (value < 0)
+	{
+// 		if (value >= -0x40)
+// 		{
+// 			mStream.Write((uint8)value);
+// 			return;
+// 		}
+// 
+// 		if (value >= -0x2000)
+// 		{
+// 			uint16 val =
+// 				(((uint16)(value << 1)) & 0x7F00) |
+// 				(((uint16)value) & 0x7F) | 0x80;
+// 			mStream.Write_2(val);
+// 			return;
+// 		}
+// 
+// 		if (value >= -0x100000)
+// 		{
+// 			uint32 val =
+// 				(((uint32)(value << 2)) & 0x7F0000) |
+// 				(((uint32)(value << 1)) & 0x7F00) |
+// 				(((uint32)value) & 0x7F) | 0x8080;
+// 			mStream.Write_3(val);
+// 			return;
+// 		}
+// 
+// 		if (value >= -0x8000000)
+// 		{
+// 			uint32 val =
+// 				(((uint32)(value << 3)) & 0x7F000000) |
+// 				(((uint32)(value << 2)) & 0x7F0000) |
+// 				(((uint32)(value << 1)) & 0x7F00) |
+// 				(((uint32)value) & 0x7F) | 0x808080;
+// 			mStream.Write_4(val);
+// 			return;
+// 		}
+	}
+	else
+	{
+		if (value <= 0x3F)
+		{
+			mStream.Write((uint8)value);
+			return;
+		}
+
+		if (value <= 0x1FFF)
+		{
+			uint16 val =
+				(((uint16)(value << 1)) & 0x7F00) |
+				(((uint16)value) & 0x7F) | 0x80;
+			mStream.Write_2(val);
+			return;
+		}
+// 
+// 		if (value <= 0x0FFFFF)
+// 		{
+// 			uint32 val =
+// 				(((uint32)(value << 2)) & 0x7F0000) |
+// 				(((uint32)(value << 1)) & 0x7F00) |
+// 				(((uint32)value) & 0x7F) | 0x8080;
+// 			mStream.Write_3(val);
+// 			return;
+// 		}
+// 
+// 		if (value <= 0x7FFFFF)
+// 		{
+// 			uint32 val =
+// 				(((uint32)(value << 3)) & 0x7F000000) |
+// 				(((uint32)(value << 2)) & 0x7F0000) |
+// 				(((uint32)(value << 1)) & 0x7F00) |
+// 				(((uint32)value) & 0x7F) | 0x808080;
+// 			mStream.Write_4(val);
+// 			return;
+// 		}
+	}
+
+	bool hasMore;
+	do
+	{
+		uint8 curByte = (uint8)(value & 0x7f);
+		value >>= 7;
+		hasMore = !((((value == 0) && ((curByte & 0x40) == 0)) ||
+			((value == -1) && ((curByte & 0x40) != 0))));
+		if (hasMore)
+			curByte |= 0x80;
+		mStream.Write(curByte);
+	} while (hasMore);
+}
+
 void BfIRBuilder::Write(uint8 val)
 void BfIRBuilder::Write(uint8 val)
 {
 {
 	mStream.Write(val);	
 	mStream.Write(val);	
@@ -4550,21 +4644,21 @@ BfIRMDNode BfIRBuilder::DbgCreateImportedModule(BfIRMDNode context, BfIRMDNode n
 
 
 BfIRMDNode BfIRBuilder::DbgCreateBasicType(const StringImpl& name, int64 sizeInBits, int64 alignInBits, int encoding)
 BfIRMDNode BfIRBuilder::DbgCreateBasicType(const StringImpl& name, int64 sizeInBits, int64 alignInBits, int encoding)
 {
 {
-	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateBasicType, name, sizeInBits, alignInBits, encoding);
+	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateBasicType, name, (int32)sizeInBits, (int32)alignInBits, encoding);
 	NEW_CMD_INSERTED_IRMD;
 	NEW_CMD_INSERTED_IRMD;
 	return retVal;
 	return retVal;
 }
 }
 
 
 BfIRMDNode BfIRBuilder::DbgCreateStructType(BfIRMDNode context, const StringImpl& name, BfIRMDNode file, int lineNum, int64 sizeInBits, int64 alignInBits, int flags, BfIRMDNode derivedFrom, const BfSizedArray<BfIRMDNode>& elements)
 BfIRMDNode BfIRBuilder::DbgCreateStructType(BfIRMDNode context, const StringImpl& name, BfIRMDNode file, int lineNum, int64 sizeInBits, int64 alignInBits, int flags, BfIRMDNode derivedFrom, const BfSizedArray<BfIRMDNode>& elements)
 {	
 {	
-	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateStructType, context, name, file, lineNum, sizeInBits, alignInBits, flags, derivedFrom, elements);
+	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateStructType, context, name, file, lineNum, (int32)sizeInBits, (int32)alignInBits, flags, derivedFrom, elements);
 	NEW_CMD_INSERTED_IRMD;
 	NEW_CMD_INSERTED_IRMD;
 	return retVal;
 	return retVal;
 }
 }
 
 
 BfIRMDNode BfIRBuilder::DbgCreateEnumerationType(BfIRMDNode scope, const StringImpl& name, BfIRMDNode file, int lineNumber, int64 sizeInBits, int64 alignInBits, const BfSizedArray<BfIRMDNode>& elements, BfIRMDNode underlyingType)
 BfIRMDNode BfIRBuilder::DbgCreateEnumerationType(BfIRMDNode scope, const StringImpl& name, BfIRMDNode file, int lineNumber, int64 sizeInBits, int64 alignInBits, const BfSizedArray<BfIRMDNode>& elements, BfIRMDNode underlyingType)
 {
 {
-	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateEnumerationType, scope, name, file, lineNumber, sizeInBits, alignInBits, elements, underlyingType);
+	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateEnumerationType, scope, name, file, lineNumber, (int32)sizeInBits, (int32)alignInBits, elements, underlyingType);
 	NEW_CMD_INSERTED_IRMD;
 	NEW_CMD_INSERTED_IRMD;
 	return retVal;
 	return retVal;
 }
 }
@@ -4606,7 +4700,7 @@ BfIRMDNode BfIRBuilder::DbgCreateArrayType(int64 sizeInBits, int64 alignInBits,
 
 
 BfIRMDNode BfIRBuilder::DbgCreateReplaceableCompositeType(int tag, const StringImpl& name, BfIRMDNode scope, BfIRMDNode file, int line, int64 sizeInBits, int64 alignInBits, int flags)
 BfIRMDNode BfIRBuilder::DbgCreateReplaceableCompositeType(int tag, const StringImpl& name, BfIRMDNode scope, BfIRMDNode file, int line, int64 sizeInBits, int64 alignInBits, int flags)
 {	
 {	
-	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateReplaceableCompositeType, tag, name, scope, file, line, sizeInBits, alignInBits, flags);
+	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateReplaceableCompositeType, tag, name, scope, file, line, (int32)sizeInBits, (int32)alignInBits, flags);
 	NEW_CMD_INSERTED_IRMD;
 	NEW_CMD_INSERTED_IRMD;
 	return retVal;
 	return retVal;
 }
 }
@@ -4627,7 +4721,7 @@ BfIRMDNode BfIRBuilder::DbgCreateForwardDecl(int tag, const StringImpl& name, Bf
 
 
 BfIRMDNode BfIRBuilder::DbgCreateSizedForwardDecl(int tag, const StringImpl& name, BfIRMDNode scope, BfIRMDNode file, int line, int64 sizeInBits, int64 alignInBits)
 BfIRMDNode BfIRBuilder::DbgCreateSizedForwardDecl(int tag, const StringImpl& name, BfIRMDNode scope, BfIRMDNode file, int line, int64 sizeInBits, int64 alignInBits)
 {
 {
-	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateSizedForwardDecl, tag, name, scope, file, line, sizeInBits, alignInBits);
+	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateSizedForwardDecl, tag, name, scope, file, line, (int32)sizeInBits, (int32)alignInBits);
 	NEW_CMD_INSERTED_IRMD;
 	NEW_CMD_INSERTED_IRMD;
 	return retVal;
 	return retVal;
 }
 }
@@ -4661,7 +4755,7 @@ BfIRMDNode BfIRBuilder::DbgCreateEnumerator(const StringImpl& name, int64 val)
 
 
 BfIRMDNode BfIRBuilder::DbgCreateMemberType(BfIRMDNode scope, const StringImpl& name, BfIRMDNode file, int lineNumber, int64 sizeInBits, int64 alignInBits, int64 offsetInBits, int flags, BfIRMDNode type)
 BfIRMDNode BfIRBuilder::DbgCreateMemberType(BfIRMDNode scope, const StringImpl& name, BfIRMDNode file, int lineNumber, int64 sizeInBits, int64 alignInBits, int64 offsetInBits, int flags, BfIRMDNode type)
 {
 {
-	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateMemberType, scope, name, file, lineNumber, sizeInBits, alignInBits, offsetInBits, flags, type);
+	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateMemberType, scope, name, file, lineNumber, (int32)sizeInBits, (int32)alignInBits, (int32)offsetInBits, flags, type);
 	NEW_CMD_INSERTED_IRMD;
 	NEW_CMD_INSERTED_IRMD;
 	return retVal;
 	return retVal;
 }
 }
@@ -4675,7 +4769,7 @@ BfIRMDNode BfIRBuilder::DbgCreateStaticMemberType(BfIRMDNode scope, const String
 
 
 BfIRMDNode BfIRBuilder::DbgCreateInheritance(BfIRMDNode type, BfIRMDNode baseType, int64 baseOffset, int flags)
 BfIRMDNode BfIRBuilder::DbgCreateInheritance(BfIRMDNode type, BfIRMDNode baseType, int64 baseOffset, int flags)
 {
 {
-	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateInheritance, type, baseType, baseOffset, flags);
+	BfIRMDNode retVal = WriteCmd(BfIRCmd_DbgCreateInheritance, type, baseType, (int32)baseOffset, flags);
 	NEW_CMD_INSERTED_IRMD;
 	NEW_CMD_INSERTED_IRMD;
 	return retVal;
 	return retVal;
 }
 }

+ 3 - 1
IDEHelper/Compiler/BfIRBuilder.h

@@ -473,6 +473,7 @@ public:
 public:	
 public:	
 	int mId;
 	int mId;
 	BfIRValueFlags mFlags;
 	BfIRValueFlags mFlags;
+	static BfIRValue sValueless;
 
 
 #ifdef CHECK_CONSTHOLDER
 #ifdef CHECK_CONSTHOLDER
 	BfIRConstHolder* mHolder;
 	BfIRConstHolder* mHolder;
@@ -883,7 +884,8 @@ public:
 public:
 public:
 	~BfIRBuilder();
 	~BfIRBuilder();
 	
 	
-	void WriteSLEB128(int64 val);	
+	void WriteSLEB128(int64 val);
+	void WriteSLEB128(int32 val);
 	void Write(uint8 val);
 	void Write(uint8 val);
 	void Write(bool val);
 	void Write(bool val);
 	void Write(int val);
 	void Write(int val);

+ 5 - 5
IDEHelper/Compiler/BfMangler.cpp

@@ -304,7 +304,7 @@ void BfGNUMangler::MangleTypeInst(MangleContext& mangleContext, StringImpl& name
 			name += "N8delegateI";
 			name += "N8delegateI";
 		else
 		else
 			name += "N8functionI";
 			name += "N8functionI";
-		BfTypeVector typeVec;
+		SizedArray<BfType*, 8> typeVec;
 		typeVec.push_back(invokeMethodInst->mReturnType);
 		typeVec.push_back(invokeMethodInst->mReturnType);
 		for (int paramIdx = 0; paramIdx < (int)invokeMethodInst->mParams.size(); paramIdx++)
 		for (int paramIdx = 0; paramIdx < (int)invokeMethodInst->mParams.size(); paramIdx++)
 		{
 		{
@@ -1095,7 +1095,7 @@ bool BfMSMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl&
 		{
 		{
 			auto tupleType = (BfTupleType*)newNameSub.mType;			
 			auto tupleType = (BfTupleType*)newNameSub.mType;			
 			name += "?$__TUPLE";
 			name += "?$__TUPLE";
-			BfTypeVector typeVec;
+			SizedArray<BfType*, 8> typeVec;
 			for (auto& fieldInst : tupleType->mFieldInstances)
 			for (auto& fieldInst : tupleType->mFieldInstances)
 			{
 			{
 				BfFieldDef* fieldDef = fieldInst.GetFieldDef();
 				BfFieldDef* fieldDef = fieldInst.GetFieldDef();
@@ -1120,7 +1120,7 @@ bool BfMSMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl&
 				 	name += "?$delegate";
 				 	name += "?$delegate";
 				else
 				else
 				 	name += "?$function";
 				 	name += "?$function";
-				BfTypeVector typeVec;				
+				SizedArray<BfType*, 8> typeVec;
 				typeVec.push_back(BfNodeDynCast<BfDirectTypeReference>(methodDef->mReturnTypeRef)->mType);
 				typeVec.push_back(BfNodeDynCast<BfDirectTypeReference>(methodDef->mReturnTypeRef)->mType);
 				for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
 				for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
 				{								
 				{								
@@ -1139,7 +1139,7 @@ bool BfMSMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl&
 // 				name += "?$delegate";
 // 				name += "?$delegate";
 // 			else
 // 			else
 // 				name += "?$function";
 // 				name += "?$function";
-// 			BfTypeVector typeVec;
+// 			SizedArray<BfType*, 8> typeVec;
 // 			typeVec.push_back(invokeMethodInst->mReturnType);
 // 			typeVec.push_back(invokeMethodInst->mReturnType);
 // 			for (int paramIdx = 0; paramIdx < (int)invokeMethodInst->mParams.size(); paramIdx++)
 // 			for (int paramIdx = 0; paramIdx < (int)invokeMethodInst->mParams.size(); paramIdx++)
 // 			{								
 // 			{								
@@ -1156,7 +1156,7 @@ bool BfMSMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl&
 		{
 		{
 			auto boxedType = (BfBoxedType*)newNameSub.mTypeInst;
 			auto boxedType = (BfBoxedType*)newNameSub.mTypeInst;
 			name += "?$Box@";
 			name += "?$Box@";
-			BfTypeVector typeVec;			
+			SizedArray<BfType*, 8> typeVec;
 			typeVec.push_back(boxedType->GetModifiedElementType());			
 			typeVec.push_back(boxedType->GetModifiedElementType());			
 			AddGenericArgs(mangleContext, name, typeVec);
 			AddGenericArgs(mangleContext, name, typeVec);
 			name += '@';
 			name += '@';

+ 44 - 29
IDEHelper/Compiler/BfModule.cpp

@@ -803,8 +803,7 @@ BfModule::BfModule(BfContext* context, const StringImpl& moduleName)
 	mHadBuildError = false;
 	mHadBuildError = false;
 	mHadBuildWarning = false;
 	mHadBuildWarning = false;
 	mIgnoreErrors = false;
 	mIgnoreErrors = false;
-	mIgnoreWarnings = false;
-	mHadIgnoredError = false;
+	mIgnoreWarnings = false;	
 	mReportErrors = true;
 	mReportErrors = true;
 	mIsInsideAutoComplete = false;
 	mIsInsideAutoComplete = false;
 	mIsDeleting = false;
 	mIsDeleting = false;
@@ -1374,7 +1373,7 @@ BfTypedValue BfModule::GetFakeTypedValue(BfType* type)
 {
 {
 	// This is a conservative "IsValueless", since it's not an error to use a fakeVal even if we don't need one
 	// This is a conservative "IsValueless", since it's not an error to use a fakeVal even if we don't need one
 	if (type->mSize == 0)
 	if (type->mSize == 0)
-		return BfTypedValue(BfIRValue(), type);
+		return BfTypedValue(BfIRValue::sValueless, type);
 	else
 	else
 		return BfTypedValue(mBfIRBuilder->GetFakeVal(), type);
 		return BfTypedValue(mBfIRBuilder->GetFakeVal(), type);
 }
 }
@@ -2446,8 +2445,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
 	BP_ZONE("BfModule::Fail");
 	BP_ZONE("BfModule::Fail");
 
 
 	if (mIgnoreErrors)
 	if (mIgnoreErrors)
-	{
-		mHadIgnoredError = true;
+	{		
 	 	return NULL;
 	 	return NULL;
 	}
 	}
 
 
@@ -8320,6 +8318,9 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
 
 
 void BfModule::EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull)
 void BfModule::EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull)
 {
 {
+	if (mBfIRBuilder->mIgnoreWrites)
+		return;
+
 	bool emitDynamicCastCheck = mCompiler->mOptions.mEmitDynamicCastCheck;
 	bool emitDynamicCastCheck = mCompiler->mOptions.mEmitDynamicCastCheck;
 	auto typeOptions = GetTypeOptions();
 	auto typeOptions = GetTypeOptions();
 	if (typeOptions != NULL)
 	if (typeOptions != NULL)
@@ -8355,19 +8356,34 @@ void BfModule::EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool al
 
 
 BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType, const BfAllocTarget& allocTarget, bool callDtor)
 BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType, const BfAllocTarget& allocTarget, bool callDtor)
 {
 {
+	if (mBfIRBuilder->mIgnoreWrites)
+	{
+		if (toType == mContext->mBfObjectType)
+			return BfTypedValue(mBfIRBuilder->GetFakeVal(), toType);
+	}
+
 	BP_ZONE("BoxValue");
 	BP_ZONE("BoxValue");
 
 
 	BfTypeInstance* fromStructTypeInstance = typedVal.mType->ToTypeInstance();
 	BfTypeInstance* fromStructTypeInstance = typedVal.mType->ToTypeInstance();
 	if (typedVal.mType->IsNullable())
 	if (typedVal.mType->IsNullable())
-	{
+	{		
 		typedVal = MakeAddressable(typedVal);
 		typedVal = MakeAddressable(typedVal);
 
 
 		auto innerType = typedVal.mType->GetUnderlyingType();
 		auto innerType = typedVal.mType->GetUnderlyingType();
 		if (!innerType->IsValueType())
 		if (!innerType->IsValueType())
 		{
 		{
-			Fail("Only value types can be boxed", srcNode);
+			if (!mIgnoreErrors)
+				Fail("Only value types can be boxed", srcNode);
 			return BfTypedValue();
 			return BfTypedValue();
 		}
 		}
+		
+		auto boxedType = CreateBoxedType(innerType);
+		auto resultType = toType;
+		if (resultType == NULL)
+			resultType = boxedType;
+
+		if (mBfIRBuilder->mIgnoreWrites)
+			return BfTypedValue(mBfIRBuilder->GetFakeVal(), resultType);
 
 
 		auto prevBB = mBfIRBuilder->GetInsertBlock();
 		auto prevBB = mBfIRBuilder->GetInsertBlock();
 		auto boxBB = mBfIRBuilder->CreateBlock("boxedN.notNull");
 		auto boxBB = mBfIRBuilder->CreateBlock("boxedN.notNull");
@@ -8378,13 +8394,9 @@ BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 		auto hasValue = mBfIRBuilder->CreateLoad(hasValueAddr);
 		auto hasValue = mBfIRBuilder->CreateLoad(hasValueAddr);
 
 
 		mBfIRBuilder->CreateCondBr(hasValue, boxBB, endBB);
 		mBfIRBuilder->CreateCondBr(hasValue, boxBB, endBB);
-
-		auto boxedType = CreateBoxedType(innerType);
+		
 		AddDependency(boxedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
 		AddDependency(boxedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
-		auto resultType = toType;
-		if (resultType == NULL)
-			resultType = boxedType;
-
+		
 		mBfIRBuilder->AddBlock(boxBB);
 		mBfIRBuilder->AddBlock(boxBB);
 		mBfIRBuilder->SetInsertPoint(boxBB);
 		mBfIRBuilder->SetInsertPoint(boxBB);
 		BfScopeData newScope;
 		BfScopeData newScope;
@@ -8443,17 +8455,16 @@ BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 	if (fromStructTypeInstance == NULL)
 	if (fromStructTypeInstance == NULL)
 		return BfTypedValue();	
 		return BfTypedValue();	
 
 
-	// Need to box it
-	auto boxedType = CreateBoxedType(typedVal.mType);
-	bool isBoxedType = (fromStructTypeInstance != NULL) && (toType->IsBoxed()) && (boxedType == toType);
-
+	// Need to box it	
+	bool isBoxedType = (fromStructTypeInstance != NULL) && (toType->IsBoxed());
+	
 	if ((toType == NULL) || (toType == mContext->mBfObjectType) || (isBoxedType) || (alreadyCheckedCast) ||  (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance)))
 	if ((toType == NULL) || (toType == mContext->mBfObjectType) || (isBoxedType) || (alreadyCheckedCast) ||  (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance)))
-	{
-		if (typedVal.mType->IsPointer())
-		{
-			NOP;
-		}
-		
+	{	
+		if (mBfIRBuilder->mIgnoreWrites)
+			return BfTypedValue(mBfIRBuilder->GetFakeVal(), (toType != NULL) ? toType : CreateBoxedType(typedVal.mType));
+
+		auto boxedType = CreateBoxedType(typedVal.mType);
+
 		mBfIRBuilder->PopulateType(boxedType);
 		mBfIRBuilder->PopulateType(boxedType);
 		AddDependency(boxedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
 		AddDependency(boxedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
 		auto allocaInst = AllocFromType(boxedType, allocTarget, BfIRValue(), BfIRValue(), 0, callDtor ? BfAllocFlags_None : BfAllocFlags_NoDtorCall);
 		auto allocaInst = AllocFromType(boxedType, allocTarget, BfIRValue(), BfIRValue(), 0, callDtor ? BfAllocFlags_None : BfAllocFlags_NoDtorCall);
@@ -8463,7 +8474,7 @@ BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 		
 		
 		if (boxedType->IsUnspecializedType())
 		if (boxedType->IsUnspecializedType())
 		{
 		{
-			BF_ASSERT(mCurMethodInstance->mIsUnspecialized);
+			BF_ASSERT((srcNode == NULL) || (mCurMethodInstance->mIsUnspecialized));
 		}
 		}
 		else
 		else
 		{
 		{
@@ -8656,7 +8667,7 @@ int BfModule::GetGenericParamAndReturnCount(BfMethodInstance* methodInstance)
 	return genericCount;
 	return genericCount;
 }
 }
 
 
-BfModule* BfModule::GetSpecializedMethodModule(const Array<BfProject*>& projectList)
+BfModule* BfModule::GetSpecializedMethodModule(const SizedArrayImpl<BfProject*>& projectList)
 {
 {
 	BF_ASSERT(!mIsScratchModule);
 	BF_ASSERT(!mIsScratchModule);
 	BF_ASSERT(mIsReified);
 	BF_ASSERT(mIsReified);
@@ -8667,7 +8678,7 @@ BfModule* BfModule::GetSpecializedMethodModule(const Array<BfProject*>& projectL
 
 
 	BfModule* specModule = NULL;	
 	BfModule* specModule = NULL;	
 	BfModule** specModulePtr = NULL;
 	BfModule** specModulePtr = NULL;
-	if (mainModule->mSpecializedMethodModules.TryGetValue(projectList, &specModulePtr))
+	if (mainModule->mSpecializedMethodModules.TryGetValueWith(projectList, &specModulePtr))
 	{
 	{
 		return *specModulePtr;
 		return *specModulePtr;
 	}
 	}
@@ -8681,7 +8692,11 @@ BfModule* BfModule::GetSpecializedMethodModule(const Array<BfProject*>& projectL
 		specModule->mParentModule = mainModule;
 		specModule->mParentModule = mainModule;
 		specModule->mIsSpecializedMethodModuleRoot = true;
 		specModule->mIsSpecializedMethodModuleRoot = true;
 		specModule->Init();
 		specModule->Init();
-		mainModule->mSpecializedMethodModules[projectList] = specModule;			
+
+		Array<BfProject*> projList;
+		for (auto project : projectList)
+			projList.Add(project);
+		mainModule->mSpecializedMethodModules[projList] = specModule;
 	}
 	}
 	return specModule;
 	return specModule;
 }
 }
@@ -11080,7 +11095,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
 	}
 	}
 
 
 	BfTypeVector sanitizedMethodGenericArguments;	
 	BfTypeVector sanitizedMethodGenericArguments;	
-	Array<BfProject*> projectList;
+	SizedArray<BfProject*, 4> projectList;
 	
 	
 	bool isUnspecializedPass = (flags & BfGetMethodInstanceFlag_UnspecializedPass) != 0;
 	bool isUnspecializedPass = (flags & BfGetMethodInstanceFlag_UnspecializedPass) != 0;
 	if ((isUnspecializedPass) && (methodDef->mGenericParams.size() == 0))
 	if ((isUnspecializedPass) && (methodDef->mGenericParams.size() == 0))
@@ -19095,7 +19110,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
 		if ((paramDef != NULL) && (paramDef->mParamDeclaration != NULL) && (paramDef->mParamDeclaration->mInitializer != NULL) &&
 		if ((paramDef != NULL) && (paramDef->mParamDeclaration != NULL) && (paramDef->mParamDeclaration->mInitializer != NULL) &&
 			(!paramDef->mParamDeclaration->mInitializer->IsA<BfBlock>()))
 			(!paramDef->mParamDeclaration->mInitializer->IsA<BfBlock>()))
 		{
 		{
-			BfMethodState methodState;
+			BfMethodState methodState;			
 			SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
 			SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
 			methodState.mTempKind = BfMethodState::TempKind_Static;
 			methodState.mTempKind = BfMethodState::TempKind_Static;
 
 

+ 12 - 6
IDEHelper/Compiler/BfModule.h

@@ -833,6 +833,7 @@ public:
 	};
 	};
 
 
 public:
 public:
+	BumpAllocator mBumpAlloc;
 	BfMethodState* mPrevMethodState; // Only non-null for things like local methods
 	BfMethodState* mPrevMethodState; // Only non-null for things like local methods
 	BfConstResolveState* mConstResolveState;	
 	BfConstResolveState* mConstResolveState;	
 	BfMethodInstance* mMethodInstance;	
 	BfMethodInstance* mMethodInstance;	
@@ -841,8 +842,8 @@ public:
 	BfIRBlock mIRHeadBlock;
 	BfIRBlock mIRHeadBlock;
 	BfIRBlock mIRInitBlock;
 	BfIRBlock mIRInitBlock;
 	BfIRBlock mIREntryBlock;
 	BfIRBlock mIREntryBlock;
-	Array<BfLocalVariable*> mLocals;
-	HashSet<BfLocalVarEntry> mLocalVarSet;
+	Array<BfLocalVariable*, AllocatorBump<BfLocalVariable*> > mLocals;
+	HashSet<BfLocalVarEntry, AllocatorBump<BfLocalVariable*> > mLocalVarSet;
 	Array<BfLocalMethod*> mLocalMethods;
 	Array<BfLocalMethod*> mLocalMethods;
 	Dictionary<String, BfLocalMethod*> mLocalMethodMap;
 	Dictionary<String, BfLocalMethod*> mLocalMethodMap;
 	Dictionary<String, BfLocalMethod*> mLocalMethodCache; // So any lambda 'capturing' and 'processing' stages use the same local method			
 	Dictionary<String, BfLocalMethod*> mLocalMethodCache; // So any lambda 'capturing' and 'processing' stages use the same local method			
@@ -899,7 +900,12 @@ public:
 
 
 public:
 public:
 	BfMethodState()
 	BfMethodState()
-	{		
+	{
+		mLocals.mAlloc = &mBumpAlloc;
+		mLocals.Reserve(8);
+		mLocalVarSet.mAlloc = &mBumpAlloc;
+		mLocalVarSet.Reserve(8);
+
 		mMethodInstance = NULL;		
 		mMethodInstance = NULL;		
 		mPrevMethodState = NULL;
 		mPrevMethodState = NULL;
 		mConstResolveState = NULL;
 		mConstResolveState = NULL;
@@ -1343,8 +1349,7 @@ public:
 	bool mHadBuildWarning;	
 	bool mHadBuildWarning;	
 	bool mIgnoreErrors;
 	bool mIgnoreErrors;
 	bool mIgnoreWarnings;	
 	bool mIgnoreWarnings;	
-	bool mSetIllegalSrcPosition;
-	bool mHadIgnoredError;
+	bool mSetIllegalSrcPosition;	
 	bool mReportErrors; // Still puts system in error state when set to false
 	bool mReportErrors; // Still puts system in error state when set to false
 	bool mIsInsideAutoComplete;
 	bool mIsInsideAutoComplete;
 	bool mIsHotModule;
 	bool mIsHotModule;
@@ -1439,6 +1444,7 @@ public:
 	BfDeferredCallEntry* AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfScopeData* scope, BfAstNode* srcNode = NULL, bool bypassVirtual = false, bool doNullCheck = false);	
 	BfDeferredCallEntry* AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfScopeData* scope, BfAstNode* srcNode = NULL, bool bypassVirtual = false, bool doNullCheck = false);	
 	void EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry);
 	void EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry);
 	void EmitDeferredCallProcessor(SLIList<BfDeferredCallEntry*>& callEntries, BfIRValue callTail);
 	void EmitDeferredCallProcessor(SLIList<BfDeferredCallEntry*>& callEntries, BfIRValue callTail);
+	bool DoCanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags = BfCastFlags_None);
 	bool CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags = BfCastFlags_None);
 	bool CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags = BfCastFlags_None);
 	bool AreSplatsCompatible(BfType* fromType, BfType* toType, bool* outNeedsMemberCasting);
 	bool AreSplatsCompatible(BfType* fromType, BfType* toType, bool* outNeedsMemberCasting);
 	BfTypedValue BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType /*Can be System.Object or interface*/, const BfAllocTarget& allocTarget, bool callDtor = true);
 	BfTypedValue BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType /*Can be System.Object or interface*/, const BfAllocTarget& allocTarget, bool callDtor = true);
@@ -1712,7 +1718,7 @@ public:
 	BfMethodInstance* GetRawMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false, bool allowMixin = false);
 	BfMethodInstance* GetRawMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false, bool allowMixin = false);
 	BfMethodInstance* GetUnspecializedMethodInstance(BfMethodInstance* methodInstance); // Unspecialized owner type and unspecialized method type	
 	BfMethodInstance* GetUnspecializedMethodInstance(BfMethodInstance* methodInstance); // Unspecialized owner type and unspecialized method type	
 	int GetGenericParamAndReturnCount(BfMethodInstance* methodInstance);	
 	int GetGenericParamAndReturnCount(BfMethodInstance* methodInstance);	
-	BfModule* GetSpecializedMethodModule(const Array<BfProject*>& projectList);	
+	BfModule* GetSpecializedMethodModule(const SizedArrayImpl<BfProject*>& projectList);	
 	BfModuleMethodInstance GetMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName = NULL);	
 	BfModuleMethodInstance GetMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName = NULL);	
 	BfModuleMethodInstance GetMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false);
 	BfModuleMethodInstance GetMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false);
 	BfModuleMethodInstance GetMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, const Array<BfType*>& paramTypes, bool checkBase = false);
 	BfModuleMethodInstance GetMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, const Array<BfType*>& paramTypes, bool checkBase = false);

+ 362 - 128
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -4653,8 +4653,6 @@ BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef)
 {	
 {	
 	bool isStructPtr = false;
 	bool isStructPtr = false;
 
 
-// 	if (resolvedTypeRef->IsPointer())
-// 		resolvedTypeRef = ((BfPointerType*)resolvedTypeRef)->mElementType;
 	if (resolvedTypeRef->IsPrimitiveType())
 	if (resolvedTypeRef->IsPrimitiveType())
 	{
 	{
 		auto primType = (BfPrimitiveType*)resolvedTypeRef;
 		auto primType = (BfPrimitiveType*)resolvedTypeRef;
@@ -7696,14 +7694,13 @@ BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfTypeRe
 	return ResolveTypeRef(typeRef, populateType, resolveFlags);
 	return ResolveTypeRef(typeRef, populateType, resolveFlags);
 }
 }
 
 
-// This flow should mirror CastToValue
-bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags)
+bool BfModule::DoCanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags)
 {
 {
 	BfType* fromType = typedVal.mType;
 	BfType* fromType = typedVal.mType;
 
 
 	if (fromType == toType)
 	if (fromType == toType)
 		return true;
 		return true;
-
+	
 	// Ref X to Ref Y, X* to Y*
 	// Ref X to Ref Y, X* to Y*
 	{
 	{
 		bool checkUnderlying = false;
 		bool checkUnderlying = false;
@@ -7782,7 +7779,7 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 		{
 		{
 			if ((genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_StructPtr)) ||
 			if ((genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_StructPtr)) ||
 				((genericParamInst->mTypeConstraint != NULL) &&
 				((genericParamInst->mTypeConstraint != NULL) &&
-				 ((genericParamInst->mTypeConstraint->IsPointer()) || (genericParamInst->mTypeConstraint->IsObjectOrInterface()))))
+				((genericParamInst->mTypeConstraint->IsPointer()) || (genericParamInst->mTypeConstraint->IsObjectOrInterface()))))
 			{
 			{
 				return true;
 				return true;
 			}
 			}
@@ -7868,8 +7865,8 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 			//  And from T* to T[size]* explicitly
 			//  And from T* to T[size]* explicitly
 			if (fromUnderlying->IsSizedArray())
 			if (fromUnderlying->IsSizedArray())
 				fromUnderlying = fromUnderlying->GetUnderlyingType();
 				fromUnderlying = fromUnderlying->GetUnderlyingType();
-// 			if ((toUnderlying->IsSizedArray()) && (explicitCast))
-// 				toUnderlying = toUnderlying->GetUnderlyingType();
+			// 			if ((toUnderlying->IsSizedArray()) && (explicitCast))
+			// 				toUnderlying = toUnderlying->GetUnderlyingType();
 
 
 			if ((fromUnderlying == toUnderlying) ||
 			if ((fromUnderlying == toUnderlying) ||
 				(TypeIsSubTypeOf(fromUnderlying->ToTypeInstance(), toUnderlying->ToTypeInstance())) ||
 				(TypeIsSubTypeOf(fromUnderlying->ToTypeInstance(), toUnderlying->ToTypeInstance())) ||
@@ -7905,20 +7902,20 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 	if (((fromType->IsValueType()) || (fromType->IsPointer()) || (fromType->IsValuelessType())) &&
 	if (((fromType->IsValueType()) || (fromType->IsPointer()) || (fromType->IsValuelessType())) &&
 		((toType->IsInterface()) || (toType == mContext->mBfObjectType)))
 		((toType->IsInterface()) || (toType == mContext->mBfObjectType)))
 	{
 	{
-//  		if (fromType->IsPointer())
-//  		{
-//  			if (toType == mContext->mBfObjectType)
-//  				return true;
-//  			return false;
-//  		}
- 
+		//  		if (fromType->IsPointer())
+		//  		{
+		//  			if (toType == mContext->mBfObjectType)
+		//  				return true;
+		//  			return false;
+		//  		}
+
 		if (toType == mContext->mBfObjectType)
 		if (toType == mContext->mBfObjectType)
 			return true;
 			return true;
 
 
- 		BfTypeInstance* fromStructTypeInstance = NULL;
- 		fromStructTypeInstance = fromType->ToTypeInstance();
- 		if (fromStructTypeInstance == NULL)
- 		{
+		BfTypeInstance* fromStructTypeInstance = NULL;
+		fromStructTypeInstance = fromType->ToTypeInstance();
+		if (fromStructTypeInstance == NULL)
+		{
 			if (fromType->IsPrimitiveType())
 			if (fromType->IsPrimitiveType())
 			{
 			{
 				auto primType = (BfPrimitiveType*)fromType;
 				auto primType = (BfPrimitiveType*)fromType;
@@ -7926,15 +7923,79 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 			}
 			}
 			else
 			else
 				return false;
 				return false;
- 		}
+		}
 
 
- 		auto toTypeInstance = toType->ToTypeInstance(); 
- 		// Need to box it
- 		if (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance))
- 			return true;
+		auto toTypeInstance = toType->ToTypeInstance();
+		// Need to box it
+		if (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance))
+			return true;
 	}
 	}
 
 
-	if (fromType->IsRef())
+	// Null -> Nullable<T>
+	if ((typedVal.mType->IsNull()) && (toType->IsNullable()))
+	{		
+		return true;
+	}
+
+	// Nullable<A> -> Nullable<B>
+	if ((typedVal.mType->IsNullable()) && (toType->IsNullable()))
+	{
+		auto fromNullableType = (BfGenericTypeInstance*)typedVal.mType;
+		auto toNullableType = (BfGenericTypeInstance*)toType;
+
+		return CanImplicitlyCast(BfTypedValue(mBfIRBuilder->GetFakeVal(), fromNullableType->mTypeGenericArguments[0]), toNullableType->mTypeGenericArguments[0], castFlags);		
+	}
+
+	// Tuple -> Tuple
+	if ((typedVal.mType->IsTuple()) && (toType->IsTuple()))
+	{
+		auto fromTupleType = (BfTupleType*)typedVal.mType;
+		auto toTupleType = (BfTupleType*)toType;
+		if (fromTupleType->mFieldInstances.size() == toTupleType->mFieldInstances.size())
+		{			
+			bool canCast = true;
+
+			BfIRValue curTupleValue = mBfIRBuilder->CreateUndefValue(mBfIRBuilder->MapType(toTupleType));
+			for (int valueIdx = 0; valueIdx < (int)fromTupleType->mFieldInstances.size(); valueIdx++)
+			{
+				BfFieldInstance* fromFieldInstance = &fromTupleType->mFieldInstances[valueIdx];
+				BfFieldInstance* toFieldInstance = &toTupleType->mFieldInstances[valueIdx];
+
+				//
+				{
+					BfFieldDef* fromFieldDef = fromFieldInstance->GetFieldDef();
+					BfFieldDef* toFieldDef = toFieldInstance->GetFieldDef();
+
+					// Either the names have to match or one has to be unnamed
+					if ((!fromFieldDef->IsUnnamedTupleField()) && (!toFieldDef->IsUnnamedTupleField()) &&
+						(fromFieldDef->mName != toFieldDef->mName))
+					{
+						curTupleValue = BfIRValue();
+						break;
+					}
+				}
+
+				auto fromFieldType = fromFieldInstance->GetResolvedType();
+				auto toFieldType = toFieldInstance->GetResolvedType();
+
+				if (toFieldType->IsVoid())
+					continue; // Allow sinking to void
+
+				BfIRValue fromFieldValue;				
+				bool canCastField = CanImplicitlyCast(BfTypedValue(mBfIRBuilder->GetFakeVal(), fromFieldType), toFieldType, (BfCastFlags)(castFlags | BfCastFlags_Explicit));
+				if (!canCastField)
+				{
+					canCast = false;
+					break;
+				}				
+			}
+
+			if (canCast)
+				return false;
+		}
+	}
+
+	/*if (fromType->IsRef())
 	{
 	{
 		if (toType->IsRef())
 		if (toType->IsRef())
 		{
 		{
@@ -7946,7 +8007,7 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 			// ref T -> T
 			// ref T -> T
 			return fromType->GetUnderlyingType() == toType;
 			return fromType->GetUnderlyingType() == toType;
 		}
 		}
-	}
+	}*/
 
 
 	// Int -> Enum
 	// Int -> Enum
 	if ((typedVal.mType->IsIntegral()) && (toType->IsEnum()))
 	if ((typedVal.mType->IsIntegral()) && (toType->IsEnum()))
@@ -8005,7 +8066,7 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 		if (constant != NULL)
 		if (constant != NULL)
 		{
 		{
 			BfConstExprValueType* toConstExprValueType = (BfConstExprValueType*)toType;
 			BfConstExprValueType* toConstExprValueType = (BfConstExprValueType*)toType;
-			
+
 			auto variantVal = TypedValueToVariant(NULL, typedVal);
 			auto variantVal = TypedValueToVariant(NULL, typedVal);
 			if ((mBfIRBuilder->IsInt(variantVal.mTypeCode)) && (mBfIRBuilder->IsInt(toConstExprValueType->mValue.mTypeCode)))
 			if ((mBfIRBuilder->IsInt(variantVal.mTypeCode)) && (mBfIRBuilder->IsInt(toConstExprValueType->mValue.mTypeCode)))
 			{
 			{
@@ -8054,15 +8115,15 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 					}
 					}
 					else if (toType->IsSigned())
 					else if (toType->IsSigned())
 					{
 					{
-                        if (toType->mSize == 8) // int64
-                            return true;
-                        else
-                        {
-                            int64 minVal = -(1LL << (8 * toType->mSize - 1));
-                            int64 maxVal = (1LL << (8 * toType->mSize - 1)) - 1;
-                            if ((srcVal >= minVal) && (srcVal <= maxVal))
-                                return true;
-                        }
+						if (toType->mSize == 8) // int64
+							return true;
+						else
+						{
+							int64 minVal = -(1LL << (8 * toType->mSize - 1));
+							int64 maxVal = (1LL << (8 * toType->mSize - 1)) - 1;
+							if ((srcVal >= minVal) && (srcVal <= maxVal))
+								return true;
+						}
 					}
 					}
 					else if (toType->mSize == 8) // ulong
 					else if (toType->mSize == 8) // ulong
 					{
 					{
@@ -8420,7 +8481,7 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 			}
 			}
 
 
 			BfBaseClassWalker baseClassWalker(fromType, toType, this);
 			BfBaseClassWalker baseClassWalker(fromType, toType, this);
-			
+
 			while (true)
 			while (true)
 			{
 			{
 				auto entry = baseClassWalker.Next();
 				auto entry = baseClassWalker.Next();
@@ -8455,7 +8516,7 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 						// Selection pass
 						// Selection pass
 						if (pass < 2)
 						if (pass < 2)
 						{
 						{
-							auto methodCheckFromType = methodFromType;							
+							auto methodCheckFromType = methodFromType;
 							auto methodCheckToType = methodToType;
 							auto methodCheckToType = methodToType;
 							if (pass == 1)
 							if (pass == 1)
 							{
 							{
@@ -8495,13 +8556,13 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 									bestToDist = toDist;
 									bestToDist = toDist;
 									bestToType = methodToType;
 									bestToType = methodToType;
 								}
 								}
-							}							
+							}
 						}
 						}
 						else if (pass == 2) // Execution Pass
 						else if (pass == 2) // Execution Pass
 						{
 						{
 							if ((methodFromType == bestFromType) && (methodToType == bestToType))
 							if ((methodFromType == bestFromType) && (methodToType == bestToType))
 							{
 							{
-								return true;
+								return CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, bestToType), toType, castFlags);
 							}
 							}
 						}
 						}
 					}
 					}
@@ -8515,12 +8576,59 @@ bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFl
 				bestFromType = bestNegFromType;
 				bestFromType = bestNegFromType;
 			if (bestToType == NULL)
 			if (bestToType == NULL)
 				bestToType = bestNegToType;
 				bestToType = bestNegToType;
-		}		
+		}
+	}
+
+	// Prim -> TypedPrimitive
+	if ((typedVal.mType->IsPrimitiveType()) && (toType->IsTypedPrimitive()))
+	{
+		bool allowCast = false;
+		if (toType == mCurTypeInstance)
+			allowCast = true;
+		if ((!allowCast) && (typedVal.mType->IsIntegral()) /*&& (!toType->IsEnum())*/)
+		{
+			// Allow implicit cast of zero
+			auto constant = mBfIRBuilder->GetConstant(typedVal.mValue);
+			if ((constant != NULL) && (mBfIRBuilder->IsInt(constant->mTypeCode)))
+			{
+				allowCast = constant->mInt64 == 0;
+			}
+		}
+		if (allowCast)
+		{
+			return CanImplicitlyCast(typedVal, toType->GetUnderlyingType(), castFlags);
+		}
 	}
 	}
 
 
 	return false;
 	return false;
 }
 }
 
 
+// This flow should mirror CastToValue
+bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags)
+{
+	BP_ZONE("BfModule::CanImplicitlyCast");
+
+	//return DoCanImplicitlyCast(typedVal, toType, castFlags);
+
+	bool canCastToValue;
+	{
+		SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
+		canCastToValue = CastToValue(NULL, typedVal, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail));
+		return canCastToValue;
+	}
+
+	return canCastToValue;
+
+	bool sideCanCast = DoCanImplicitlyCast(typedVal, toType, castFlags);
+	if (canCastToValue != sideCanCast)
+	{
+		NOP;  
+	}
+	//BF_ASSERT(canCastToValue == sideCanCast);
+	return sideCanCast;
+}
+
+
 bool BfModule::AreSplatsCompatible(BfType* fromType, BfType* toType, bool* outNeedsMemberCasting)
 bool BfModule::AreSplatsCompatible(BfType* fromType, BfType* toType, bool* outNeedsMemberCasting)
 {
 {
 	if ((fromType->IsTypeInstance()) && (!fromType->IsSplattable()))
 	if ((fromType->IsTypeInstance()) && (!fromType->IsSplattable()))
@@ -8600,6 +8708,8 @@ BfIRValue BfModule::CastToFunction(BfAstNode* srcNode, BfMethodInstance* methodI
 BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags, BfCastResultFlags* resultFlags)
 BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags, BfCastResultFlags* resultFlags)
 {
 {
 	bool explicitCast = (castFlags & BfCastFlags_Explicit) != 0;
 	bool explicitCast = (castFlags & BfCastFlags_Explicit) != 0;
+	bool ignoreErrors = mIgnoreErrors || ((castFlags & BfCastFlags_SilentFail) != 0);	
+	bool ignoreWrites = mBfIRBuilder->mIgnoreWrites;
 
 
 	if (typedVal.mType == toType)
 	if (typedVal.mType == toType)
 	{
 	{
@@ -8692,12 +8802,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 
 
 		// void* -> intptr
 		// void* -> intptr
 		if ((typedVal.mType->IsPointer()) && (toType->IsIntPtr()))
 		if ((typedVal.mType->IsPointer()) && (toType->IsIntPtr()))
-		{
-			//TODO: Put back
-			/*if ((!typedVal.mType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
+		{				
+			if ((!ignoreErrors) && (!typedVal.mType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
 			{
 			{
 				Fail(StrFormat("Unable to cast direct from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
 				Fail(StrFormat("Unable to cast direct from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
-			}*/
+			}
 						
 						
 			auto toPrimitive = (BfPrimitiveType*)toType;
 			auto toPrimitive = (BfPrimitiveType*)toType;
 			return mBfIRBuilder->CreatePtrToInt(typedVal.mValue, toPrimitive->mTypeDef->mTypeCode);
 			return mBfIRBuilder->CreatePtrToInt(typedVal.mValue, toPrimitive->mTypeDef->mTypeCode);
@@ -8705,12 +8814,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 
 
 		// intptr -> void*
 		// intptr -> void*
 		if ((typedVal.mType->IsIntPtr()) && (toType->IsPointer()))
 		if ((typedVal.mType->IsIntPtr()) && (toType->IsPointer()))
-		{
-			//TODO: Put back
-			/*if ((!toType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
+		{			
+			if ((!ignoreErrors) && (!toType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
 			{
 			{
 				Fail(StrFormat("Unable to cast direct from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
 				Fail(StrFormat("Unable to cast direct from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
-			}*/
+			}
 
 
 			return mBfIRBuilder->CreateIntToPtr(typedVal.mValue, mBfIRBuilder->MapType(toType));
 			return mBfIRBuilder->CreateIntToPtr(typedVal.mValue, mBfIRBuilder->MapType(toType));
 		}
 		}
@@ -8846,30 +8954,49 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 		}
 		}
 	}
 	}
 
 
-	// ObjectInst|IFace -> object|IFace
-	if ((typedVal.mType->IsObject() || (typedVal.mType->IsInterface())) && ((toType->IsObject() || (toType->IsInterface()))))
+	if ((typedVal.mType->IsTypeInstance()) && (toType->IsTypeInstance()))
 	{
 	{
-		bool allowCast = false;
-		
 		auto fromTypeInstance = typedVal.mType->ToTypeInstance();
 		auto fromTypeInstance = typedVal.mType->ToTypeInstance();
 		auto toTypeInstance = toType->ToTypeInstance();
 		auto toTypeInstance = toType->ToTypeInstance();
 
 
-		if (TypeIsSubTypeOf(fromTypeInstance, toTypeInstance))
-			allowCast = true;
-		else if ((explicitCast) && 
-			((toType->IsInterface()) || (TypeIsSubTypeOf(toTypeInstance, fromTypeInstance))))
+		if ((typedVal.mType->IsValueType()) && (toType->IsValueType()))
 		{
 		{
-			if (toType->IsObjectOrInterface())
+			bool allowCast = false;
+			if (TypeIsSubTypeOf(fromTypeInstance, toTypeInstance))
+				allowCast = true;
+			if (allowCast)
 			{
 			{
-				if ((castFlags & BfCastFlags_Unchecked) == 0)
-					EmitDynamicCastCheck(typedVal, toType, true);
+				if (toType->IsValuelessType())
+					return BfIRValue::sValueless;
 			}
 			}
-			allowCast = true;
 		}
 		}
 
 
-		if (allowCast)
-			return mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapType(toType));
-	}
+		// ObjectInst|IFace -> object|IFace
+		if ((typedVal.mType->IsObject() || (typedVal.mType->IsInterface())) && ((toType->IsObject() || (toType->IsInterface()))))
+		{
+			bool allowCast = false;			
+
+			if (TypeIsSubTypeOf(fromTypeInstance, toTypeInstance))
+				allowCast = true;
+			else if ((explicitCast) &&
+				((toType->IsInterface()) || (TypeIsSubTypeOf(toTypeInstance, fromTypeInstance))))
+			{
+				if (toType->IsObjectOrInterface())
+				{
+					if ((castFlags & BfCastFlags_Unchecked) == 0)
+						EmitDynamicCastCheck(typedVal, toType, true);
+				}
+				allowCast = true;
+			}
+
+			if (allowCast)
+			{
+				if (ignoreWrites)
+					return mBfIRBuilder->GetFakeVal();
+				return mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapType(toType));
+			}
+		}
+	}	
 
 
 	// MethodRef -> Function
 	// MethodRef -> Function
 	if ((typedVal.mType->IsMethodRef()) && (toType->IsFunction()))
 	if ((typedVal.mType->IsMethodRef()) && (toType->IsFunction()))
@@ -8918,7 +9045,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 				allowCast = true;
 				allowCast = true;
 
 
 			if (allowCast)
 			if (allowCast)
+			{
+				if (ignoreWrites)
+					return mBfIRBuilder->GetFakeVal();
 				return mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapType(toType));
 				return mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapType(toType));
+			}
 		}
 		}
 		else if (typedVal.mType->IsObject())
 		else if (typedVal.mType->IsObject())
 		{
 		{
@@ -8951,9 +9082,10 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 		((toType->IsValueType()) || (toType->IsPointer())))
 		((toType->IsValueType()) || (toType->IsPointer())))
 	{
 	{
 		if (toType->IsValuelessType())
 		if (toType->IsValuelessType())
-		{
-			return mBfIRBuilder->GetFakeVal();
-		}
+			return BfIRValue::sValueless;		
+
+		if (ignoreWrites)		
+			return mBfIRBuilder->GetFakeVal();		
 
 
 		// Unbox!
 		// Unbox!
 		if ((castFlags & BfCastFlags_Unchecked) == 0)
 		if ((castFlags & BfCastFlags_Unchecked) == 0)
@@ -9036,6 +9168,9 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 	// Null -> Nullable<T>
 	// Null -> Nullable<T>
 	if ((typedVal.mType->IsNull()) && (toType->IsNullable()))
 	if ((typedVal.mType->IsNull()) && (toType->IsNullable()))
 	{
 	{
+		if (ignoreWrites)
+			return mBfIRBuilder->GetFakeVal();
+
 		if ((castFlags & BfCastFlags_PreferAddr) != 0)
 		if ((castFlags & BfCastFlags_PreferAddr) != 0)
 		{
 		{
 			auto boolType = GetPrimitiveType(BfTypeCode_Boolean);		
 			auto boolType = GetPrimitiveType(BfTypeCode_Boolean);		
@@ -9059,6 +9194,9 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 	// Nullable<A> -> Nullable<B>
 	// Nullable<A> -> Nullable<B>
 	if ((typedVal.mType->IsNullable()) && (toType->IsNullable()))
 	if ((typedVal.mType->IsNullable()) && (toType->IsNullable()))
 	{
 	{
+		if (ignoreWrites)		
+			return mBfIRBuilder->GetFakeVal();
+
 		auto fromNullableType = (BfGenericTypeInstance*)typedVal.mType;
 		auto fromNullableType = (BfGenericTypeInstance*)typedVal.mType;
 		auto toNullableType = (BfGenericTypeInstance*)toType;
 		auto toNullableType = (BfGenericTypeInstance*)toType;
 
 
@@ -9073,7 +9211,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 		auto srcAddr = mBfIRBuilder->CreateInBoundsGEP(srcPtr, 0, 1); // mValue
 		auto srcAddr = mBfIRBuilder->CreateInBoundsGEP(srcPtr, 0, 1); // mValue
 		auto srcVal = mBfIRBuilder->CreateLoad(srcAddr);
 		auto srcVal = mBfIRBuilder->CreateLoad(srcAddr);
 
 
-		auto toVal = CastToValue(srcNode, BfTypedValue(srcVal, fromNullableType->mTypeGenericArguments[0]), toNullableType->mTypeGenericArguments[0]);
+		auto toVal = CastToValue(srcNode, BfTypedValue(srcVal, fromNullableType->mTypeGenericArguments[0]), toNullableType->mTypeGenericArguments[0], ignoreErrors ? BfCastFlags_SilentFail : BfCastFlags_None);
 		if (!toVal)
 		if (!toVal)
 			return BfIRValue();
 			return BfIRValue();
 
 
@@ -9166,7 +9304,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 					return typedVal.mValue;
 					return typedVal.mValue;
 			}
 			}
 
 
-			if ((castFlags & BfCastFlags_SilentFail) == 0)
+			if (!ignoreErrors)
 			{	
 			{	
 				String valStr;
 				String valStr;
 				VariantToString(valStr, variantVal);
 				VariantToString(valStr, variantVal);
@@ -9533,7 +9671,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 							if (fromDist < 0)
 							if (fromDist < 0)
 							{
 							{
 								// Allow us to cast a constant int to a smaller type if it satisfies the cast operator
 								// Allow us to cast a constant int to a smaller type if it satisfies the cast operator
-								if ((typedVal.mValue.IsConst()) && (CanImplicitlyCast(typedVal, methodCheckFromType)))
+								if ((typedVal.mValue.IsConst()) && (CanImplicitlyCast(typedVal, methodCheckFromType, BfCastFlags_NoConversionOperator)))
 								{
 								{
 									fromDist = 0;
 									fromDist = 0;
 								}
 								}
@@ -9623,7 +9761,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 				{
 				{
 					if (mayBeBox)
 					if (mayBeBox)
 					{
 					{
-						if (Fail("Ambiguous cast, may be conversion operator or may be boxing request", srcNode) != NULL)
+						if ((!ignoreErrors) && (Fail("Ambiguous cast, may be conversion operator or may be boxing request", srcNode) != NULL))
 							mCompiler->mPassInstance->MoreInfo("See conversion operator", opMethodInstance->mMethodDef->GetRefNode());
 							mCompiler->mPassInstance->MoreInfo("See conversion operator", opMethodInstance->mMethodDef->GetRefNode());
 					}
 					}
 
 
@@ -9653,7 +9791,10 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 					auto castedFromValue = Cast(srcNode, typedVal, bestFromType, castFlags);
 					auto castedFromValue = Cast(srcNode, typedVal, bestFromType, castFlags);
 					if (!castedFromValue)
 					if (!castedFromValue)
 						return BfIRValue();
 						return BfIRValue();
-										
+					
+					if (ignoreWrites)
+						return mBfIRBuilder->GetFakeVal();
+
 					SizedArray<BfIRValue, 1> args;					
 					SizedArray<BfIRValue, 1> args;					
 					exprEvaluator.PushArg(castedFromValue, args);
 					exprEvaluator.PushArg(castedFromValue, args);
 					auto operatorOut = exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, mCompiler->IsSkippingExtraResolveChecks() ? BfIRValue() : moduleMethodInstance.mFunc, false, args);
 					auto operatorOut = exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, mCompiler->IsSkippingExtraResolveChecks() ? BfIRValue() : moduleMethodInstance.mFunc, false, args);
@@ -9676,8 +9817,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 		isAmbiguousCast |= ((bestFromType != NULL) && (bestToType != NULL));
 		isAmbiguousCast |= ((bestFromType != NULL) && (bestToType != NULL));
 		if (isAmbiguousCast)
 		if (isAmbiguousCast)
 		{
 		{
-			const char* errStr = "Ambiguous conversion operators for casting from '%s' to '%s'";
-			Fail(StrFormat(errStr, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
+			if (!ignoreErrors)
+			{
+				const char* errStr = "Ambiguous conversion operators for casting from '%s' to '%s'";
+				Fail(StrFormat(errStr, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
+			}
 			return BfIRValue();
 			return BfIRValue();
 		}
 		}
 
 
@@ -9697,7 +9841,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 						{
 						{
 							// .. and we can convert the constraint's toType to OUR toType then we're good
 							// .. and we can convert the constraint's toType to OUR toType then we're good
 							auto opToVal = genericParam->mExternType;
 							auto opToVal = genericParam->mExternType;
-							if (CanImplicitlyCast(opToVal, toType))
+							if (CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType))
 								return mBfIRBuilder->GetFakeVal();
 								return mBfIRBuilder->GetFakeVal();
 						}
 						}
 					}
 					}
@@ -9722,7 +9866,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 						{
 						{
 							// .. and we can convert the constraint's toType to OUR toType then we're good
 							// .. and we can convert the constraint's toType to OUR toType then we're good
 							auto opToVal = genericParam->mExternType;
 							auto opToVal = genericParam->mExternType;
-							if (CanImplicitlyCast(opToVal, toType))
+							if (CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType))
 								return mBfIRBuilder->GetFakeVal();
 								return mBfIRBuilder->GetFakeVal();
 						}
 						}
 					}
 					}
@@ -9777,7 +9921,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 		bool allowCast = explicitCast;
 		bool allowCast = explicitCast;
 		if (toType == mCurTypeInstance)
 		if (toType == mCurTypeInstance)
 			allowCast = true;
 			allowCast = true;
- 		if ((!allowCast) && (typedVal.mType->IsIntegral()) && (!toType->IsEnum()))
+ 		if ((!allowCast) && (typedVal.mType->IsIntegral()) /*&& (!toType->IsEnum())*/)
  		{
  		{
  			// Allow implicit cast of zero
  			// Allow implicit cast of zero
  			auto constant = mBfIRBuilder->GetConstant(typedVal.mValue);
  			auto constant = mBfIRBuilder->GetConstant(typedVal.mValue);
@@ -9803,16 +9947,14 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 			Warn(0, "This implicit boxing will only be in scope during the constructor. Consider using a longer-term allocation such as 'box new'", srcNode);
 			Warn(0, "This implicit boxing will only be in scope during the constructor. Consider using a longer-term allocation such as 'box new'", srcNode);
 		}
 		}
 
 
+		SetAndRestoreValue<bool> ignoreWrites(mBfIRBuilder->mIgnoreWrites, ignoreWrites);
 		auto value = BoxValue(srcNode, typedVal, toType, scopeData, (castFlags & BfCastFlags_NoBoxDtor) == 0);
 		auto value = BoxValue(srcNode, typedVal, toType, scopeData, (castFlags & BfCastFlags_NoBoxDtor) == 0);
 		if (value)
 		if (value)
 			return value.mValue;
 			return value.mValue;
 	}
 	}
 
 
-	if ((castFlags & BfCastFlags_SilentFail) == 0)
+	if (!ignoreErrors)
 	{
 	{
-		if (mIgnoreErrors)
-			return BfIRValue();
-
 		const char* errStrF = explicitCast ?
 		const char* errStrF = explicitCast ?
 			"Unable to cast '%s' to '%s'" :
 			"Unable to cast '%s' to '%s'" :
 			"Unable to implicitly cast '%s' to '%s'";
 			"Unable to implicitly cast '%s' to '%s'";
@@ -10526,44 +10668,156 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
 	{
 	{
 		BfTypeInstance* typeInstance = (BfTypeInstance*)resolvedType;
 		BfTypeInstance* typeInstance = (BfTypeInstance*)resolvedType;
 		
 		
-		auto checkTypeInst = typeInstance;
-		auto checkTypeDef = typeInstance->mTypeDef;
+		//auto checkTypeInst = typeInstance;
+		//auto checkTypeDef = typeInstance->mTypeDef;
+							
+		bool omitNamespace = (typeNameFlags & BfTypeNameFlag_OmitNamespace) != 0;
+		if ((typeNameFlags & BfTypeNameFlag_ReduceName) != 0)
+		{
+			for (auto& checkNamespace : mCurTypeInstance->mTypeDef->mNamespaceSearch)
+			{
+				if (checkNamespace == typeInstance->mTypeDef->mNamespace)
+					omitNamespace = true;
+			}
+		}
 
 
-		auto checkCurTypeInst = mCurTypeInstance; // Only used for ReduceName
-		BfTypeDef* checkCurTypeDef = NULL;
-		if (checkCurTypeInst != NULL)
-			checkCurTypeDef = checkCurTypeInst->mTypeDef;
+		if ((!typeInstance->mTypeDef->mNamespace.IsEmpty()) && (!omitNamespace))
+		{			
+			if (!typeInstance->mTypeDef->mNamespace.IsEmpty())
+			{
+				typeInstance->mTypeDef->mNamespace.ToString(str);
+				if (!typeInstance->mTypeDef->IsGlobalsContainer())
+					str += '.';
+			}
+		}
+		
+		//_AddTypeName(typeInstance->mTypeDef, 0);
 
 
-		std::function<void(BfTypeDef*, int)> _AddTypeName = [&](BfTypeDef* checkTypeDef, int depth) 
+		//std::function<void(String& str, BfTypeInstance*, BfTypeDef*, int, BfTypeNameFlags)> _AddTypeName = [&](StringImpl& str, BfTypeInstance*& checkTypeInst, BfTypeDef* checkTypeDef, int depth, BfTypeNameFlags typeNameFlags)
+		
+// 		BfTypeDef* endTypeDef = NULL;
+// 		if ((typeNameFlags & BfTypeNameFlag_ReduceName) != 0)
+// 		{
+// 			auto checkTypeInst = typeInstance;
+// 			auto checkTypeDef = typeInstance->mTypeDef;
+// 
+// 			auto outerTypeInst = GetOuterType(checkTypeInst);
+// 			if (outerTypeInst == NULL)
+// 				return;
+// 			checkTypeInst = outerTypeInst;
+// 
+// 			auto checkCurTypeInst = mCurTypeInstance; // Only used for ReduceName
+// 			BfTypeDef* checkCurTypeDef = NULL;
+// 			if (checkCurTypeInst != NULL)
+// 				checkCurTypeDef = checkCurTypeInst->mTypeDef;
+// 
+// 			while (checkCurTypeDef->mNestDepth > checkTypeDef->mNestDepth)
+// 			{
+// 				checkCurTypeInst = GetOuterType(checkCurTypeInst);
+// 				checkCurTypeDef = checkCurTypeInst->mTypeDef;
+// 			}
+// 
+// 			if (TypeIsSubTypeOf(checkCurTypeInst, checkTypeInst))
+// 				endTypeDef = checkCurTypeDef;
+// 		}
+
+		
+
+		SizedArray<BfTypeDef*, 8> typeDefStack;		
+		
+		BfTypeDef* endTypeDef = NULL;
+		if (((typeNameFlags & BfTypeNameFlag_ReduceName) != 0) && (mCurTypeInstance != NULL))
 		{
 		{
-			if (depth > 0)
+			auto checkTypeInst = typeInstance; 			
+ 
+ 			auto outerTypeInst = GetOuterType(checkTypeInst);
+ 			if (outerTypeInst != NULL) 				
 			{
 			{
-				if ((typeNameFlags & BfTypeNameFlag_OmitOuterType) != 0)
-					return;
+				checkTypeInst = outerTypeInst;
+				auto checkTypeDef = checkTypeInst->mTypeDef;
+
+				auto checkCurTypeInst = mCurTypeInstance; // Only used for ReduceName
+				BfTypeDef* checkCurTypeDef = NULL;
+				if (checkCurTypeInst != NULL)
+					checkCurTypeDef = checkCurTypeInst->mTypeDef;
 
 
-				if ((typeNameFlags & BfTypeNameFlag_ReduceName) != 0)
+				while (checkCurTypeDef->mNestDepth > checkTypeDef->mNestDepth)
 				{
 				{
-					auto outerTypeInst = GetOuterType(checkTypeInst);
-					if (outerTypeInst == NULL)
-						return;
-					checkTypeInst = outerTypeInst;
+					checkCurTypeInst = GetOuterType(checkCurTypeInst);
+					checkCurTypeDef = checkCurTypeInst->mTypeDef;
+				}
 
 
-					while (checkCurTypeDef->mNestDepth > checkTypeDef->mNestDepth)
+				while (checkTypeDef != NULL)
+				{
+					if (TypeIsSubTypeOf(checkCurTypeInst, checkTypeInst))
 					{
 					{
-						checkCurTypeInst = GetOuterType(checkCurTypeInst);
-						checkCurTypeDef = checkCurTypeInst->mTypeDef;
+						endTypeDef = checkTypeDef;
+						break;
 					}
 					}
 
 
-					if (TypeIsSubTypeOf(checkCurTypeInst, checkTypeInst))
-						return; // Found outer type				
+					checkCurTypeInst = GetOuterType(checkCurTypeInst);
+					if (checkCurTypeInst == NULL)
+						break;
+					checkCurTypeDef = checkCurTypeInst->mTypeDef;
+
+					checkTypeInst = GetOuterType(checkTypeInst);
+					if (checkTypeInst == NULL)
+						break;
+					checkTypeDef = checkTypeInst->mTypeDef;
 				}
 				}
 			}
 			}
+		}
 
 
-			auto parentTypeDef = checkTypeDef->mOuterType;
-			if (parentTypeDef != NULL)
-			{
-				_AddTypeName(parentTypeDef, depth + 1);				
-			}
+		BfTypeDef* checkTypeDef = typeInstance->mTypeDef;
+		while (checkTypeDef != NULL)
+		{
+			typeDefStack.Add(checkTypeDef);
+
+			checkTypeDef = checkTypeDef->mOuterType;
+
+			if ((typeNameFlags & BfTypeNameFlag_OmitOuterType) != 0)
+				break;
+
+			if (checkTypeDef == endTypeDef)
+				break;
+		}
+
+		while (!typeDefStack.IsEmpty())
+		{
+			BfTypeDef* checkTypeDef = typeDefStack.back();
+			int depth = (int)typeDefStack.size() - 1;
+			typeDefStack.pop_back();
+
+// 			if (depth > 0)
+// 			{
+// 				if ((typeNameFlags & BfTypeNameFlag_OmitOuterType) != 0)
+// 					return;
+// 
+// 				if ((typeNameFlags & BfTypeNameFlag_ReduceName) != 0)
+// 				{
+// 					auto outerTypeInst = GetOuterType(checkTypeInst);
+// 					if (outerTypeInst == NULL)
+// 						return;
+// 					checkTypeInst = outerTypeInst;
+// 
+// 					while (checkCurTypeDef->mNestDepth > checkTypeDef->mNestDepth)
+// 					{
+// 						checkCurTypeInst = GetOuterType(checkCurTypeInst);
+// 						checkCurTypeDef = checkCurTypeInst->mTypeDef;
+// 					}
+// 
+// 					if (TypeIsSubTypeOf(checkCurTypeInst, checkTypeInst))
+// 						return; // Found outer type				
+// 				}
+// 			}
+
+// 			auto parentTypeDef = checkTypeDef->mOuterType;
+// 			if (parentTypeDef != NULL)
+// 			{
+// 				//_AddTypeName(parentTypeDef, depth + 1);
+// 				typeDefStack.Add(parentTypeDef);
+// 				continue;
+// 			}
 
 
 			if (checkTypeDef->IsGlobalsContainer())
 			if (checkTypeDef->IsGlobalsContainer())
 			{
 			{
@@ -10630,32 +10884,12 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
 					}
 					}
 					str += '>';
 					str += '>';
 				}
 				}
-			}		
+			}
 
 
 			if (depth > 0)
 			if (depth > 0)
 				str += '.';
 				str += '.';
-		};							
-
-		bool omitNamespace = (typeNameFlags & BfTypeNameFlag_OmitNamespace) != 0;
-		if ((typeNameFlags & BfTypeNameFlag_ReduceName) != 0)
-		{
-			for (auto& checkNamespace : mCurTypeInstance->mTypeDef->mNamespaceSearch)
-			{
-				if (checkNamespace == typeInstance->mTypeDef->mNamespace)
-					omitNamespace = true;
-			}
-		}
+		};
 
 
-		if ((!typeInstance->mTypeDef->mNamespace.IsEmpty()) && (!omitNamespace))
-		{			
-			if (!typeInstance->mTypeDef->mNamespace.IsEmpty())
-			{
-				typeInstance->mTypeDef->mNamespace.ToString(str);
-				if (!typeInstance->mTypeDef->IsGlobalsContainer())
-					str += '.';
-			}
-		}
-		_AddTypeName(typeInstance->mTypeDef, 0);
 		return;
 		return;
 	}
 	}
 	else if (resolvedType->IsPrimitiveType())
 	else if (resolvedType->IsPrimitiveType())

+ 0 - 58
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -3627,64 +3627,6 @@ String BfTypeUtils::HashEncode64(uint64 val)
 	return outStr;
 	return outStr;
 }
 }
 
 
-void BfTypeUtils::GetProjectList(BfType* checkType, Array<BfProject*>* projectList, int immutableLength)
-{	
-	if (checkType->IsBoxed())
-		GetProjectList(((BfBoxedType*)checkType)->mElementType, projectList, immutableLength);
-
-	BfTypeInstance* typeInst = checkType->ToTypeInstance();
-	if (typeInst != NULL)
-	{
-		auto genericTypeInst = typeInst->ToGenericTypeInstance();
-		if (genericTypeInst != NULL)
-		{
-			for (auto genericArg : genericTypeInst->mTypeGenericArguments)
-				GetProjectList(genericArg, projectList, immutableLength);
-		}
-
-		BfProject* bfProject = typeInst->mTypeDef->mProject;
-		if (std::find(projectList->begin(), projectList->end(), bfProject) == projectList->end())
-		{
-			bool handled = false;
-			for (int idx = 0; idx < (int)projectList->size(); idx++)
-			{
-				auto checkProject = (*projectList)[idx];
-				bool isBetter = bfProject->ContainsReference(checkProject);
-				bool isWorse = checkProject->ContainsReference(bfProject);
-				if (isBetter == isWorse)
-					continue;
-				if (isBetter)
-				{
-					if (idx >= immutableLength)
-					{
-						// This is even more specific, so replace with this one
-						(*projectList)[idx] = bfProject;
-						handled = true;
-					}
-				}
-				else
-				{
-					// This is less specific, ignore
-					handled = true;
-				}
-				break;
-			}
-			if (!handled)
-			{			
-				projectList->push_back(bfProject);
-			}
-		}
-	}
-	else if (checkType->IsPointer())
-		GetProjectList(((BfPointerType*)checkType)->mElementType, projectList, immutableLength);
-	else if (checkType->IsRef())
-		GetProjectList(((BfPointerType*)checkType)->mElementType, projectList, immutableLength);
-	else if (checkType->IsSizedArray())
-		GetProjectList(((BfSizedArrayType*)checkType)->mElementType, projectList, immutableLength);	
-	else if (checkType->IsMethodRef())
-		GetProjectList(((BfMethodRefType*)checkType)->mOwner, projectList, immutableLength);
-}
-
 BfPrimitiveType* BfTypeUtils::GetPrimitiveType(BfModule* module, BfTypeCode typeCode)
 BfPrimitiveType* BfTypeUtils::GetPrimitiveType(BfModule* module, BfTypeCode typeCode)
 {
 {
 	return module->GetPrimitiveType(typeCode);
 	return module->GetPrimitiveType(typeCode);

+ 58 - 1
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -2332,7 +2332,64 @@ public:
 	static bool TypeToString(StringImpl& str, BfTypeDef* typeDef, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None);
 	static bool TypeToString(StringImpl& str, BfTypeDef* typeDef, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None);
 	static bool TypeEquals(BfType* typeA, BfType* typeB, BfType* selfType);
 	static bool TypeEquals(BfType* typeA, BfType* typeB, BfType* selfType);
 
 
-	static void GetProjectList(BfType* checkType, Array<BfProject*>* projectVector, int immutableLength);
+	template <typename T>
+	static void GetProjectList(BfType* checkType, T* projectList, int immutableLength)
+	{
+		if (checkType->IsBoxed())
+			GetProjectList(((BfBoxedType*)checkType)->mElementType, projectList, immutableLength);
+
+		BfTypeInstance* typeInst = checkType->ToTypeInstance();
+		if (typeInst != NULL)
+		{
+			auto genericTypeInst = typeInst->ToGenericTypeInstance();
+			if (genericTypeInst != NULL)
+			{
+				for (auto genericArg : genericTypeInst->mTypeGenericArguments)
+					GetProjectList(genericArg, projectList, immutableLength);
+			}
+
+			BfProject* bfProject = typeInst->mTypeDef->mProject;
+			if (!projectList->Contains(bfProject))
+			{
+				bool handled = false;
+				for (int idx = 0; idx < (int)projectList->size(); idx++)
+				{
+					auto checkProject = (*projectList)[idx];
+					bool isBetter = bfProject->ContainsReference(checkProject);
+					bool isWorse = checkProject->ContainsReference(bfProject);
+					if (isBetter == isWorse)
+						continue;
+					if (isBetter)
+					{
+						if (idx >= immutableLength)
+						{
+							// This is even more specific, so replace with this one
+							(*projectList)[idx] = bfProject;
+							handled = true;
+						}
+					}
+					else
+					{
+						// This is less specific, ignore
+						handled = true;
+					}
+					break;
+				}
+				if (!handled)
+				{
+					projectList->Add(bfProject);
+				}
+			}
+		}
+		else if (checkType->IsPointer())
+			GetProjectList(((BfPointerType*)checkType)->mElementType, projectList, immutableLength);
+		else if (checkType->IsRef())
+			GetProjectList(((BfPointerType*)checkType)->mElementType, projectList, immutableLength);
+		else if (checkType->IsSizedArray())
+			GetProjectList(((BfSizedArrayType*)checkType)->mElementType, projectList, immutableLength);
+		else if (checkType->IsMethodRef())
+			GetProjectList(((BfMethodRefType*)checkType)->mOwner, projectList, immutableLength);
+	}
 
 
 	static BfPrimitiveType* GetPrimitiveType(BfModule* module, BfTypeCode typeCode);
 	static BfPrimitiveType* GetPrimitiveType(BfModule* module, BfTypeCode typeCode);
 	static void PopulateType(BfModule* module, BfType* type);
 	static void PopulateType(BfModule* module, BfType* type);

+ 5 - 5
IDEHelper/Compiler/BfStmtEvaluator.cpp

@@ -1162,7 +1162,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
 	BfLocalVariable* localDef = new BfLocalVariable();
 	BfLocalVariable* localDef = new BfLocalVariable();
 	if (varDecl->mNameNode != NULL)
 	if (varDecl->mNameNode != NULL)
 	{
 	{
-		localDef->mName = varDecl->mNameNode->ToString();
+		varDecl->mNameNode->ToString(localDef->mName);
 		localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varDecl->mNameNode);
 		localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varDecl->mNameNode);
 	}
 	}
 	else
 	else
@@ -1773,7 +1773,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
 
 
 	BfLocalVariable* localDef = new BfLocalVariable();
 	BfLocalVariable* localDef = new BfLocalVariable();
 	if (varDecl->mNameNode != NULL)
 	if (varDecl->mNameNode != NULL)
-		localDef->mName = varDecl->mNameNode->ToString();
+		varDecl->mNameNode->ToString(localDef->mName);
 	localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varDecl->mNameNode);
 	localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varDecl->mNameNode);
 	localDef->mResolvedType = type;
 	localDef->mResolvedType = type;
 	localDef->mIsAssigned = true;	
 	localDef->mIsAssigned = true;	
@@ -1906,7 +1906,7 @@ void BfModule::HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl, Bf
 		bool initHandled = false;
 		bool initHandled = false;
 
 
 		BfLocalVariable* localDef = new BfLocalVariable();
 		BfLocalVariable* localDef = new BfLocalVariable();
-		localDef->mName = varNameNode->ToString();
+		varNameNode->ToString(localDef->mName);
 		localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varNameNode);		
 		localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varNameNode);		
 		localDef->mResolvedType = resolvedType;
 		localDef->mResolvedType = resolvedType;
 		localDef->mReadFromId = 0; // Don't give usage errors for binds
 		localDef->mReadFromId = 0; // Don't give usage errors for binds
@@ -2326,9 +2326,9 @@ BfTypedValue BfModule::TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVa
 	auto enumType = targetType->ToTypeInstance();
 	auto enumType = targetType->ToTypeInstance();
 	PopulateType(enumType);
 	PopulateType(enumType);
 
 
-	String enumCaseName;
+	StringT<128> enumCaseName;
 	if (nameNode != NULL)
 	if (nameNode != NULL)
-		enumCaseName = nameNode->ToString();
+		nameNode->ToString(enumCaseName);
 
 
 	auto tagType = GetPrimitiveType(BfTypeCode_Int32);
 	auto tagType = GetPrimitiveType(BfTypeCode_Int32);
 	if (enumVal.mType != enumType)
 	if (enumVal.mType != enumType)

+ 2 - 2
IDEHelper/IDEHelper.vcxproj

@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
     <ProjectConfiguration Include="Debug|Win32">
@@ -218,7 +218,7 @@
       <Optimization>MaxSpeed</Optimization>
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;IDEHELPER_EXPORTS;BFSYSLIB_DYNAMIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>BP_DISABLED;WIN32;NDEBUG;_WINDOWS;_USRDLL;IDEHELPER_EXPORTS;BFSYSLIB_DYNAMIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>../;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_8_0_1\llvm\include;..\extern\llvm_win64_8_0_1\include;..\extern\llvm-project_8_0_1\llvm\lib\Target;..\extern\llvm_win64_8_0_1\lib\Target\X86;..\extern\llvm-project_8_0_1\llvm\tools\clang\include;..\extern\curl\builds\libcurl-vc15-x64-release-static-zlib-static-ipv6-sspi-winssl\include</AdditionalIncludeDirectories>
       <AdditionalIncludeDirectories>../;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_8_0_1\llvm\include;..\extern\llvm_win64_8_0_1\include;..\extern\llvm-project_8_0_1\llvm\lib\Target;..\extern\llvm_win64_8_0_1\lib\Target\X86;..\extern\llvm-project_8_0_1\llvm\tools\clang\include;..\extern\curl\builds\libcurl-vc15-x64-release-static-zlib-static-ipv6-sspi-winssl\include</AdditionalIncludeDirectories>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <BufferSecurityCheck>false</BufferSecurityCheck>