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

Optimizations, switching CanImplicitlyCast method, new CPU rate checker

This commit is contained in:
Brian Fiete 2019-11-19 09:58:35 -08:00
parent 39fd8d2624
commit 098ad1ce55
25 changed files with 759 additions and 301 deletions

View file

@ -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;
} }

View file

@ -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:

View file

@ -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);
} }
} }

View file

@ -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;

View file

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

View file

@ -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)
{ {

View file

@ -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 }; LARGE_INTEGER largeVal = { 0 };
QueryPerformanceFrequency(&freq); QueryPerformanceFrequency(&largeVal);
return freq.QuadPart; 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)

View file

@ -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)

View file

@ -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
} }

View file

@ -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)
{
}
}; };

View file

@ -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);

View file

@ -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();

View file

@ -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> template <typename TKey, typename TAlloc = AllocatorCLib<TKey> >
class HashSet 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]; Entry* newEntries = (Entry*)rawAllocate(sizeof(Entry)*newSize);
//mEntries.CopyTo(newEntries, 0, 0, mCount);
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; rawDeallocate(mBuckets);
delete[] mEntries; 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]; mBuckets = (int_cosize*)rawAllocate(sizeof(int_cosize) * mAllocSize);
mEntries = new Entry[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; rawDeallocate(mBuckets);
delete[] mEntries; rawDeallocate(mEntries);
} }
HashSet& operator=(const HashSet& rhs) HashSet& operator=(const HashSet& rhs)

View file

@ -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);
} }
}; };
}*/ }

View file

@ -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; static int sCallIdx = 0;
// sCallIdx++; sCallIdx++;
// int callIdx = sCallIdx; int callIdx = sCallIdx;
// if (callIdx == 1557) if (callIdx == 1557)
// { {
// NOP; 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); convLeftValue = mModule->CastToValue(leftExpression, leftValue, intPtrType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_FromCompiler));
convRightValue = mModule->CastToValue(rightExpression, rightValue, intPtrType, BfCastFlags_Explicit); 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);

View file

@ -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;
} }

View file

@ -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);

View file

@ -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 += '@';

View file

@ -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; mIgnoreWarnings = false;
mHadIgnoredError = 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 // Need to box it
auto boxedType = CreateBoxedType(typedVal.mType); bool isBoxedType = (fromStructTypeInstance != NULL) && (toType->IsBoxed());
bool isBoxedType = (fromStructTypeInstance != NULL) && (toType->IsBoxed()) && (boxedType == toType);
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()) if (mBfIRBuilder->mIgnoreWrites)
{ return BfTypedValue(mBfIRBuilder->GetFakeVal(), (toType != NULL) ? toType : CreateBoxedType(typedVal.mType));
NOP;
} 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;

View file

@ -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; Array<BfLocalVariable*, AllocatorBump<BfLocalVariable*> > mLocals;
HashSet<BfLocalVarEntry> mLocalVarSet; 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 mSetIllegalSrcPosition;
bool mHadIgnoredError;
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);

View file

@ -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::DoCanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags)
bool BfModule::CanImplicitlyCast(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)) // if ((toUnderlying->IsSizedArray()) && (explicitCast))
// toUnderlying = toUnderlying->GetUnderlyingType(); // 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 (fromType->IsPointer())
// { // {
// if (toType == mContext->mBfObjectType) // if (toType == mContext->mBfObjectType)
// return true; // return true;
// return false; // return false;
// } // }
if (toType == mContext->mBfObjectType) if (toType == mContext->mBfObjectType)
return true; return true;
BfTypeInstance* fromStructTypeInstance = NULL; BfTypeInstance* fromStructTypeInstance = NULL;
fromStructTypeInstance = fromType->ToTypeInstance(); fromStructTypeInstance = fromType->ToTypeInstance();
if (fromStructTypeInstance == NULL) 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(); auto toTypeInstance = toType->ToTypeInstance();
// Need to box it // Need to box it
if (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance)) if (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance))
return true; 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 if (toType->mSize == 8) // int64
return true; return true;
else else
{ {
int64 minVal = -(1LL << (8 * toType->mSize - 1)); int64 minVal = -(1LL << (8 * toType->mSize - 1));
int64 maxVal = (1LL << (8 * toType->mSize - 1)) - 1; int64 maxVal = (1LL << (8 * toType->mSize - 1)) - 1;
if ((srcVal >= minVal) && (srcVal <= maxVal)) if ((srcVal >= minVal) && (srcVal <= maxVal))
return true; 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 ((!ignoreErrors) && (!typedVal.mType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
/*if ((!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 ((!ignoreErrors) && (!toType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
/*if ((!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->IsTypeInstance()) && (toType->IsTypeInstance()))
if ((typedVal.mType->IsObject() || (typedVal.mType->IsInterface())) && ((toType->IsObject() || (toType->IsInterface()))))
{ {
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)) if ((typedVal.mType->IsValueType()) && (toType->IsValueType()))
allowCast = true;
else if ((explicitCast) &&
((toType->IsInterface()) || (TypeIsSubTypeOf(toTypeInstance, fromTypeInstance))))
{ {
if (toType->IsObjectOrInterface()) bool allowCast = false;
if (TypeIsSubTypeOf(fromTypeInstance, toTypeInstance))
allowCast = true;
if (allowCast)
{ {
if ((castFlags & BfCastFlags_Unchecked) == 0) if (toType->IsValuelessType())
EmitDynamicCastCheck(typedVal, toType, true); return BfIRValue::sValueless;
} }
allowCast = true;
} }
if (allowCast) // ObjectInst|IFace -> object|IFace
return mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapType(toType)); 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 BfIRValue::sValueless;
return mBfIRBuilder->GetFakeVal();
} 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'"; if (!ignoreErrors)
Fail(StrFormat(errStr, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode); {
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 checkTypeInst = typeInstance;
auto checkTypeDef = typeInstance->mTypeDef; //auto checkTypeDef = typeInstance->mTypeDef;
auto checkCurTypeInst = mCurTypeInstance; // Only used for ReduceName bool omitNamespace = (typeNameFlags & BfTypeNameFlag_OmitNamespace) != 0;
BfTypeDef* checkCurTypeDef = NULL; if ((typeNameFlags & BfTypeNameFlag_ReduceName) != 0)
if (checkCurTypeInst != NULL)
checkCurTypeDef = checkCurTypeInst->mTypeDef;
std::function<void(BfTypeDef*, int)> _AddTypeName = [&](BfTypeDef* checkTypeDef, int depth)
{ {
if (depth > 0) for (auto& checkNamespace : mCurTypeInstance->mTypeDef->mNamespaceSearch)
{ {
if ((typeNameFlags & BfTypeNameFlag_OmitOuterType) != 0) if (checkNamespace == typeInstance->mTypeDef->mNamespace)
return; omitNamespace = true;
}
}
if ((typeNameFlags & BfTypeNameFlag_ReduceName) != 0) 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(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))
{
auto checkTypeInst = typeInstance;
auto outerTypeInst = GetOuterType(checkTypeInst);
if (outerTypeInst != NULL)
{
checkTypeInst = outerTypeInst;
auto checkTypeDef = checkTypeInst->mTypeDef;
auto checkCurTypeInst = mCurTypeInstance; // Only used for ReduceName
BfTypeDef* checkCurTypeDef = NULL;
if (checkCurTypeInst != NULL)
checkCurTypeDef = checkCurTypeInst->mTypeDef;
while (checkCurTypeDef->mNestDepth > checkTypeDef->mNestDepth)
{ {
auto outerTypeInst = GetOuterType(checkTypeInst); checkCurTypeInst = GetOuterType(checkCurTypeInst);
if (outerTypeInst == NULL) checkCurTypeDef = checkCurTypeInst->mTypeDef;
return; }
checkTypeInst = outerTypeInst;
while (checkCurTypeDef->mNestDepth > checkTypeDef->mNestDepth) while (checkTypeDef != NULL)
{
if (TypeIsSubTypeOf(checkCurTypeInst, checkTypeInst))
{ {
checkCurTypeInst = GetOuterType(checkCurTypeInst); endTypeDef = checkTypeDef;
checkCurTypeDef = checkCurTypeInst->mTypeDef; break;
} }
if (TypeIsSubTypeOf(checkCurTypeInst, checkTypeInst)) checkCurTypeInst = GetOuterType(checkCurTypeInst);
return; // Found outer type if (checkCurTypeInst == NULL)
break;
checkCurTypeDef = checkCurTypeInst->mTypeDef;
checkTypeInst = GetOuterType(checkTypeInst);
if (checkTypeInst == NULL)
break;
checkTypeDef = checkTypeInst->mTypeDef;
} }
} }
}
auto parentTypeDef = checkTypeDef->mOuterType; BfTypeDef* checkTypeDef = typeInstance->mTypeDef;
if (parentTypeDef != NULL) while (checkTypeDef != NULL)
{ {
_AddTypeName(parentTypeDef, depth + 1); 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())

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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>