diff --git a/BeefLibs/corlib/src/Diagnostics/Debug.bf b/BeefLibs/corlib/src/Diagnostics/Debug.bf
index b88b55a8..d4df7bd4 100644
--- a/BeefLibs/corlib/src/Diagnostics/Debug.bf
+++ b/BeefLibs/corlib/src/Diagnostics/Debug.bf
@@ -36,6 +36,8 @@ namespace System.Diagnostics
[CallingConvention(.Cdecl)]
static extern void Write(char8* str, int strLen);
+ [CallingConvention(.Cdecl)]
+ static extern void Write(int val);
public static void Write(String line)
{
diff --git a/BeefySysLib/BeefySysLib.vcxproj b/BeefySysLib/BeefySysLib.vcxproj
index aa1fb938..46f8d0c6 100644
--- a/BeefySysLib/BeefySysLib.vcxproj
+++ b/BeefySysLib/BeefySysLib.vcxproj
@@ -1932,6 +1932,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"
+
@@ -2159,6 +2160,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\"
+
diff --git a/BeefySysLib/BeefySysLib.vcxproj.filters b/BeefySysLib/BeefySysLib.vcxproj.filters
index 0b9db518..a4f7ebce 100644
--- a/BeefySysLib/BeefySysLib.vcxproj.filters
+++ b/BeefySysLib/BeefySysLib.vcxproj.filters
@@ -704,6 +704,9 @@
src\platform\win
+
+ src\util
+
@@ -1069,6 +1072,9 @@
src\platform\win
+
+ src\util
+
diff --git a/BeefySysLib/BeefySysLib_static.vcxproj b/BeefySysLib/BeefySysLib_static.vcxproj
index b65c738e..b7398576 100644
--- a/BeefySysLib/BeefySysLib_static.vcxproj
+++ b/BeefySysLib/BeefySysLib_static.vcxproj
@@ -868,6 +868,7 @@
+
@@ -1029,6 +1030,7 @@
+
diff --git a/BeefySysLib/BeefySysLib_static.vcxproj.filters b/BeefySysLib/BeefySysLib_static.vcxproj.filters
index 5bb87d3d..486d3602 100644
--- a/BeefySysLib/BeefySysLib_static.vcxproj.filters
+++ b/BeefySysLib/BeefySysLib_static.vcxproj.filters
@@ -569,6 +569,9 @@
src\util
+
+ src\util
+
@@ -871,6 +874,9 @@
src\util
+
+ src\util
+
diff --git a/BeefySysLib/platform/win/CrashCatcher.cpp b/BeefySysLib/platform/win/CrashCatcher.cpp
index 2d7ce4fd..0177eb57 100644
--- a/BeefySysLib/platform/win/CrashCatcher.cpp
+++ b/BeefySysLib/platform/win/CrashCatcher.cpp
@@ -1156,6 +1156,9 @@ void CrashCatcher::Crash(const StringImpl& str)
{
}*/
+
+ for (auto func : CrashCatcher::Get()->mCrashInfoFuncs)
+ func();
exit(1);
}
diff --git a/BeefySysLib/util/AllocDebug.h b/BeefySysLib/util/AllocDebug.h
index c0ce11d1..cf6bc8af 100644
--- a/BeefySysLib/util/AllocDebug.h
+++ b/BeefySysLib/util/AllocDebug.h
@@ -2,6 +2,8 @@
//#define BP_ALLOC_TRACK
+#include
+
#ifdef BF_PLATFORM_WINDOWS
#define _CRTDBG_MAP_ALLOC
@@ -87,4 +89,29 @@ void BpDump();
#endif
void* StompAlloc(int size);
-void StompFree(void* addr);
\ No newline at end of file
+void StompFree(void* addr);
+
+template
+class AllocatorStomp
+{
+public:
+ T* allocate(intptr_t count)
+ {
+ return (T*)StompAlloc((int)(sizeof(T) * count));
+ }
+
+ void deallocate(T* ptr)
+ {
+ StompFree(ptr);
+ }
+
+ void* rawAllocate(intptr_t size)
+ {
+ return StompAlloc((int)size);
+ }
+
+ void rawDeallocate(void* ptr)
+ {
+ StompFree(ptr);
+ }
+};
diff --git a/BeefySysLib/util/Heap.cpp b/BeefySysLib/util/Heap.cpp
new file mode 100644
index 00000000..2410a9d5
--- /dev/null
+++ b/BeefySysLib/util/Heap.cpp
@@ -0,0 +1,335 @@
+#include "Heap.h"
+#include "DLIList.h"
+
+USING_NS_BF;
+
+//////////////////////////////////////////////////////////////////////////
+
+#define CH_REL_TO_ABS(VAL) ((ChBlock*)((uint8*)mMetadata + (VAL)))
+#define CH_REL_TO_ABS(VAL) ((ChBlock*)((uint8*)mMetadata + (VAL)))
+#define CH_ABS_TO_REL(VAL) (int)((uint8*)(VAL) - (uint8*)mMetadata)
+
+enum ChBlockKind
+{
+ ChBlockKind_Bad = 0xBEEF0BAD,
+ ChBlockKind_Unused = 0xBEEF1212,
+ ChBlockKind_Used = 0xBEEF2323,
+ ChBlockKind_Merged = 0xBEEF3434,
+};
+
+struct ChBlock
+{
+ ContiguousHeap::AllocRef mPrev;
+ ContiguousHeap::AllocRef mNext;
+ int mSize;
+ ChBlockKind mKind;
+
+ ChBlock()
+ {
+ mPrev = -1;
+ mNext = -1;
+ mSize = 0;
+ mKind = ChBlockKind_Bad;
+ }
+};
+
+class ChList
+{
+public:
+ void* mMetadata;
+ int32 mHead;
+ int32 mTail;
+
+public:
+ ChList()
+ {
+ mHead = -1;
+ mTail = -1;
+ }
+
+ void Size()
+ {
+ int size = 0;
+ int checkNode = mHead;
+ while (checkNode != NULL)
+ {
+ size++;
+ checkNode = CH_REL_TO_ABS(checkNode)->mNext;
+ }
+ }
+
+ void PushBack(int node)
+ {
+ BF_ASSERT(CH_REL_TO_ABS(node)->mNext == -1);
+
+ if (mHead == -1)
+ mHead = node;
+ else
+ {
+ CH_REL_TO_ABS(mTail)->mNext = node;
+ CH_REL_TO_ABS(node)->mPrev = mTail;
+ }
+ mTail = node;
+ }
+
+ void AddAfter(int refNode, int newNode)
+ {
+ int32 prevNext = CH_REL_TO_ABS(refNode)->mNext;
+ CH_REL_TO_ABS(refNode)->mNext = newNode;
+ CH_REL_TO_ABS(newNode)->mPrev = refNode;
+ CH_REL_TO_ABS(newNode)->mNext = prevNext;
+ if (prevNext != -1)
+ CH_REL_TO_ABS(prevNext)->mPrev = newNode;
+ if (refNode == mTail)
+ mTail = newNode;
+ }
+
+ void Remove(int node)
+ {
+ if (CH_REL_TO_ABS(node)->mPrev == -1)
+ {
+ mHead = CH_REL_TO_ABS(node)->mNext;
+ if (mHead != -1)
+ CH_REL_TO_ABS(mHead)->mPrev = -1;
+ }
+ else
+ CH_REL_TO_ABS(CH_REL_TO_ABS(node)->mPrev)->mNext = CH_REL_TO_ABS(node)->mNext;
+
+ if (CH_REL_TO_ABS(node)->mNext == -1)
+ {
+ mTail = CH_REL_TO_ABS(node)->mPrev;
+ if (mTail != -1)
+ CH_REL_TO_ABS(mTail)->mNext = -1;
+ }
+ else
+ CH_REL_TO_ABS(CH_REL_TO_ABS(node)->mNext)->mPrev = CH_REL_TO_ABS(node)->mPrev;
+
+ CH_REL_TO_ABS(node)->mPrev = -1;
+ CH_REL_TO_ABS(node)->mNext = -1;
+ }
+
+ bool IsEmpty()
+ {
+ return mHead == -1;
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+ContiguousHeap::ContiguousHeap()
+{
+ mMetadata = NULL;
+ mMemorySize = 0;
+ mBlockDataOfs = 0;
+ mFreeIdx = 0;
+}
+
+ContiguousHeap::~ContiguousHeap()
+{
+ free(mMetadata);
+}
+
+void ContiguousHeap::Clear(int maxAllocSize)
+{
+ if (mBlockDataOfs == 0)
+ return;
+
+ mBlockDataOfs = 0;
+ mFreeList.Clear();
+ if ((mMemorySize != -1) && (mMemorySize > maxAllocSize))
+ {
+ free(mMetadata);
+ mMetadata = NULL;
+ mMemorySize = 0;
+ return;
+ }
+
+ auto blockList = (ChList*)mMetadata;
+ if (blockList->mHead != -1)
+ {
+ auto block = CH_REL_TO_ABS(blockList->mHead);
+ while (block != NULL)
+ {
+ block->mKind = ChBlockKind_Bad;
+ block = CH_REL_TO_ABS(block->mNext);
+ }
+ }
+ blockList->mHead = -1;
+ blockList->mTail = -1;
+}
+
+ContiguousHeap::AllocRef ContiguousHeap::Alloc(int size)
+{
+ if (size == 0)
+ return 0;
+
+ size = BF_ALIGN(size, 16);
+
+ auto blockList = (ChList*)mMetadata;
+
+ while (true)
+ {
+ for (int itr = 0; itr < (int)mFreeList.size(); itr++)
+ {
+ auto block = (ChBlock*)((uint8*)mMetadata + mFreeList[mFreeIdx]);
+
+ if (block->mKind == ChBlockKind_Merged)
+ {
+ itr--;
+ if (mFreeIdx >= mFreeList.mSize)
+ mFreeIdx = 0;
+ block->mKind = (ChBlockKind)0;
+ mFreeList.RemoveAtFast(mFreeIdx);
+ continue;
+ }
+
+ BF_ASSERT(block->mKind == ChBlockKind_Unused);
+
+ if (block->mSize >= size)
+ {
+ mFreeList.RemoveAtFast(mFreeIdx);
+ if (block->mSize >= size + 64)
+ {
+ // Split block
+ auto newBlock = new ((uint8*)block + size) ChBlock();
+ newBlock->mSize = block->mSize - size;
+ newBlock->mKind = ChBlockKind_Unused;
+ blockList->AddAfter(CH_ABS_TO_REL(block), CH_ABS_TO_REL(newBlock));
+ block->mSize = size;
+
+ mFreeList.Add(CH_ABS_TO_REL(newBlock));
+ }
+
+ block->mKind = ChBlockKind_Used;
+ return CH_ABS_TO_REL(block);
+ }
+
+ mFreeIdx = (mFreeIdx + 1) % mFreeList.mSize;
+ }
+
+ int wantSize = BF_MAX(mMemorySize + mMemorySize / 2, mMemorySize + BF_MAX(size, 64 * 1024));
+ mMetadata = realloc(mMetadata, wantSize);
+
+ memset((uint8*)mMetadata + mMemorySize, 0, wantSize - mMemorySize);
+
+ blockList = (ChList*)mMetadata;
+ mMemorySize = wantSize;
+
+ if (mBlockDataOfs == 0)
+ {
+ blockList = new (mMetadata) ChList();
+ mBlockDataOfs = sizeof(ChList);
+ }
+ blockList->mMetadata = mMetadata;
+
+ auto block = new ((uint8*)mMetadata + mBlockDataOfs) ChBlock();
+ block->mSize = mMemorySize - mBlockDataOfs;
+ block->mKind = ChBlockKind_Unused;
+ mBlockDataOfs += block->mSize;
+ blockList->PushBack(CH_ABS_TO_REL(block));
+
+ mFreeList.Add(CH_ABS_TO_REL(block));
+ }
+}
+
+bool ContiguousHeap::Free(AllocRef ref)
+{
+ if ((ref < 0) || (ref > mMemorySize - sizeof(ChBlock)))
+ return false;
+
+ auto blockList = (ChList*)mMetadata;
+ auto block = CH_REL_TO_ABS(ref);
+
+ if (block->mKind != ChBlockKind_Used)
+ return false;
+
+ int headAccSize = 0;
+ auto mergeHead = block;
+ while (mergeHead->mPrev != -1)
+ {
+ auto checkBlock = CH_REL_TO_ABS(mergeHead->mPrev);
+ if (checkBlock->mKind != ChBlockKind_Unused)
+ break;
+ headAccSize += mergeHead->mSize;
+ // Mark PREVIOUS as merged, only leave the current alive
+ mergeHead->mKind = ChBlockKind_Merged;
+ blockList->Remove(CH_ABS_TO_REL(mergeHead));
+ mergeHead = checkBlock;
+ }
+
+ int tailAccSize = 0;
+ if (mergeHead->mNext != -1)
+ {
+ auto mergeTail = CH_REL_TO_ABS(mergeHead->mNext);
+ while (mergeTail->mKind == ChBlockKind_Unused)
+ {
+ ChBlock* nextBlock = NULL;
+ if (mergeTail->mNext != -1)
+ nextBlock = CH_REL_TO_ABS(mergeTail->mNext);
+ tailAccSize += mergeTail->mSize;
+ mergeTail->mKind = ChBlockKind_Merged;
+ blockList->Remove(CH_ABS_TO_REL(mergeTail));
+ if (nextBlock == NULL)
+ break;
+ mergeTail = nextBlock;
+ }
+ }
+
+ mergeHead->mSize += tailAccSize + headAccSize;
+ if ((mergeHead->mKind != ChBlockKind_Unused) && (mergeHead->mKind != ChBlockKind_Merged))
+ {
+ // If it were MERGED that means it's still in the free list
+ mFreeList.Add(CH_ABS_TO_REL(mergeHead));
+ }
+ mergeHead->mKind = ChBlockKind_Unused;
+ return true;
+}
+
+void ContiguousHeap::DebugDump()
+{
+ String str = "Heap Dump:\n";
+
+ auto blockList = (ChList*)mMetadata;
+
+ if (blockList->mHead != -1)
+ {
+ int totalSize = 0;
+
+ auto block = CH_REL_TO_ABS(blockList->mHead);
+ while (block != NULL)
+ {
+ str += StrFormat("@%d: %d ", CH_ABS_TO_REL(block), block->mSize);
+ switch (block->mKind)
+ {
+ case ChBlockKind_Unused:
+ str += "Unused";
+ break;
+ case ChBlockKind_Used:
+ str += "Used";
+ break;
+ case ChBlockKind_Merged:
+ str += "Merged";
+ break;
+ default:
+ str += "??????";
+ }
+
+ str += "\n";
+
+ totalSize += block->mSize;
+
+ if (block->mNext == -1)
+ break;
+ block = CH_REL_TO_ABS(block->mNext);
+ }
+
+ str += StrFormat("Sum: %d Allocated: %d\n", totalSize, mMemorySize);
+ }
+
+ str += "\nFree List:\n";
+ for (auto val : mFreeList)
+ str += StrFormat("@%d\n", val);
+ str += "\n";
+
+ OutputDebugStrF(str.c_str());
+}
diff --git a/BeefySysLib/util/Heap.h b/BeefySysLib/util/Heap.h
new file mode 100644
index 00000000..d1a8cf57
--- /dev/null
+++ b/BeefySysLib/util/Heap.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "../Common.h"
+
+NS_BF_BEGIN
+
+class ContiguousHeap
+{
+public:
+ typedef int AllocRef;
+
+public:
+ void* mMetadata;
+
+ int mMemorySize;
+ int mBlockDataOfs;
+ Array mFreeList;
+ int mFreeIdx;
+
+public:
+ ContiguousHeap();
+ virtual ~ContiguousHeap();
+
+ void Clear(int maxAllocSize = -1);
+
+ AllocRef Alloc(int size);
+ bool Free(AllocRef ref);
+
+ void DebugDump();
+};
+
+NS_BF_END
\ No newline at end of file
diff --git a/IDE/src/Compiler/BfPassInstance.bf b/IDE/src/Compiler/BfPassInstance.bf
index 49e22c40..0e98d30e 100644
--- a/IDE/src/Compiler/BfPassInstance.bf
+++ b/IDE/src/Compiler/BfPassInstance.bf
@@ -141,7 +141,7 @@ namespace IDE.Compiler
{
char8* fileName = null;
char8* errorStr = BfPassInstance_Error_GetMoreInfoData(mNativeBfPassInstance, errorIdx, moreInfoIdx, out fileName, out bfError.mSrcStart, out bfError.mSrcEnd,
- getLine ? &bfError.mLine : null, getLine ? &bfError.mColumn : null);
+ &bfError.mLine, &bfError.mColumn);
Debug.Assert(bfError.mFilePath == null);
if (fileName != null)
bfError.mFilePath = new String(fileName);
diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf
index 2d528b57..aa492127 100644
--- a/IDE/src/IDEApp.bf
+++ b/IDE/src/IDEApp.bf
@@ -1054,13 +1054,25 @@ namespace IDE
if (var sourceViewPanel = GetActiveSourceViewPanel(true))
sourceViewPanel.RecordHistoryLocation();
- int32 charIdx = int32.Parse(cmds[2]).GetValueOrDefault();
+ StringView loc = cmds[2];
+ int32 charIdx = int32.Parse(loc).GetValueOrDefault();
if (charIdx < 0)
return;
var sourceViewPanel = ShowSourceFile(cmds[1], null, SourceShowType.Temp);
if (sourceViewPanel == null)
return;
var editWidgetContent = sourceViewPanel.mEditWidget.mEditWidgetContent;
+
+ int colonIdx = loc.IndexOf(':');
+ if (colonIdx != -1)
+ {
+ int line = int.Parse(loc.Substring(0, colonIdx)).GetValueOrDefault();
+ int column = int.Parse(loc.Substring(colonIdx + 1)).GetValueOrDefault();
+ charIdx = (.)editWidgetContent.GetTextIdx(line, column);
+ }
+ if (charIdx < 0)
+ return;
+
int line;
int lineChar;
editWidgetContent.GetLineCharAtIdx(charIdx, out line, out lineChar);
diff --git a/IDE/src/ui/SourceViewPanel.bf b/IDE/src/ui/SourceViewPanel.bf
index 744bc21b..bcd17036 100644
--- a/IDE/src/ui/SourceViewPanel.bf
+++ b/IDE/src/ui/SourceViewPanel.bf
@@ -4966,7 +4966,12 @@ namespace IDE.ui
{
for (var moreInfo in bestError.mMoreInfo)
{
- showMouseoverString.AppendF("\n@{0}\t{1}\t{2}", moreInfo.mFilePath, moreInfo.mSrcStart, moreInfo.mError);
+ if ((moreInfo.mSrcStart == -1) && (moreInfo.mSrcStart == -1) && (moreInfo.mLine != -1))
+ {
+ showMouseoverString.AppendF("\n@{}\t{}:{}\t{}", moreInfo.mFilePath, moreInfo.mLine, moreInfo.mColumn, moreInfo.mError);
+ }
+ else
+ showMouseoverString.AppendF("\n@{0}\t{1}\t{2}", moreInfo.mFilePath, moreInfo.mSrcStart, moreInfo.mError);
}
}
}
diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp
index fc2ff4e9..240e0c5c 100644
--- a/IDEHelper/Backend/BeIRCodeGen.cpp
+++ b/IDEHelper/Backend/BeIRCodeGen.cpp
@@ -889,6 +889,9 @@ void BeIRCodeGen::Read(BeValue*& beValue)
beValue = result.mBeValue;
BE_MEM_END("ParamType_StreamId");
}
+
+ if (beValue != NULL)
+ beValue->mRefCount++;
}
void BeIRCodeGen::Read(BeConstant*& llvmConstant)
@@ -922,6 +925,8 @@ void BeIRCodeGen::Read(BeFunction*& beFunc)
BF_ASSERT(BeValueDynCast(result.mBeValue));
beFunc = (BeFunction*)result.mBeValue;
BE_MEM_END("BeFunction");
+
+ beFunc->mRefCount++;
}
void BeIRCodeGen::Read(BeBlock*& beBlock)
@@ -932,6 +937,8 @@ void BeIRCodeGen::Read(BeBlock*& beBlock)
BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Block);
beBlock = (BeBlock*)result.mBeType;
BE_MEM_END("BeBlock");
+
+ beBlock->mRefCount++;
}
void BeIRCodeGen::Read(BeMDNode*& llvmMD)
@@ -947,6 +954,8 @@ void BeIRCodeGen::Read(BeMDNode*& llvmMD)
BF_ASSERT(result.mKind == BeIRCodeGenEntryKind_Metadata);
llvmMD = result.mBeMetadata;
BE_MEM_END("BeMDNode");
+
+ llvmMD->mRefCount++;
}
void BeIRCodeGen::HandleNextCmd()
@@ -2522,9 +2531,62 @@ void BeIRCodeGen::HandleNextCmd()
auto inst = mBeModule->AllocInst();
inst->mValue = val;
- SetResult(curId, mBeModule->GetInsertBlock());
+ SetResult(curId, mBeModule->GetInsertBlock());
}
break;
+ case BfIRCmd_ConstEval_GetBfType:
+ {
+ CMD_PARAM(int32, typeId);
+ CMD_PARAM(BeType*, resultType);
+
+ auto inst = mBeModule->AllocInst();
+ inst->mTypeId = typeId;
+ inst->mResultType = resultType;
+ SetResult(curId, inst);
+ }
+ break;
+ case BfIRCmd_ConstEval_DynamicCastCheck:
+ {
+ CMD_PARAM(BeValue*, value);
+ CMD_PARAM(int32, typeId);
+ CMD_PARAM(BeType*, resultType);
+
+ auto inst = mBeModule->AllocInst();
+ inst->mValue = value;
+ inst->mTypeId = typeId;
+ inst->mResultType = resultType;
+ SetResult(curId, inst);
+ }
+ break;
+ case BfIRCmd_ConstEval_GetVirtualFunc:
+ {
+ CMD_PARAM(BeValue*, value);
+ CMD_PARAM(int32, virtualTableIdx);
+ CMD_PARAM(BeType*, resultType);
+
+ auto inst = mBeModule->AllocInst();
+ inst->mValue = value;
+ inst->mVirtualTableIdx = virtualTableIdx;
+ inst->mResultType = resultType;
+ SetResult(curId, inst);
+ }
+ break;
+ case BfIRCmd_ConstEval_GetInterfaceFunc:
+ {
+ CMD_PARAM(BeValue*, value);
+ CMD_PARAM(int32, ifaceTypeId);
+ CMD_PARAM(int32, virtualTableIdx);
+ CMD_PARAM(BeType*, resultType);
+
+ auto inst = mBeModule->AllocInst();
+ inst->mValue = value;
+ inst->mIFaceTypeId = ifaceTypeId;
+ inst->mVirtualTableIdx = virtualTableIdx;
+ inst->mResultType = resultType;
+ SetResult(curId, inst);
+ }
+ break;
+
case BfIRCmd_DbgInit:
{
/*mDIBuilder = new BeDIBuilder(*mBeModule); */
diff --git a/IDEHelper/Backend/BeModule.cpp b/IDEHelper/Backend/BeModule.cpp
index b52fadbe..2f337cc8 100644
--- a/IDEHelper/Backend/BeModule.cpp
+++ b/IDEHelper/Backend/BeModule.cpp
@@ -1723,6 +1723,13 @@ void BeDbgFile::ToString(String& str)
str = '\\';
}
+void BeDbgFile::GetFilePath(String& outStr)
+{
+ outStr.Append(mDirectory);
+ outStr.Append(DIR_SEP_CHAR);
+ outStr.Append(mFileName);
+}
+
//////////////////////////////////////////////////////////////////////////
BeModule::BeModule(const StringImpl& moduleName, BeContext* context)
@@ -2442,6 +2449,10 @@ String BeModule::ToString(BeFunction* wantFunc)
}
}
break;
+ DISPLAY_INST1(BeConstEvalGetType, "ConstEvalGetType", mTypeId);
+ DISPLAY_INST2(BeConstEvalDynamicCastCheck, "ConstEvalDynamicCastCheck", mValue, mTypeId);
+ DISPLAY_INST2(BeConstEvalGetVirtualFunc, "ConstEvalGetVirtualFunc", mValue, mVirtualTableIdx);
+ DISPLAY_INST3(BeConstEvalGetInterfaceFunc, "ConstEvalGetInterfaceFunc", mValue, mIFaceTypeId, mVirtualTableIdx);
default:
BF_FATAL("Notimpl");
str += "";
diff --git a/IDEHelper/Backend/BeModule.h b/IDEHelper/Backend/BeModule.h
index e24465ac..88e7ecf1 100644
--- a/IDEHelper/Backend/BeModule.h
+++ b/IDEHelper/Backend/BeModule.h
@@ -208,10 +208,12 @@ public:
#ifdef _DEBUG
bool mLifetimeEnded;
bool mWasRemoved;
+ int mRefCount;
BeValue()
{
mLifetimeEnded = false;
mWasRemoved = false;
+ mRefCount = 0;
}
#endif
@@ -264,6 +266,16 @@ T* BeValueDynCast(BeValue* value)
return (T*)result;
}
+template
+T* BeValueDynCastExact(BeValue* value)
+{
+ if (value == NULL)
+ return NULL;
+ if (value->GetTypeId() != T::TypeId)
+ return NULL;
+ return (T*)value;
+}
+
class BeBlock;
class BeInst;
class BeModule;
@@ -1320,6 +1332,106 @@ public:
}
};
+//////////////////////////////////////////////////////////////////////////
+
+class BeConstEvalGetType : public BeInst
+{
+public:
+ BE_VALUE_TYPE(BeConstEvalGetType, BeInst);
+
+public:
+ int mTypeId;
+ BeType* mResultType;
+
+public:
+ virtual BeType* GetType() override
+ {
+ return mResultType;
+ }
+
+ virtual void HashInst(BeHashContext& hashCtx) override
+ {
+ hashCtx.Mixin(TypeId);
+ hashCtx.Mixin(mTypeId);
+ }
+};
+
+class BeConstEvalDynamicCastCheck : public BeInst
+{
+public:
+ BE_VALUE_TYPE(BeConstEvalDynamicCastCheck, BeInst);
+
+public:
+ BeValue* mValue;
+ int mTypeId;
+ BeType* mResultType;
+
+public:
+ virtual BeType* GetType() override
+ {
+ return mResultType;
+ }
+
+ virtual void HashInst(BeHashContext& hashCtx) override
+ {
+ hashCtx.Mixin(TypeId);
+ mValue->HashReference(hashCtx);
+ hashCtx.Mixin(mTypeId);
+ }
+};
+
+class BeConstEvalGetVirtualFunc : public BeInst
+{
+public:
+ BE_VALUE_TYPE(BeConstEvalGetVirtualFunc, BeInst);
+
+public:
+ BeValue* mValue;
+ int mVirtualTableIdx;
+ BeType* mResultType;
+
+public:
+ virtual BeType* GetType() override
+ {
+ return mResultType;
+ }
+
+ virtual void HashInst(BeHashContext& hashCtx) override
+ {
+ hashCtx.Mixin(TypeId);
+ mValue->HashReference(hashCtx);
+ hashCtx.Mixin(mVirtualTableIdx);
+ }
+};
+
+class BeConstEvalGetInterfaceFunc : public BeInst
+{
+public:
+ BE_VALUE_TYPE(BeConstEvalGetInterfaceFunc, BeInst);
+
+public:
+ BeValue* mValue;
+ int mIFaceTypeId;
+ int mVirtualTableIdx;
+ BeType* mResultType;
+
+public:
+ virtual BeType* GetType() override
+ {
+ return mResultType;
+ }
+
+ virtual void HashInst(BeHashContext& hashCtx) override
+ {
+ hashCtx.Mixin(TypeId);
+ mValue->HashReference(hashCtx);
+ hashCtx.Mixin(mIFaceTypeId);
+ hashCtx.Mixin(mVirtualTableIdx);
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+
class BeArgument : public BeValue
{
public:
@@ -2007,6 +2119,7 @@ public:
int mIdx;
void ToString(String& str);
+ void GetFilePath(String& outStr);
virtual void HashContent(BeHashContext& hashCtx) override
{
@@ -2175,6 +2288,8 @@ public:
BeRetInst* CreateRet(BeValue* value);
BeCallInst* CreateCall(BeValue* func, const SizedArrayImpl& args);
+
+
BeConstant* GetConstant(BeType* type, double floatVal);
BeConstant* GetConstant(BeType* type, int64 intVal);
BeConstant* GetConstant(BeType* type, bool boolVal);
diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp
index 5ffa7139..cc4d6def 100644
--- a/IDEHelper/Compiler/BfCompiler.cpp
+++ b/IDEHelper/Compiler/BfCompiler.cpp
@@ -406,6 +406,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mGenericIRefEnumeratorTypeDef = NULL;
mInlineAttributeTypeDef = NULL;
mInternalTypeDef = NULL;
+ mDiagnosticsDebugTypeDef = NULL;
mIDisposableTypeDef = NULL;
mIPrintableTypeDef = NULL;
mIHashableTypeDef = NULL;
@@ -452,11 +453,12 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
BfCompiler::~BfCompiler()
{
+ delete mCEMachine;
+ mCEMachine = NULL;
delete mContext;
delete mHotData;
delete mHotState;
- delete mHotResolveData;
- delete mCEMachine;
+ delete mHotResolveData;
}
bool BfCompiler::IsTypeAccessible(BfType* checkType, BfProject* curProject)
@@ -6580,6 +6582,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mGenericIRefEnumeratorTypeDef = _GetRequiredType("System.Collections.IRefEnumerator", 1);
mInlineAttributeTypeDef = _GetRequiredType("System.InlineAttribute");
mInternalTypeDef = _GetRequiredType("System.Internal");
+ mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug");
mIDisposableTypeDef = _GetRequiredType("System.IDisposable");
mIPrintableTypeDef = _GetRequiredType("System.IPrintable");
mIHashableTypeDef = _GetRequiredType("System.IHashable");
diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h
index 0a9228fc..24bd2211 100644
--- a/IDEHelper/Compiler/BfCompiler.h
+++ b/IDEHelper/Compiler/BfCompiler.h
@@ -356,6 +356,7 @@ public:
BfTypeDef* mGenericIRefEnumeratorTypeDef;
BfTypeDef* mInternalTypeDef;
+ BfTypeDef* mDiagnosticsDebugTypeDef;
BfTypeDef* mIDisposableTypeDef;
BfTypeDef* mIPrintableTypeDef;
BfTypeDef* mIHashableTypeDef;
diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp
index 9b08023b..9c4f7454 100644
--- a/IDEHelper/Compiler/BfContext.cpp
+++ b/IDEHelper/Compiler/BfContext.cpp
@@ -2756,12 +2756,17 @@ void BfContext::Cleanup()
// Can't clean up LLVM types, they are allocated with a bump allocator
RemoveInvalidFailTypes();
+ // Clean up deleted BfTypes
+ // These need to get deleted before the modules because we access mModule in the MethodInstance dtors
+ for (auto type : mTypeGraveyard)
+ {
+ BF_ASSERT(type->mRebuildFlags & BfTypeRebuildFlag_Deleted);
+ delete type;
+ }
+ mTypeGraveyard.Clear();
+
for (auto module : mDeletingModules)
{
-// auto itr = std::find(mFinishedModuleWorkList.begin(), mFinishedModuleWorkList.end(), module);
-// if (itr != mFinishedModuleWorkList.end())
-// mFinishedModuleWorkList.erase(itr);
-
int idx = (int)mFinishedModuleWorkList.IndexOf(module);
if (idx != -1)
mFinishedModuleWorkList.RemoveAt(idx);
@@ -2773,14 +2778,7 @@ void BfContext::Cleanup()
delete module;
}
mDeletingModules.Clear();
-
- // Clean up deleted BfTypes
- for (auto type : mTypeGraveyard)
- {
- BF_ASSERT(type->mRebuildFlags & BfTypeRebuildFlag_Deleted);
- delete type;
- }
- mTypeGraveyard.Clear();
+
for (auto typeDef : mTypeDefGraveyard)
delete typeDef;
mTypeDefGraveyard.Clear();
diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp
index f36ab0b4..21bcd855 100644
--- a/IDEHelper/Compiler/BfExprEvaluator.cpp
+++ b/IDEHelper/Compiler/BfExprEvaluator.cpp
@@ -5025,18 +5025,29 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
if (methodInstance->mMethodInstanceGroup->mOwner->IsInterface())
{
- // IFace dispatch
- auto ifaceTypeInst = methodInstance->mMethodInstanceGroup->mOwner;
- BfIRValue slotOfs = mModule->GetInterfaceSlotNum(methodInstance->mMethodInstanceGroup->mOwner);
+ if (mModule->mIsConstModule)
+ {
+ funcCallInst = mModule->mBfIRBuilder->ConstEval_GetInterfaceFunc(irArgs[0], methodInstance->mMethodInstanceGroup->mOwner->mTypeId, methodInstance->mVirtualTableIdx, funcPtrType1);
+ }
+ else
+ {
+ // IFace dispatch
+ auto ifaceTypeInst = methodInstance->mMethodInstanceGroup->mOwner;
+ BfIRValue slotOfs = mModule->GetInterfaceSlotNum(methodInstance->mMethodInstanceGroup->mOwner);
- auto vDataPtrPtr = mModule->mBfIRBuilder->CreateBitCast(irArgs[0], funcPtrType4);
- auto vDataPtr = mModule->FixClassVData(mModule->mBfIRBuilder->CreateLoad(vDataPtrPtr/*, "vtable"*/));
+ auto vDataPtrPtr = mModule->mBfIRBuilder->CreateBitCast(irArgs[0], funcPtrType4);
+ auto vDataPtr = mModule->FixClassVData(mModule->mBfIRBuilder->CreateLoad(vDataPtrPtr/*, "vtable"*/));
- auto ifacePtrPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(vDataPtr, slotOfs/*, "iface"*/);
- auto ifacePtr = mModule->mBfIRBuilder->CreateLoad(ifacePtrPtr);
+ auto ifacePtrPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(vDataPtr, slotOfs/*, "iface"*/);
+ auto ifacePtr = mModule->mBfIRBuilder->CreateLoad(ifacePtrPtr);
- auto funcPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(ifacePtr, methodInstance->mVirtualTableIdx/*, "vfn"*/);
- funcCallInst = mModule->mBfIRBuilder->CreateLoad(funcPtr);
+ auto funcPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(ifacePtr, methodInstance->mVirtualTableIdx/*, "vfn"*/);
+ funcCallInst = mModule->mBfIRBuilder->CreateLoad(funcPtr);
+ }
+ }
+ else if (mModule->mIsConstModule)
+ {
+ funcCallInst = mModule->mBfIRBuilder->ConstEval_GetVirtualFunc(irArgs[0], methodInstance->mVirtualTableIdx, funcPtrType1);
}
else
{
@@ -6435,7 +6446,7 @@ SplatArgs(lookupVal, irArgs);
if (!argValue)
{
- if ((argValues[argExprIdx].mArgFlags & BfArgFlag_StringInterpolateArg) != 0)
+ if ((argExprIdx < (int)argValues.size()) && ((argValues[argExprIdx].mArgFlags & BfArgFlag_StringInterpolateArg) != 0))
{
BfAstNode* errorRef = NULL;
int checkIdx = argExprIdx - 1;
@@ -12761,7 +12772,8 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
}
// Actually leave it alone?
- if ((isUninit) && (mModule->IsOptimized()))
+ if ((isUninit) &&
+ ((mModule->IsOptimized()) || (mModule->mIsConstModule) || (mModule->mBfIRBuilder->mIgnoreWrites)))
return;
bool doClear = true;
@@ -18223,7 +18235,8 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
}
}
}
- else if ((mModule->HasCompiledOutput()) && (wantsChecks))
+ else if (((mModule->HasCompiledOutput()) || (mModule->mIsConstModule)) &&
+ (wantsChecks))
{
if (checkedKind == BfCheckedKind_NotSet)
checkedKind = mModule->GetDefaultCheckedKind();
@@ -18254,6 +18267,9 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
OutputDebugStrF("-OOB %d %d\n", oobFunc.mFunc.mId, oobFunc.mFunc.mFlags);
}*/
+ if (mModule->mIsConstModule)
+ mModule->mCompiler->mCEMachine->QueueMethod(oobFunc.mMethodInstance, oobFunc.mFunc);
+
SizedArray args;
args.push_back(mModule->GetConstValue(0));
mModule->mBfIRBuilder->CreateCall(oobFunc.mFunc, args);
diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp
index 4bb61d26..c575b170 100644
--- a/IDEHelper/Compiler/BfIRBuilder.cpp
+++ b/IDEHelper/Compiler/BfIRBuilder.cpp
@@ -3117,6 +3117,7 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDbgDefine)
auto& fieldInst = boxedType->mFieldInstances.back();
auto elementType = fieldInst.mResolvedType;
+ populateModule->PopulateType(elementType, BfPopulateType_Data);
if (!elementType->IsValuelessType())
{
@@ -3872,8 +3873,20 @@ BfIRValue BfIRBuilder::CreateMul(BfIRValue lhs, BfIRValue rhs)
BfIRValue BfIRBuilder::CreateDiv(BfIRValue lhs, BfIRValue rhs, bool isSigned)
{
if ((lhs.IsConst()) && (rhs.IsConst()))
- {
- BINOP_APPLY(lhs, rhs, /);
+ {
+ auto constLHS = GetConstantById(lhs.mId);
+ auto constRHS = GetConstantById(rhs.mId);
+
+ if ((constLHS->mTypeCode == BfTypeCode_Float) || (constLHS->mTypeCode == BfTypeCode_Double))
+ {
+ double fVal = constLHS->mDouble / constRHS->mDouble;
+ return CreateConst(constLHS->mTypeCode, fVal);
+ }
+
+ if (constRHS->mInt64 != 0)
+ {
+ INT_BINOP_APPLY(constLHS, constRHS, /);
+ }
}
auto retVal = WriteCmd(isSigned ? BfIRCmd_SDiv : BfIRCmd_UDiv, lhs, rhs);
@@ -3887,10 +3900,17 @@ BfIRValue BfIRBuilder::CreateRem(BfIRValue lhs, BfIRValue rhs, bool isSigned)
{
auto constLHS = GetConstantById(lhs.mId);
auto constRHS = GetConstantById(rhs.mId);
- INT_BINOP_APPLY(constLHS, constRHS, %);
- double fVal = fmod(constLHS->mDouble, constRHS->mDouble);
- return CreateConst(constLHS->mTypeCode, fVal);
+ if ((constLHS->mTypeCode == BfTypeCode_Float) || (constLHS->mTypeCode == BfTypeCode_Double))
+ {
+ double fVal = fmod(constLHS->mDouble, constRHS->mDouble);
+ return CreateConst(constLHS->mTypeCode, fVal);
+ }
+
+ if (constRHS->mInt64 != 0)
+ {
+ INT_BINOP_APPLY(constLHS, constRHS, %);
+ }
}
auto retVal = WriteCmd(isSigned ? BfIRCmd_SRem : BfIRCmd_URem, lhs, rhs);
@@ -4779,6 +4799,34 @@ void BfIRBuilder::Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage)
NEW_CMD_INSERTED;
}
+BfIRValue BfIRBuilder::ConstEval_GetBfType(int typeId, BfIRType resultType)
+{
+ BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_GetBfType, typeId, resultType);
+ NEW_CMD_INSERTED;
+ return retVal;
+}
+
+BfIRValue BfIRBuilder::ConstEval_DynamicCastCheck(BfIRValue value, int typeId, BfIRType resultType)
+{
+ BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_DynamicCastCheck, value, typeId, resultType);
+ NEW_CMD_INSERTED;
+ return retVal;
+}
+
+BfIRValue BfIRBuilder::ConstEval_GetVirtualFunc(BfIRValue value, int virtualTableId, BfIRType resultType)
+{
+ BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_GetVirtualFunc, value, virtualTableId, resultType);
+ NEW_CMD_INSERTED;
+ return retVal;
+}
+
+BfIRValue BfIRBuilder::ConstEval_GetInterfaceFunc(BfIRValue value, int typeId, int virtualTableId, BfIRType resultType)
+{
+ BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_GetInterfaceFunc, value, typeId, virtualTableId, resultType);
+ NEW_CMD_INSERTED;
+ return retVal;
+}
+
void BfIRBuilder::SaveDebugLocation()
{
if (!mIgnoreWrites)
diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h
index 4482e838..93d6b732 100644
--- a/IDEHelper/Compiler/BfIRBuilder.h
+++ b/IDEHelper/Compiler/BfIRBuilder.h
@@ -281,6 +281,11 @@ enum BfIRCmd : uint8
BfIRCmd_Func_SafeRename,
BfIRCmd_Func_SetLinkage,
+ BfIRCmd_ConstEval_GetBfType,
+ BfIRCmd_ConstEval_DynamicCastCheck,
+ BfIRCmd_ConstEval_GetVirtualFunc,
+ BfIRCmd_ConstEval_GetInterfaceFunc,
+
BfIRCmd_SaveDebugLocation,
BfIRCmd_RestoreDebugLocation,
BfIRCmd_DupDebugLocation,
@@ -1224,6 +1229,11 @@ public:
void Func_SafeRename(BfIRFunction func);
void Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage);
+ BfIRValue ConstEval_GetBfType(int typeId, BfIRType resultType);
+ BfIRValue ConstEval_DynamicCastCheck(BfIRValue value, int typeId, BfIRType resultType);
+ BfIRValue ConstEval_GetVirtualFunc(BfIRValue value, int virtualTableId, BfIRType resultType);
+ BfIRValue ConstEval_GetInterfaceFunc(BfIRValue value, int typeId, int virtualTableId, BfIRType resultType);
+
void SaveDebugLocation();
void RestoreDebugLocation();
void DupDebugLocation();
diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp
index f7917903..048c58a0 100644
--- a/IDEHelper/Compiler/BfModule.cpp
+++ b/IDEHelper/Compiler/BfModule.cpp
@@ -24,6 +24,7 @@
#include "BfIRCodeGen.h"
#include "BfDefBuilder.h"
#include "BfDeferEvalChecker.h"
+#include "CeMachine.h"
#include
#include
@@ -1532,7 +1533,7 @@ BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId,
auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize;
typeValueParams.clear();
- typeValueParams.push_back(objData);
+ typeValueParams.push_back(objData);
if (lenByteCount == 4)
{
typeValueParams.push_back(GetConstValue32((int)str.length())); // mLength
@@ -1928,8 +1929,7 @@ void BfModule::AddStackAlloc(BfTypedValue val, BfIRValue arraySize, BfAstNode* r
//TODO: In the future we could be smarter about statically determining that our value hasn't escaped and eliding this
if (mayEscape)
{
-
- if ((!IsOptimized()) && (!val.mType->IsValuelessType()) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly))
+ if ((!IsOptimized()) && (!mIsConstModule) && (!val.mType->IsValuelessType()) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly))
{
auto nullPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
bool isDyn = mCurMethodState->mCurScope->IsDyn(scopeData);
@@ -1945,7 +1945,10 @@ void BfModule::AddStackAlloc(BfTypedValue val, BfIRValue arraySize, BfAstNode* r
else
{
SizedArray llvmArgs;
- llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(nullPtrType)));
+ if (IsTargetingBeefBackend())
+ llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(nullPtrType)));
+ else
+ llvmArgs.push_back(val.mValue);
llvmArgs.push_back(GetConstValue(val.mType->mSize));
llvmArgs.push_back(GetConstValue32(val.mType->mAlign));
if (arraySize)
@@ -2029,7 +2032,7 @@ bool BfModule::TryLocalVariableInit(BfLocalVariable* localVar)
if (!fieldDef->mDeclaringType->IsExtension())
return false;
- if ((fieldInstance.mDataIdx != -1) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly))
+ if ((fieldInstance.mDataIdx != -1) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly) && (!mIsConstModule))
{
auto curInsertBlock = mBfIRBuilder->GetInsertBlock();
@@ -2724,6 +2727,12 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
//BF_ASSERT(refNode != NULL);
+ if (mIsConstModule)
+ {
+ mHadBuildError = true;
+ return NULL;
+ }
+
if (mCurMethodInstance != NULL)
mCurMethodInstance->mHasFailed = true;
@@ -4706,6 +4715,8 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou
BfIRValue BfModule::GetClassVDataPtr(BfTypeInstance* typeInstance)
{
auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef);
+ if (mIsConstModule)
+ return mBfIRBuilder->ConstEval_GetBfType(typeInstance->mTypeId, mBfIRBuilder->MapType(CreatePointerType(classVDataType)));
return mBfIRBuilder->CreateBitCast(CreateClassVDataGlobal(typeInstance), mBfIRBuilder->MapType(CreatePointerType(classVDataType)));
}
@@ -6728,7 +6739,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin
BfIRValue BfModule::FixClassVData(BfIRValue value)
{
- if (!mCompiler->mOptions.mObjectHasDebugFlags)
+ if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsConstModule))
return value;
auto intptrValue = mBfIRBuilder->CreatePtrToInt(value, BfTypeCode_IntPtr);
auto maskedValue = mBfIRBuilder->CreateAnd(intptrValue, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)~0xFFULL));
@@ -8025,7 +8036,7 @@ void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, boo
auto destAddr = mBfIRBuilder->CreateBitCast(vObjectAddr, mBfIRBuilder->MapType(ptrPtrType));
if (!isAutocomplete)
{
- if (mCompiler->mOptions.mObjectHasDebugFlags)
+ if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
{
auto objectPtr = mBfIRBuilder->CreateBitCast(destAddr, mBfIRBuilder->MapType(mContext->mBfObjectType));
@@ -8414,8 +8425,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
BfIRValue allocaInst;
BfIRValue result;
if ((typeInstance == NULL) || (typeInstance->mIsCRepr))
- {
- sizeValue = mBfIRBuilder->CreateMul(GetConstValue(typeSize), arraySize);
+ {
allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(type), arraySize);
result = allocaInst;
}
@@ -8450,28 +8460,32 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
bool isConstSize = arraySize.IsConst();
BfIRBlock clearBlock;
BfIRBlock contBlock;
+
+ bool wantsDeinit = ((!IsOptimized()) && (!mIsConstModule) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly));
- if (!isConstSize)
+ if (wantsDeinit)
{
- clearBlock = mBfIRBuilder->CreateBlock("clear");
- contBlock = mBfIRBuilder->CreateBlock("clearCont");
- mBfIRBuilder->CreateCondBr(mBfIRBuilder->CreateCmpNE(arraySize, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 0)), clearBlock, contBlock);
+ if (!isConstSize)
+ {
+ clearBlock = mBfIRBuilder->CreateBlock("clear");
+ contBlock = mBfIRBuilder->CreateBlock("clearCont");
+ mBfIRBuilder->CreateCondBr(mBfIRBuilder->CreateCmpNE(arraySize, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 0)), clearBlock, contBlock);
- mBfIRBuilder->AddBlock(clearBlock);
- mBfIRBuilder->SetInsertPoint(clearBlock);
+ mBfIRBuilder->AddBlock(clearBlock);
+ mBfIRBuilder->SetInsertPoint(clearBlock);
+ }
+
+ AddStackAlloc(typedVal, arraySize, NULL, scopeData, false, true);
+
+ if (!isConstSize)
+ {
+ mBfIRBuilder->CreateBr(contBlock);
+
+ mBfIRBuilder->AddBlock(contBlock);
+ mBfIRBuilder->SetInsertPoint(contBlock);
+ }
}
-
- AddStackAlloc(typedVal, arraySize, NULL, scopeData, false, true);
-
- if (!isConstSize)
- {
- mBfIRBuilder->CreateBr(contBlock);
-
- mBfIRBuilder->AddBlock(contBlock);
- mBfIRBuilder->SetInsertPoint(contBlock);
- }
- }
- //InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue);
+ }
return result;
}
@@ -8707,6 +8721,8 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
auto typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx);
stackCount = BfTypeOptions::Apply(stackCount, typeOptions->mAllocStackTraceDepth);
}
+ if (mIsConstModule)
+ stackCount = 0;
if (!sizeValue)
sizeValue = GetConstValue(typeInstance->mInstSize);
@@ -8777,7 +8793,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
{
if (hasCustomAllocator)
result = AllocBytes(allocTarget.mRefNode, allocTarget, typeInstance, sizeValue, GetConstValue(typeInstance->mInstAlign), (BfAllocFlags)(BfAllocFlags_ZeroMemory | BfAllocFlags_NoDefaultToMalloc));
- else if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mCompiler->mOptions.mDebugAlloc))
+ else if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule))
{
SizedArray llvmArgs;
llvmArgs.push_back(sizeValue);
@@ -8790,7 +8806,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
if (result)
{
- if (mCompiler->mOptions.mObjectHasDebugFlags)
+ if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
{
auto objectPtr = mBfIRBuilder->CreateBitCast(result, mBfIRBuilder->MapTypeInstPtr(mContext->mBfObjectType));
SizedArray llvmArgs;
@@ -8828,7 +8844,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef);
auto vData = mBfIRBuilder->CreateBitCast(vDataRef, mBfIRBuilder->MapTypeInstPtr(classVDataType->ToTypeInstance()));
- if (mCompiler->mOptions.mObjectHasDebugFlags)
+ if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
{
SizedArray llvmArgs;
llvmArgs.push_back(vData);
@@ -8844,7 +8860,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
SizedArray llvmArgs;
llvmArgs.push_back(sizeValue);
BfIRFunction irFunc;
- if (mCompiler->mOptions.mDebugAlloc)
+ if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule))
{
auto moduleMethodInstance = GetInternalMethod("Dbg_RawObjectAlloc", 1);
irFunc = moduleMethodInstance.mFunc;
@@ -9062,7 +9078,7 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue,
auto curThis = GetThis();
BfIRValue newFlags;
- if (mCompiler->mOptions.mObjectHasDebugFlags)
+ if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
{
auto thisFlagsPtr = mBfIRBuilder->CreateBitCast(curThis.mValue, ptrType);
auto thisFlags = mBfIRBuilder->CreateLoad(thisFlagsPtr);
@@ -9078,7 +9094,7 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue,
auto srcVal = mBfIRBuilder->CreateBitCast(vDataRef, ptrType);
mBfIRBuilder->CreateStore(srcVal, destAddr);
- if (mCompiler->mOptions.mObjectHasDebugFlags)
+ if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
{
auto flagsPtr = mBfIRBuilder->CreateBitCast(destAddr, ptrType);
mBfIRBuilder->CreateStore(newFlags, flagsPtr);
@@ -9129,7 +9145,7 @@ void BfModule::SkipObjectAccessCheck(BfTypedValue typedVal)
if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck))
return;
- if (!mCompiler->mOptions.mObjectHasDebugFlags)
+ if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsConstModule))
return;
if ((typedVal.mValue.mFlags & BfIRValueFlags_Value) == 0)
@@ -9143,7 +9159,7 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck))
return;
- if (!mCompiler->mOptions.mObjectHasDebugFlags)
+ if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsConstModule))
return;
if (typedVal.mValue.IsConst())
@@ -9187,8 +9203,17 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
{
if (mBfIRBuilder->mIgnoreWrites)
return; // Nothing needed here
-
+
auto irb = mBfIRBuilder;
+
+ if (mIsConstModule)
+ {
+ auto callResult = mBfIRBuilder->ConstEval_DynamicCastCheck(targetValue.mValue, targetType->mTypeId, mBfIRBuilder->MapType(mContext->mBfObjectType));
+ auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult, GetDefaultValue(mContext->mBfObjectType));
+ irb->CreateCondBr(cmpResult, trueBlock, falseBlock);
+ return;
+ }
+
auto checkBB = irb->CreateBlock("as.check");
auto isNull = irb->CreateIsNull(targetValue.mValue);
mBfIRBuilder->CreateCondBr(isNull, nullSucceeds ? trueBlock : falseBlock, checkBB);
@@ -9212,7 +9237,6 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
irArgs.push_back(objectParam);
irArgs.push_back(GetConstValue32(targetType->mTypeId));
auto callResult = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
- auto resultType = ResolveTypeDef(mSystem->mTypeBool);
auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult.mValue, GetDefaultValue(callResult.mType));
irb->CreateCondBr(cmpResult, trueBlock, falseBlock);
}
@@ -9221,7 +9245,7 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
AddBasicBlock(checkBB);
BfIRValue vDataPtr = irb->CreateBitCast(targetValue.mValue, irb->MapType(intPtrType));
vDataPtr = irb->CreateLoad(vDataPtr);
- if (mCompiler->mOptions.mObjectHasDebugFlags)
+ if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
vDataPtr = irb->CreateAnd(vDataPtr, irb->CreateConst(BfTypeCode_IntPtr, (uint64)~0xFFULL));
if (targetType->IsInterface())
@@ -13531,13 +13555,13 @@ BfLocalVariable* BfModule::AddLocalVariableDef(BfLocalVariable* localVarDef, boo
BF_ASSERT(rootMethodState->mCurLocalVarId >= 0);
localVarDef->mLocalVarId = rootMethodState->mCurLocalVarId++;
}
- if ((localVarDef->mNameNode != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
+ if ((localVarDef->mNameNode != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) && (!mIsConstModule))
mCompiler->mResolvePassData->mAutoComplete->CheckLocalDef(localVarDef->mNameNode, localVarDef);
if ((localVarDef->mNameNode != NULL) && (mCurMethodInstance != NULL))
{
bool isClosureProcessing = (mCurMethodState->mClosureState != NULL) && (!mCurMethodState->mClosureState->mCapturing);
- if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL))
+ if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL) && (!mIsConstModule))
mCompiler->mResolvePassData->HandleLocalReference(localVarDef->mNameNode, rootMethodState->mMethodInstance->GetOwner()->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVarDef->mLocalVarId);
}
@@ -14513,7 +14537,7 @@ BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArr
{
BP_ZONE("BfModule::TryConstCalcAppend");
- if (mCompiler->mIsResolveOnly)
+ if ((mCompiler->mIsResolveOnly) && (!mIsConstModule))
return BfTypedValue();
// We want to regenerate all ctor calls when the method internals change
@@ -14798,7 +14822,7 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly)
// This method never throws errors - it relies on the proper ctor actually throwing the errors
void BfModule::EmitCtorCalcAppend()
{
- if (mCompiler->mIsResolveOnly)
+ if ((mCompiler->mIsResolveOnly) && (!mIsConstModule))
return;
auto methodDef = mCurMethodInstance->mMethodDef;
@@ -14939,6 +14963,8 @@ void BfModule::EmitDtorBody()
// Fall through to Object::~this call
auto dtorFunc = GetMethodByName(mContext->mBfObjectType, "~this");
+ if (mIsConstModule)
+ mCompiler->mCEMachine->QueueMethod(dtorFunc.mMethodInstance, dtorFunc.mFunc);
auto basePtr = mBfIRBuilder->CreateBitCast(thisVal.mValue, mBfIRBuilder->MapTypeInstPtr(mContext->mBfObjectType));
SizedArray vals = { basePtr };
result = mBfIRBuilder->CreateCall(dtorFunc.mFunc, vals);
@@ -15115,6 +15141,8 @@ void BfModule::EmitDtorBody()
auto basePtr = mBfIRBuilder->CreateBitCast(mCurMethodState->mLocals[0]->mValue, mBfIRBuilder->MapTypeInstPtr(checkBaseType));
SizedArray vals = { basePtr };
auto callInst = mBfIRBuilder->CreateCall(dtorMethodInstance.mFunc, vals);
+ if (mIsConstModule)
+ mCompiler->mCEMachine->QueueMethod(dtorMethodInstance.mMethodInstance, dtorMethodInstance.mFunc);
mBfIRBuilder->SetCallCallingConv(callInst, GetIRCallingConvention(dtorMethodInstance.mMethodInstance));
}
}
@@ -15649,6 +15677,8 @@ void BfModule::EmitCtorBody(bool& skipBody)
SizedArray irArgs;
exprEvaluator.PushThis(NULL, GetThis(), moduleMethodInstance.mMethodInstance, irArgs);
exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
+ if (mIsConstModule)
+ mCompiler->mCEMachine->QueueMethod(moduleMethodInstance);
calledCtorNoBody = true;
}
@@ -15984,6 +16014,8 @@ void BfModule::EmitCtorBody(bool& skipBody)
auto callingConv = GetIRCallingConvention(ctorBodyMethodInstance.mMethodInstance);
if (callingConv != BfIRCallingConv_CDecl)
mBfIRBuilder->SetCallCallingConv(callInst, callingConv);
+ if (mIsConstModule)
+ mCompiler->mCEMachine->QueueMethod(ctorBodyMethodInstance);
}
if (matchedMethod == NULL)
@@ -20384,7 +20416,8 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man
// We can have a collision of names when we have generic methods that differ only in
// their constraints, but they should only collide in their unspecialized form
// since only one will be chosen for a given concrete type
- mCurMethodInstance->mMangleWithIdx = true;
+ if (!mIsConstModule)
+ mCurMethodInstance->mMangleWithIdx = true;
mangledName.Clear();
BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), mCurMethodInstance);
prevFunc = mBfIRBuilder->GetFunction(mangledName);
diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp
index 892f74e6..330b2700 100644
--- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp
+++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp
@@ -535,6 +535,13 @@ BfMethodInfoEx::~BfMethodInfoEx()
BfMethodInstance::~BfMethodInstance()
{
+ if (mInCEMachine)
+ {
+ auto module = GetOwner()->mModule;
+ if (module->mCompiler->mCEMachine != NULL)
+ module->mCompiler->mCEMachine->RemoveMethod(this);
+ }
+
if (mHasMethodRefType)
{
auto module = GetOwner()->mModule;
@@ -557,13 +564,7 @@ BfMethodInstance::~BfMethodInstance()
mHotMethod->Deref();
}
- delete mMethodInfoEx;
-
- if (mInCEMachine)
- {
- auto module = GetOwner()->mModule;
- module->mCompiler->mCEMachine->RemoveMethod(this);
- }
+ delete mMethodInfoEx;
}
BfImportKind BfMethodInstance::GetImportKind()
diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h
index 30e16b11..005e28cb 100644
--- a/IDEHelper/Compiler/BfResolvedTypeUtils.h
+++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h
@@ -55,7 +55,8 @@ enum BfMethodNameFlags : uint8
BfMethodNameFlag_None = 0,
BfMethodNameFlag_ResolveGenericParamNames = 1,
BfMethodNameFlag_OmitTypeName = 2,
- BfMethodNameFlag_IncludeReturnType = 4
+ BfMethodNameFlag_IncludeReturnType = 4,
+ BfMethodNameFlag_OmitParams = 8
};
enum BfGetMethodInstanceFlags : uint16
@@ -1416,7 +1417,7 @@ public:
mMethodRefFlags = BfMethodRefFlag_None;
}
- BfMethodRef(BfMethodInstance* methodInstance);
+ BfMethodRef(BfMethodInstance* methodInstance);
operator BfMethodInstance*() const;
bool IsNull() { return mTypeInstance == NULL; };
diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp
index 13f71f53..29960fe8 100644
--- a/IDEHelper/Compiler/BfStmtEvaluator.cpp
+++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp
@@ -42,7 +42,8 @@ USING_NS_BF;
bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfScopeData* scopeData)
{
- if (((mCompiler->mIsResolveOnly) || (mBfIRBuilder->mIgnoreWrites)) && (deferredCallEntry->mDeferredBlock == NULL))
+ if ((((mCompiler->mIsResolveOnly) && (!mIsConstModule)) ||
+ (mBfIRBuilder->mIgnoreWrites)) && (deferredCallEntry->mDeferredBlock == NULL))
{
// For resolve entries, we only keep deferred blocks because we need to process them later so we can
// resolve inside of them. This is also required for lambda bind scan-pass
@@ -782,7 +783,7 @@ void BfModule::EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, Siz
void BfModule::EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry, bool moveBlocks)
{
- if ((mCompiler->mIsResolveOnly) && (deferredCallEntry.mHandlerCount > 0))
+ if ((mCompiler->mIsResolveOnly) && (!mIsConstModule) && (deferredCallEntry.mHandlerCount > 0))
{
// We only want to process deferred blocks once, otherwise it could significantly slow down autocompletion
return;
diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp
index 77bc5af9..5804572b 100644
--- a/IDEHelper/Compiler/BfSystem.cpp
+++ b/IDEHelper/Compiler/BfSystem.cpp
@@ -928,6 +928,7 @@ bool BfProject::IsTestProject()
BfErrorBase::~BfErrorBase()
{
+ delete mLocation;
}
void BfErrorBase::SetSource(BfPassInstance* passInstance, BfSourceData* source)
@@ -1598,9 +1599,8 @@ BfError* BfPassInstance::WarnAfter(int warningNumber, const StringImpl& warning,
return WarnAt(warningNumber, warning, refNode->GetSourceData(), refNode->GetSrcEnd());
}
-BfError* BfPassInstance::MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags)
-{
- String msgPrefix;
+BfMoreInfo* BfPassInstance::MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags)
+{
if (!mLastWasDisplayed)
{
if (mLastWasAdded)
@@ -1612,25 +1612,20 @@ BfError* BfPassInstance::MoreInfoAt(const StringImpl& info, BfSourceData* bfSour
moreInfo->mSrcStart = srcIdx;
moreInfo->mSrcEnd = srcIdx + srcLen;
- if (lastError->mIsWarning)
- msgPrefix = ":warn";
- else
- msgPrefix = ":error";
-
lastError->mMoreInfo.push_back(moreInfo);
+ return moreInfo;
}
return NULL;
}
+ String msgPrefix;
MessageAt(msgPrefix, " > " + info, bfSource, srcIdx, srcLen, flags);
return NULL;
}
-BfError* BfPassInstance::MoreInfo(const StringImpl& info)
-{
- String outText;
-
+BfMoreInfo* BfPassInstance::MoreInfo(const StringImpl& info)
+{
if (!mLastWasDisplayed)
{
if (mLastWasAdded)
@@ -1642,23 +1637,21 @@ BfError* BfPassInstance::MoreInfo(const StringImpl& info)
moreInfo->mSrcStart = -1;
moreInfo->mSrcEnd = -1;
- if (lastError->mIsWarning)
- outText = ":warn ";
- else
- outText = ":error ";
-
lastError->mMoreInfo.push_back(moreInfo);
+ return moreInfo;
}
return NULL;
}
+ String outText;
+ outText += " > ";
outText += info;
OutputLine(outText);
return NULL;
}
-BfError* BfPassInstance::MoreInfo(const StringImpl& info, BfAstNode* refNode)
+BfMoreInfo* BfPassInstance::MoreInfo(const StringImpl& info, BfAstNode* refNode)
{
if (refNode == NULL)
return MoreInfo(info);
@@ -1666,7 +1659,7 @@ BfError* BfPassInstance::MoreInfo(const StringImpl& info, BfAstNode* refNode)
return MoreInfoAt(info, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength());
}
-BfError* BfPassInstance::MoreInfoAfter(const StringImpl& info, BfAstNode* refNode)
+BfMoreInfo* BfPassInstance::MoreInfoAfter(const StringImpl& info, BfAstNode* refNode)
{
return MoreInfoAt(info, refNode->GetSourceData(), refNode->GetSrcEnd(), 1);
}
@@ -3486,6 +3479,14 @@ BF_EXPORT const char* BF_CALLTYPE BfPassInstance_GetErrorData(BfPassInstance* bf
}
}
}
+
+ if (bfError->mLocation != NULL)
+ {
+ fileName = (char*)bfError->mLocation->mFile.c_str();
+ *outLine = bfError->mLocation->mLine;
+ *outColumn = bfError->mLocation->mColumn;
+ }
+
outSrcStart = bfError->mSrcStart;
outSrcEnd = bfError->mSrcEnd;
outMoreInfoCount = (int)bfError->mMoreInfo.size();
@@ -3504,6 +3505,16 @@ BF_EXPORT const char* BfPassInstance_Error_GetMoreInfoData(BfPassInstance* bfPas
fileName = (char*)srcFileName->c_str();
}
}
+
+ if (moreInfo->mLocation != NULL)
+ {
+ fileName = (char*)moreInfo->mLocation->mFile.c_str();
+ if (outLine != NULL)
+ *outLine = moreInfo->mLocation->mLine;
+ if (outColumn != NULL)
+ *outColumn = moreInfo->mLocation->mColumn;
+ }
+
srcStart = moreInfo->mSrcStart;
srcEnd = moreInfo->mSrcEnd;
return moreInfo->mInfo.c_str();
diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h
index 95ed3b3a..1836bc81 100644
--- a/IDEHelper/Compiler/BfSystem.h
+++ b/IDEHelper/Compiler/BfSystem.h
@@ -1122,6 +1122,14 @@ enum BfWarning
BfWarning_C4554_PossiblePrecedenceError = 4554
};
+class BfErrorLocation
+{
+public:
+ String mFile;
+ int mLine;
+ int mColumn;
+};
+
class BfErrorBase
{
public:
@@ -1129,7 +1137,8 @@ public:
bool mIsDeferred;
BfSourceData* mSource;
int mSrcStart;
- int mSrcEnd;
+ int mSrcEnd;
+ BfErrorLocation* mLocation;
public:
BfErrorBase()
@@ -1139,6 +1148,7 @@ public:
mSource = NULL;
mSrcStart = -1;
mSrcEnd = -1;
+ mLocation = NULL;
}
~BfErrorBase();
@@ -1278,10 +1288,10 @@ public:
BfError* Warn(int warningNumber, const StringImpl& warning, BfAstNode* refNode);
BfError* WarnAfter(int warningNumber, const StringImpl& warning, BfAstNode* refNode);
- BfError* MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags = BfFailFlag_None);
- BfError* MoreInfo(const StringImpl& info);
- BfError* MoreInfo(const StringImpl& info, BfAstNode* refNode);
- BfError* MoreInfoAfter(const StringImpl& info, BfAstNode* refNode);
+ BfMoreInfo* MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags = BfFailFlag_None);
+ BfMoreInfo* MoreInfo(const StringImpl& info);
+ BfMoreInfo* MoreInfo(const StringImpl& info, BfAstNode* refNode);
+ BfMoreInfo* MoreInfoAfter(const StringImpl& info, BfAstNode* refNode);
BfError* FailAt(const StringImpl& error, BfSourceData* bfSource, int srcIdx, int srcLen = 1, BfFailFlags flags = BfFailFlag_None);
BfError* FailAfterAt(const StringImpl& error, BfSourceData* bfSource, int srcIdx);
diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp
index d52f3e01..a07dad96 100644
--- a/IDEHelper/Compiler/CeMachine.cpp
+++ b/IDEHelper/Compiler/CeMachine.cpp
@@ -4,8 +4,9 @@
#include "BfIRBuilder.h"
#include "../Backend/BeIRCodeGen.h"
-USING_NS_BF;
+#define CE_ENABLE_HEAP
+USING_NS_BF;
struct CeOpInfo
{
@@ -37,12 +38,11 @@ struct CeOpInfo
{OPNAME "_64", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME "_X", OPINFOA, CEOI_IMM32, OPINFOB, OPINFOC}
-#define CEOPINFO_SIZED_NUMERIC(OPNAME, OPINFOA, OPINFOB, OPINFOC) \
- {OPNAME "_I8", OPINFOA, OPINFOB, OPINFOC}, \
- {OPNAME "_I16", OPINFOA, OPINFOB, OPINFOC}, \
- {OPNAME "_I32", OPINFOA, OPINFOB, OPINFOC}, \
- {OPNAME "_I64", OPINFOA, OPINFOB, OPINFOC}
-
+#define CEOPINFO_SIZED_NUMERIC_2(OPNAME, OPINFOA, OPINFOB) \
+ {OPNAME "_I8", OPINFOA, OPINFOB}, \
+ {OPNAME "_I16", OPINFOA, OPINFOB}, \
+ {OPNAME "_I32", OPINFOA, OPINFOB}, \
+ {OPNAME "_I64", OPINFOA, OPINFOB}
#define CEOPINFO_SIZED_NUMERIC_PLUSF_2(OPNAME, OPINFOA, OPINFOB) \
{OPNAME "_I8", OPINFOA, OPINFOB}, \
{OPNAME "_I16", OPINFOA, OPINFOB}, \
@@ -55,6 +55,11 @@ struct CeOpInfo
{OPNAME "_I16", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME "_I32", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME "_I64", OPINFOA, OPINFOB, OPINFOC}
+#define CEOPINFO_SIZED_UNUMERIC_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \
+ {OPNAME "_U8", OPINFOA, OPINFOB, OPINFOC}, \
+ {OPNAME "_U16", OPINFOA, OPINFOB, OPINFOC}, \
+ {OPNAME "_U32", OPINFOA, OPINFOB, OPINFOC}, \
+ {OPNAME "_U64", OPINFOA, OPINFOB, OPINFOC}
#define CEOPINFO_SIZED_NUMERIC_PLUSF_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \
{OPNAME "_I8", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME "_I16", OPINFOA, OPINFOB, OPINFOC}, \
@@ -70,9 +75,18 @@ static CeOpInfo gOpInfo[] =
{"Jmp", CEOI_None, CEOI_JMPREL},
{"JmpIf", CEOI_None, CEOI_JMPREL, CEOI_FrameRef},
{"JmpIfNot", CEOI_None, CEOI_JMPREL, CEOI_FrameRef},
+ {"Error", CEOI_None, CEOI_IMM32},
+ {"DynamicCastCheck", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM32},
+ {"GetString", CEOI_FrameRef, CEOI_IMM32},
+ {"Malloc", CEOI_FrameRef, CEOI_FrameRef},
+ {"Free", CEOI_None, CEOI_FrameRef},
+
+ {"MemSet", CEOI_None, CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef},
+ {"MemSet_Const", CEOI_None, CEOI_FrameRef, CEOI_IMM8, CEOI_IMM32},
+ {"MemCpy", CEOI_None, CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef},
{"FrameAddr_32", CEOI_FrameRef, CEOI_FrameRef},
{"FrameAddr_64", CEOI_FrameRef, CEOI_FrameRef},
- {"Zero", CEOI_FrameRef, CEOI_IMM32},
+ {"Zero", CEOI_None, CEOI_FrameRef, CEOI_IMM32},
{"Const_8", CEOI_FrameRef, CEOI_IMM8},
{"Const_16", CEOI_FrameRef, CEOI_IMM16},
@@ -87,10 +101,53 @@ static CeOpInfo gOpInfo[] =
CEOPINFO_SIZED_1("Pop", CEOI_FrameRef),
{"AdjustSP", CEOI_None, CEOI_FrameRef},
+ {"AdjustSPNeg", CEOI_None, CEOI_FrameRef},
+ {"AdjustSPConst", CEOI_None, CEOI_IMM32},
+ {"CeOp_GetSP", CEOI_FrameRef},
+ {"CeOp_SetSP", CEOI_None, CEOI_FrameRef},
{"Call", CEOI_None, CEOI_IMM32},
+ {"Call_Virt", CEOI_None, CEOI_FrameRef, CEOI_IMM32},
+ {"CeOp_Call_IFace", CEOI_None, CEOI_FrameRef, CEOI_IMM32, CEOI_IMM32},
- {"Conv_I32_I64", CEOI_FrameRef, CEOI_FrameRef},
-
+ {"CeOp_Conv_I8_I16", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I8_I32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I8_I64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I8_F32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I8_F64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I16_I32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I16_I64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I16_F32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I16_F64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I32_I64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I32_F32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I32_F64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I64_F32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_I64_F64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U8_U16", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U8_U32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U8_U64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U8_F32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U8_F64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U16_U32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U16_U64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U16_F32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U16_F64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U32_U64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U32_F32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U32_F64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U64_F32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_U64_F64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_F32_I8", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_F32_I16", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_F32_I32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_F32_I64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_F32_F64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_F64_I8", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_F64_I16", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_F64_I32", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_F64_I64", CEOI_FrameRef, CEOI_FrameRef},
+ {"CeOp_Conv_F64_F32", CEOI_FrameRef, CEOI_FrameRef},
+
{"AddConst_I8", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM8},
{"AddConst_I16", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM16},
{"AddConst_I32", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM32},
@@ -105,19 +162,36 @@ static CeOpInfo gOpInfo[] =
CEOPINFO_SIZED_NUMERIC_3("UDiv", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("SMod", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_3("UMod", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
+ CEOPINFO_SIZED_NUMERIC_3("And", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
+ CEOPINFO_SIZED_NUMERIC_3("Or", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
+ CEOPINFO_SIZED_NUMERIC_3("Xor", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
+ CEOPINFO_SIZED_NUMERIC_3("Shl", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
+ CEOPINFO_SIZED_NUMERIC_3("Shr", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
+ CEOPINFO_SIZED_UNUMERIC_3("Shr", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_EQ", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
+ CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_NE", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_SLT", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_3("Cmp_ULT", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_SLE", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_3("Cmp_ULE", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
- //{"Cmp_SLT_I32", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef},
-
+ CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_SGT", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
+ CEOPINFO_SIZED_NUMERIC_3("Cmp_UGT", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
+ CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_SGE", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
+ CEOPINFO_SIZED_NUMERIC_3("Cmp_UGE", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_2("Neg", CEOI_FrameRef, CEOI_FrameRef),
+ {"Not_I1", CEOI_FrameRef, CEOI_FrameRef},
+ CEOPINFO_SIZED_NUMERIC_2("Not", CEOI_FrameRef, CEOI_FrameRef),
};
static_assert(BF_ARRAY_COUNT(gOpInfo) == (int)CeOp_COUNT, "gOpName incorrect size");
+//////////////////////////////////////////////////////////////////////////
+
+CeFunction::~CeFunction()
+{
+
+}
//////////////////////////////////////////////////////////////////////////
@@ -211,9 +285,8 @@ void CeDumpContext::Dump()
{
int ofs = mPtr - start;
- while ((curEmitIdx < mCeFunction->mEmitTable.mSize) && (ofs > mCeFunction->mEmitTable[curEmitIdx].mCodePos))
+ while ((curEmitIdx < mCeFunction->mEmitTable.mSize - 1) && (ofs >= mCeFunction->mEmitTable[curEmitIdx + 1].mCodePos))
curEmitIdx++;
-
if (curEmitIdx < mCeFunction->mEmitTable.mSize)
curEmitEntry = &mCeFunction->mEmitTable[curEmitIdx];
@@ -267,7 +340,11 @@ void CeBuilder::Fail(const StringImpl& str)
String errStr = StrFormat("Failure during const code generation of %s: %s", mBeFunction->mName.c_str(), str.c_str());
if (mCurDbgLoc != NULL)
- errStr += StrFormat(" at line %d:%d in %s", mCurDbgLoc->mLine + 1, mCurDbgLoc->mColumn + 1, mCurDbgLoc->GetDbgFile()->mFileName.c_str());
+ {
+ String filePath;
+ mCurDbgLoc->GetDbgFile()->GetFilePath(filePath);
+ errStr += StrFormat(" at line %d:%d in %s", mCurDbgLoc->mLine + 1, mCurDbgLoc->mColumn + 1, filePath.c_str());
+ }
mCeFunction->mGenError = errStr;
}
@@ -282,6 +359,11 @@ void CeBuilder::Emit(CeOp val)
*(CeOp*)mCeFunction->mCode.GrowUninitialized(sizeof(CeOp)) = val;
}
+void CeBuilder::EmitSizedOp(CeOp val, int size)
+{
+ Emit((CeOp)(val + GetSizeClass(size)));
+}
+
void CeBuilder::Emit(int32 val)
{
*(int32*)mCeFunction->mCode.GrowUninitialized(4) = val;
@@ -386,7 +468,7 @@ void CeBuilder::FlushPhi(CeBlock* ceBlock, int targetBlockIdx)
void CeBuilder::EmitBinaryOp(CeOp iOp, CeOp fOp, const CeOperand& lhs, const CeOperand& rhs, CeOperand& result)
{
CeOp op = iOp;
- if (lhs.mType->IsIntegral())
+ if (lhs.mType->IsIntable())
{
if (lhs.mType->mSize == 1)
op = iOp;
@@ -421,7 +503,7 @@ void CeBuilder::EmitBinaryOp(CeOp iOp, CeOp fOp, const CeOperand& lhs, const CeO
void CeBuilder::EmitUnaryOp(CeOp iOp, CeOp fOp, const CeOperand& val, CeOperand& result)
{
CeOp op = iOp;
- if (val.mType->IsIntegral())
+ if (val.mType->IsIntable())
{
if (val.mType->mSize == 1)
op = iOp;
@@ -499,33 +581,99 @@ CeOperand CeBuilder::FrameAlloc(BeType* type)
return result;
}
+CeOperand CeBuilder::EmitConst(int64 val, int size)
+{
+ BeType* type = mIntPtrType;
+ switch (size)
+ {
+ case 1:
+ type = mCeMachine->GetBeContext()->GetPrimitiveType(BeTypeCode_Int8);
+ break;
+ case 2:
+ type = mCeMachine->GetBeContext()->GetPrimitiveType(BeTypeCode_Int16);
+ break;
+ case 4:
+ type = mCeMachine->GetBeContext()->GetPrimitiveType(BeTypeCode_Int32);
+ break;
+ case 8:
+ type = mCeMachine->GetBeContext()->GetPrimitiveType(BeTypeCode_Int64);
+ break;
+ default:
+ Fail("Bad const size");
+ }
+
+ auto result = FrameAlloc(type);
+
+ EmitSizedOp(CeOp_Const_8, type->mSize);
+ EmitFrameOffset(result);
+ Emit(&val, size);
+ return result;
+}
+
CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImmediate)
{
if (value == NULL)
return CeOperand();
+
+ BeType* errorType = mIntPtrType;
+ CeErrorKind errorKind = CeErrorKind_None;
switch (value->GetTypeId())
{
case BeGlobalVariable::TypeId:
{
-// auto globalVar = (BeGlobalVariable*)value;
-// if ((globalVar->mIsTLS) && (mTLSVRegIdx == -1))
-// {
-// auto tlsVReg = AllocVirtualReg(mNativeIntType);
-// auto vregInfo = GetVRegInfo(tlsVReg);
-// vregInfo->mMustExist = true;
-// vregInfo->mForceReg = true;
-// mTLSVRegIdx = tlsVReg.mVRegIdx;
-// }
-//
-// auto sym = mCOFFObject->GetSymbol(globalVar);
-// if (sym != NULL)
-// {
-// CeOperand mcOperand;
-// mcOperand.mKind = CeOperandKind_SymbolAddr;
-// mcOperand.mSymbolIdx = sym->mIdx;
-// return mcOperand;
-// }
+ auto globalVar = (BeGlobalVariable*)value;
+ if (globalVar->mName.StartsWith("__bfStrObj"))
+ {
+ int stringId = atoi(globalVar->mName.c_str() + 10);
+
+ int* stringTableIdxPtr = NULL;
+ if (mStringMap.TryAdd(stringId, NULL, &stringTableIdxPtr))
+ {
+ *stringTableIdxPtr = (int)mCeFunction->mStringTable.size();
+ CeStringEntry ceStringEntry;
+ ceStringEntry.mStringId = stringId;
+ mCeFunction->mStringTable.Add(ceStringEntry);
+ }
+
+ auto result = FrameAlloc(mCeMachine->GetBeContext()->GetPointerTo(globalVar->mType));
+
+ Emit(CeOp_GetString);
+ EmitFrameOffset(result);
+ Emit((int32)*stringTableIdxPtr);
+ return result;
+ }
+ else if (globalVar->mName.StartsWith("__bfStrData"))
+ {
+ int stringId = atoi(globalVar->mName.c_str() + 11);
+
+ int* stringTableIdxPtr = NULL;
+ if (mStringMap.TryAdd(stringId, NULL, &stringTableIdxPtr))
+ {
+ *stringTableIdxPtr = (int)mCeFunction->mStringTable.size();
+ CeStringEntry ceStringEntry;
+ ceStringEntry.mStringId = stringId;
+ mCeFunction->mStringTable.Add(ceStringEntry);
+ }
+
+ auto result = FrameAlloc(mCeMachine->GetBeContext()->GetPointerTo(globalVar->mType));
+
+ Emit(CeOp_GetString);
+ EmitFrameOffset(result);
+ Emit((int32)*stringTableIdxPtr);
+
+ BfTypeInstance* stringTypeInst = (BfTypeInstance*)mCeMachine->mCeModule->ResolveTypeDef(
+ mCeMachine->mCeModule->mCompiler->mStringTypeDef, BfPopulateType_Data);
+
+ Emit(CeOp_AddConst_I32);
+ EmitFrameOffset(result);
+ EmitFrameOffset(result);
+ Emit((int32)stringTypeInst->mInstSize);
+
+ return result;
+ }
+ errorKind = CeErrorKind_GlobalVariable;
+ errorType = mCeMachine->GetBeContext()->GetPointerTo(globalVar->mType);
}
break;
case BeCastConstant::TypeId:
@@ -533,22 +681,9 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
auto constant = (BeCastConstant*)value;
CeOperand mcOperand;
- auto relTo = GetOperand(constant->mTarget);
- if (relTo.mKind == CeOperandKind_Immediate)
- {
- mcOperand.mKind = CeOperandKind_Immediate;
- mcOperand.mType = constant->mType;
- return mcOperand;
- }
-
- //Fail("Invalid operand");
-// mcOperand = AllocVirtualReg(constant->mType);
-// auto vregInfo = GetVRegInfo(mcOperand);
-// vregInfo->mDefOnFirstUse = true;
-// vregInfo->mRelTo = relTo;
-// vregInfo->mIsExpr = true;
-
- //return mcOperand;
+ auto result = GetOperand(constant->mTarget);
+ result.mType = constant->mType;
+ return result;
}
break;
case BeConstant::TypeId:
@@ -665,43 +800,49 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
}
case BeGEPConstant::TypeId:
{
-// auto gepConstant = (BeGEPConstant*)value;
-//
-// auto mcVal = GetOperand(gepConstant->mTarget);
-//
-// BePointerType* ptrType = (BePointerType*)GetType(mcVal);
-// BEMC_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer);
-//
-// auto result = mcVal;
-//
-// // We assume we never do both an idx0 and idx1 at once. Fix if we change that.
-// int byteOffset = 0;
-// BeType* elementType = NULL;
-// byteOffset += gepConstant->mIdx0 * ptrType->mElementType->mSize;
-//
-// if (ptrType->mElementType->mTypeCode == BeTypeCode_Struct)
-// {
-// BeStructType* structType = (BeStructType*)ptrType->mElementType;
-// auto& structMember = structType->mMembers[gepConstant->mIdx1];
-// elementType = structMember.mType;
-// byteOffset = structMember.mByteOffset;
-// }
-// else
-// {
-// BEMC_ASSERT(ptrType->mElementType->mTypeCode == BeTypeCode_SizedArray);
-// auto arrayType = (BeSizedArrayType*)ptrType->mElementType;
-// elementType = arrayType->mElementType;
-// byteOffset = gepConstant->mIdx1 * elementType->mSize;
-// }
-//
-// auto elementPtrType = mModule->mContext->GetPointerTo(elementType);
+ auto gepConstant = (BeGEPConstant*)value;
+
+ auto mcVal = GetOperand(gepConstant->mTarget);
+
+ BePointerType* ptrType = (BePointerType*)mcVal.mType;
+ BF_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer);
+
+ auto result = mcVal;
+
+ // We assume we never do both an idx0 and idx1 at once. Fix if we change that.
+ int64 byteOffset = 0;
+ BeType* elementType = NULL;
+ byteOffset += gepConstant->mIdx0 * ptrType->mElementType->mSize;
+
+ if (ptrType->mElementType->mTypeCode == BeTypeCode_Struct)
+ {
+ BeStructType* structType = (BeStructType*)ptrType->mElementType;
+ auto& structMember = structType->mMembers[gepConstant->mIdx1];
+ elementType = structMember.mType;
+ byteOffset = structMember.mByteOffset;
+ }
+ else
+ {
+ BF_ASSERT(ptrType->mElementType->mTypeCode == BeTypeCode_SizedArray);
+ auto arrayType = (BeSizedArrayType*)ptrType->mElementType;
+ elementType = arrayType->mElementType;
+ byteOffset = gepConstant->mIdx1 * elementType->mSize;
+ }
+
+ auto elementPtrType = mCeMachine->GetBeContext()->GetPointerTo(elementType);
+ result = FrameAlloc(elementPtrType);
+ EmitSizedOp(CeOp_AddConst_I8, mPtrSize);
+ EmitFrameOffset(result);
+ EmitFrameOffset(mcVal);
+ Emit(&byteOffset, mPtrSize);
+
// result = AllocRelativeVirtualReg(elementPtrType, result, GetImmediate(byteOffset), 1);
-// // The def is primary to create a single 'master location' for the GEP vreg to become legalized before use
-// auto vregInfo = GetVRegInfo(result);
-// vregInfo->mDefOnFirstUse = true;
-// result.mKind = CeOperandKind_VReg;
-//
-// return result;
+// // The def is primary to create a single 'master location' for the GEP vreg to become legalized before use
+// auto vregInfo = GetVRegInfo(result);
+// vregInfo->mDefOnFirstUse = true;
+// result.mKind = CeOperandKind_VReg;
+
+ return result;
}
break;
case BeExtractValueConstant::TypeId:
@@ -744,7 +885,12 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
CeOperand* operandPtr = NULL;
mValueToOperand.TryGetValue(value, &operandPtr);
- //if (!allowFail)
+ if (errorKind != CeErrorKind_None)
+ {
+ Emit(CeOp_Error);
+ Emit((int32)errorKind);
+ }
+ else
{
if (operandPtr == NULL)
{
@@ -756,7 +902,7 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
}
if (operandPtr == NULL)
{
- return FrameAlloc(mIntPtrType);
+ return FrameAlloc(errorType);
}
auto operand = *operandPtr;
@@ -773,160 +919,6 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
return result;
}
-// if ((operand.mKind == CeOperandKind_Phi) && (!allowMetaResult))
-// {
-// auto phi = operand.mPhi;
-//
-// int phiInstIdx = 0;
-//
-// auto mcBlock = phi->mBlock;
-// for (auto instIdx = 0; instIdx < mcBlock->mInstructions.size(); instIdx++)
-// {
-// auto inst = mcBlock->mInstructions[instIdx];
-// if (inst->mKind == BeMCInstKind_DefPhi)
-// {
-// BEMC_ASSERT(inst->mArg0.mPhi == phi);
-// phiInstIdx = instIdx;
-// RemoveInst(mcBlock, phiInstIdx);
-// break;
-// }
-// }
-//
-// SetAndRestoreValue prevBlock(mActiveBlock, mcBlock);
-// SetAndRestoreValue prevInstIdxRef(mInsertInstIdxRef, &phiInstIdx);
-//
-// auto resultType = value->GetType();
-// auto result = AllocVirtualReg(resultType);
-// auto vregInfo = GetVRegInfo(result);
-// vregInfo->mHasDynLife = true; // No specific 'def' location
-// mValueToOperand[value] = result;
-//
-// if (resultType->mTypeCode == BeTypeCode_Boolean)
-// {
-// CreateDefineVReg(result);
-//
-// CeOperand falseLabel = CeOperand::FromLabel(mCurLabelIdx++);
-// CeOperand trueLabel = CeOperand::FromLabel(mCurLabelIdx++);
-// CeOperand endLabel = CeOperand::FromLabel(mCurLabelIdx++);
-// CreateCondBr(mActiveBlock, operand, trueLabel, falseLabel);
-//
-// AllocInst(BeMCInstKind_Label, falseLabel);
-// AllocInst(BeMCInstKind_Mov, result, CeOperand::FromImmediate(0));
-// AllocInst(BeMCInstKind_Br, endLabel);
-// AllocInst(BeMCInstKind_Label, trueLabel);
-// AllocInst(BeMCInstKind_Mov, result, CeOperand::FromImmediate(1));
-// AllocInst(BeMCInstKind_Label, endLabel);
-// }
-// else
-// {
-// // Attempt to find common ancestor to insert a 'def' at
-// SizedArray blockSearch;
-// blockSearch.reserve(phi->mValues.size());
-// BeMCBlock* lowestBlock = NULL;
-// for (auto& phiValue : phi->mValues)
-// {
-// if ((lowestBlock == NULL) || (phiValue.mBlockFrom->mBlockIdx < lowestBlock->mBlockIdx))
-// lowestBlock = phiValue.mBlockFrom;
-// blockSearch.push_back(phiValue.mBlockFrom);
-// }
-// while (true)
-// {
-// bool allMatched = true;
-// bool didWork = false;
-// for (int searchIdx = 0; searchIdx < (int)blockSearch.size(); searchIdx++)
-// {
-// auto& blockRef = blockSearch[searchIdx];
-// if (blockRef != lowestBlock)
-// {
-// allMatched = false;
-//
-// for (auto& pred : blockRef->mPreds)
-// {
-// // Try find a block closer to start, but not below the current lowestBlock
-// if ((pred->mBlockIdx >= lowestBlock->mBlockIdx) && (pred->mBlockIdx < blockRef->mBlockIdx))
-// {
-// blockRef = pred;
-// didWork = true;
-// }
-// }
-// }
-// }
-//
-// if (allMatched)
-// {
-// SetAndRestoreValue prevActiveBlock(mActiveBlock, lowestBlock);
-// SetAndRestoreValue prevInstIdxRef(mInsertInstIdxRef, NULL);
-// auto inst = CreateDefineVReg(result);
-// inst->mVRegsInitialized = NULL;
-// inst->mDbgLoc = NULL;
-// break;
-// }
-//
-// if (!didWork)
-// {
-// BeMCBlock* nextLowestBlock = NULL;
-//
-// // Find the next candidate block
-// for (auto& blockRef : blockSearch)
-// {
-// for (auto& pred : blockRef->mPreds)
-// {
-// if (pred->mBlockIdx < lowestBlock->mBlockIdx)
-// {
-// if ((nextLowestBlock == NULL) || (pred->mBlockIdx > nextLowestBlock->mBlockIdx))
-// nextLowestBlock = pred;
-// }
-// }
-// }
-//
-// if (nextLowestBlock == NULL)
-// break;
-// lowestBlock = nextLowestBlock;
-// }
-// }
-//
-// CeOperand doneLabel = CeOperand::FromLabel(mCurLabelIdx++);
-// CreatePhiAssign(mActiveBlock, operand, result, doneLabel);
-//
-// // Don't use an explicit dbgLoc
-// SetAndRestoreValue prevDbgLoc(mCurDbgLoc, NULL);
-// AllocInst(BeMCInstKind_Label, doneLabel);
-// }
-//
-// return result;
-// }
-//
-// if ((operand.mKind == CeOperandKind_CmpResult) && (!allowMetaResult))
-// {
-// auto& cmpResult = mCmpResults[operand.mCmpResultIdx];
-// if (cmpResult.mResultVRegIdx == -1)
-// {
-// // Create the vreg now, and insert the CmpToBool during legalization
-// BeType* boolType = mModule->mContext->GetPrimitiveType(BeTypeCode_Boolean);
-// operand = AllocVirtualReg(boolType);
-// cmpResult.mResultVRegIdx = operand.mVRegIdx;
-//
-// auto vregInfo = GetVRegInfo(operand);
-// vregInfo->mDefOnFirstUse = true;
-// }
-//
-// operand = CeOperand::FromVReg(cmpResult.mResultVRegIdx);
-// }
-//
-// if ((operand.mKind == CeOperandKind_NotResult) && (!allowMetaResult))
-// {
-// auto mcValue = GetOperand(operand.mNotResult->mValue, false, allowFail);
-//
-// operand = AllocVirtualReg(GetType(mcValue));
-// CreateDefineVReg(operand);
-// AllocInst(BeMCInstKind_Mov, operand, mcValue);
-//
-// CeOperand xorVal;
-// xorVal.mKind = CeOperandKind_Immediate_i8;
-// xorVal.mImmediate = 0x1;
-// AllocInst(BeMCInstKind_Xor, operand, xorVal);
-// }
-
return operand;
}
@@ -1010,9 +1002,11 @@ void CeBuilder::Build()
dupMethodInstance.mIsReified = true;
dupMethodInstance.mHotMethod = NULL;
dupMethodInstance.mInCEMachine = false; // Only have the original one
-
+
+ mCeMachine->mCeModule->mIgnoreWarnings = true;
+ mCeMachine->mCeModule->mHadBuildError = false;
mCeMachine->mCeModule->ProcessMethod(&dupMethodInstance, true);
-
+
if (!dupMethodInstance.mIRFunction)
{
mCeFunction->mFailed = true;
@@ -1023,8 +1017,23 @@ void CeBuilder::Build()
mIntPtrType = irCodeGen->mBeContext->GetPrimitiveType((mPtrSize == 4) ? BeTypeCode_Int32 : BeTypeCode_Int64);
mBeFunction = (BeFunction*)irCodeGen->GetBeValue(dupMethodInstance.mIRFunction.mId);
- mCeFunction->mName = mBeFunction->mName;
- mCeMachine->mNamedFunctionMap[mCeFunction->mName] = mCeFunction;
+ if (!mCeFunction->mCeFunctionInfo->mName.IsEmpty())
+ {
+ BF_ASSERT(mCeFunction->mCeFunctionInfo->mName == mBeFunction->mName);
+ }
+ else
+ {
+ mCeFunction->mCeFunctionInfo->mName = mBeFunction->mName;
+ mCeMachine->mNamedFunctionMap[mCeFunction->mCeFunctionInfo->mName] = mCeFunction->mCeFunctionInfo;
+ }
+
+ if (mCeMachine->mCeModule->mHadBuildError)
+ {
+ mCeFunction->mGenError = "Method had errors";
+ mCeMachine->mCeModule->mHadBuildError = false;
+ return;
+ }
+
auto beModule = irCodeGen->mBeModule;
SetAndRestoreValue prevBeFunction(beModule->mActiveFunction, mBeFunction);
@@ -1128,32 +1137,85 @@ void CeBuilder::Build()
case BeLifetimeExtendInst::TypeId:
case BeValueScopeStartInst::TypeId:
case BeValueScopeEndInst::TypeId:
+ case BeValueScopeRetainInst::TypeId:
+ case BeConstEvalGetVirtualFunc::TypeId:
+ case BeConstEvalGetInterfaceFunc::TypeId:
break;
case BeUnreachableInst::TypeId:
Emit(CeOp_InvalidOp);
break;
+ case BeUndefValueInst::TypeId:
+ {
+ auto castedInst = (BeUndefValueInst*)inst;
+ result = FrameAlloc(castedInst->mType);
+ }
+ break;
case BeAllocaInst::TypeId:
{
auto castedInst = (BeAllocaInst*)inst;
- int size = castedInst->mType->mSize;
+
+ CeOperand ceSize;
+ ceSize.mKind = CeOperandKind_Immediate;
+ ceSize.mImmediate = castedInst->mType->mSize;
+ ceSize.mType = mIntPtrType;
bool isAligned16 = false;
int align = castedInst->mAlign;
BeType* allocType = castedInst->mType;
- bool preservedVolatiles = false;
- bool doPtrCast = false;
+ bool preservedVolatiles = false;
+
+ if (castedInst->mArraySize != NULL)
+ {
+ auto mcArraySize = GetOperand(castedInst->mArraySize, false, true);
+ if (mcArraySize.IsImmediate())
+ {
+ ceSize.mImmediate = ceSize.mImmediate * mcArraySize.mImmediate;
+ }
+ else
+ {
+ inHeadAlloca = false;
+ if (ceSize.mImmediate == 1)
+ {
+ ceSize = mcArraySize;
+ }
+ else
+ {
+ ceSize = EmitConst(ceSize.mImmediate, mcArraySize.mType->mSize);
+
+ EmitSizedOp(CeOp_Mul_I8, ceSize.mType->mSize);
+ EmitFrameOffset(ceSize);
+ EmitFrameOffset(ceSize);
+ EmitFrameOffset(mcArraySize);
+ }
+ }
+ }
if (inHeadAlloca)
{
- mFrameSize += size;
+ BF_ASSERT(ceSize.mKind == CeOperandKind_Immediate);
+ mFrameSize += ceSize.mImmediate;
result.mKind = CeOperandKind_AllocaAddr;
result.mFrameOfs = -mFrameSize;
- result.mType = castedInst->mType;
+ result.mType = castedInst->mType;
}
else
{
- Fail("Non-head alloca");
- return;
+ if (ceSize.mKind == CeOperandKind_Immediate)
+ {
+ Emit(CeOp_AdjustSPConst);
+ Emit((int32)-ceSize.mImmediate);
+ }
+ else
+ {
+ Emit(CeOp_AdjustSPNeg);
+ EmitFrameOffset(ceSize);
+ }
+
+ auto ptrType = beModule->mContext->GetPointerTo(allocType);
+
+ result = FrameAlloc(ptrType);
+ Emit(CeOp_GetSP);
+ EmitFrameOffset(result);
}
}
break;
@@ -1164,8 +1226,18 @@ void CeBuilder::Build()
if (ceTarget.mKind == CeOperandKind_AllocaAddr)
{
- result = ceTarget;
- result.mKind = CeOperandKind_FrameOfs;
+ if (inst->mRefCount <= 1)
+ {
+ result = ceTarget;
+ result.mKind = CeOperandKind_FrameOfs;
+ }
+ else
+ {
+ ceTarget.mKind = CeOperandKind_FrameOfs;
+ result = FrameAlloc(ceTarget.mType);
+ EmitSizedOp(CeOp_Move_8, ceTarget, NULL, true);
+ Emit((int32)result.mFrameOfs);
+ }
}
else
{
@@ -1185,21 +1257,6 @@ void CeBuilder::Build()
auto ceLHS = GetOperand(castedInst->mLHS);
auto ceRHS = GetOperand(castedInst->mRHS);
-// if (castedInst->mOpKind == BeBinaryOpKind_Subtract)
-// {
-// if (((mcLHS.IsImmediateFloat()) && (mcLHS.GetImmediateDouble() == 0.0)) ||
-// ((mcLHS.IsImmediateInt()) && (mcLHS.mImmediate == 0)))
-// {
-// auto castedInst = (BeNumericCastInst*)inst;
-//
-// result = AllocVirtualReg(GetType(mcRHS));
-// CreateDefineVReg(result);
-// AllocInst(BeMCInstKind_Mov, result, mcRHS);
-// AllocInst(BeMCInstKind_Neg, result);
-// break;
-// }
-// }
-
switch (castedInst->mOpKind)
{
case BeBinaryOpKind_Add:
@@ -1212,39 +1269,78 @@ void CeBuilder::Build()
EmitBinaryOp(CeOp_Mul_I8, CeOp_Mul_F32, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_SDivide:
- EmitBinaryOp(CeOp_SDiv_I8, CeOp_SDiv_F32, ceLHS, ceRHS, result);
+ EmitBinaryOp(CeOp_Div_I8, CeOp_Div_F32, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_UDivide:
- EmitBinaryOp(CeOp_UDiv_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
+ EmitBinaryOp(CeOp_Div_U8, CeOp_InvalidOp, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_SModulus:
- EmitBinaryOp(CeOp_SMod_I8, CeOp_SMod_F32, ceLHS, ceRHS, result);
+ EmitBinaryOp(CeOp_Mod_I8, CeOp_Mod_F32, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_UModulus:
- EmitBinaryOp(CeOp_UMod_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
+ EmitBinaryOp(CeOp_Mod_U8, CeOp_InvalidOp, ceLHS, ceRHS, result);
+ break;
+ case BeBinaryOpKind_BitwiseAnd:
+ EmitBinaryOp(CeOp_And_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
+ break;
+ case BeBinaryOpKind_BitwiseOr:
+ EmitBinaryOp(CeOp_Or_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
+ break;
+ case BeBinaryOpKind_ExclusiveOr:
+ EmitBinaryOp(CeOp_Xor_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
+ break;
+ case BeBinaryOpKind_LeftShift:
+ EmitBinaryOp(CeOp_Shl_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
+ break;
+ case BeBinaryOpKind_RightShift:
+ EmitBinaryOp(CeOp_Shr_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
+ break;
+ case BeBinaryOpKind_ARightShift:
+ EmitBinaryOp(CeOp_Shr_U8, CeOp_InvalidOp, ceLHS, ceRHS, result);
break;
default:
Fail("Invalid binary op");
}
+ }
+ break;
+ case BeBitCastInst::TypeId:
+ {
+ auto castedInst = (BeBitCastInst*)inst;
+ auto mcValue = GetOperand(castedInst->mValue, false, true);
+ if (castedInst->mToType->IsInt())
+ {
+ BF_ASSERT(castedInst->mToType->mSize == 8);
+ }
+ else
+ BF_ASSERT(castedInst->mToType->IsPointer());
+ auto toType = castedInst->mToType;
-// auto type = GetType(mcLHS);
-//
-// switch (castedInst->mOpKind)
-// {
-// case BeBinaryOpKind_Add: result = AllocBinaryOp(BeMCInstKind_Add, mcLHS, mcRHS, BeMCBinIdentityKind_Any_IsZero); break;
-// case BeBinaryOpKind_Subtract: result = AllocBinaryOp(BeMCInstKind_Sub, mcLHS, mcRHS, BeMCBinIdentityKind_Right_IsZero); break;
-// case BeBinaryOpKind_Multiply: result = AllocBinaryOp(BeMCInstKind_IMul, mcLHS, mcRHS, BeMCBinIdentityKind_Any_IsOne); break;
-// case BeBinaryOpKind_SDivide: result = AllocBinaryOp(BeMCInstKind_IDiv, mcLHS, mcRHS, BeMCBinIdentityKind_Right_IsOne); break;
-// case BeBinaryOpKind_UDivide: result = AllocBinaryOp(BeMCInstKind_Div, mcLHS, mcRHS, BeMCBinIdentityKind_Right_IsOne); break;
-// case BeBinaryOpKind_SModulus: result = AllocBinaryOp(BeMCInstKind_IRem, mcLHS, mcRHS, type->IsFloat() ? BeMCBinIdentityKind_None : BeMCBinIdentityKind_Right_IsOne_Result_Zero); break;
-// case BeBinaryOpKind_UModulus: result = AllocBinaryOp(BeMCInstKind_Rem, mcLHS, mcRHS, type->IsFloat() ? BeMCBinIdentityKind_None : BeMCBinIdentityKind_Right_IsOne_Result_Zero); break;
-// case BeBinaryOpKind_BitwiseAnd: result = AllocBinaryOp(BeMCInstKind_And, mcLHS, mcRHS, BeMCBinIdentityKind_None); break;
-// case BeBinaryOpKind_BitwiseOr: result = AllocBinaryOp(BeMCInstKind_Or, mcLHS, mcRHS, BeMCBinIdentityKind_Any_IsZero); break;
-// case BeBinaryOpKind_ExclusiveOr: result = AllocBinaryOp(BeMCInstKind_Xor, mcLHS, mcRHS, BeMCBinIdentityKind_Any_IsZero); break;
-// case BeBinaryOpKind_LeftShift: result = AllocBinaryOp(BeMCInstKind_Shl, mcLHS, mcRHS, BeMCBinIdentityKind_Any_IsZero); break;
-// case BeBinaryOpKind_RightShift: result = AllocBinaryOp(BeMCInstKind_Shr, mcLHS, mcRHS, BeMCBinIdentityKind_Any_IsZero); break;
-// case BeBinaryOpKind_ARightShift: result = AllocBinaryOp(BeMCInstKind_Sar, mcLHS, mcRHS, BeMCBinIdentityKind_Any_IsZero); break;
-// }
+ if (mcValue.IsImmediate())
+ {
+ if (mcValue.mImmediate == 0)
+ {
+ CeOperand newImmediate;
+ newImmediate.mKind = CeOperandKind_Immediate;
+ newImmediate.mType = toType;
+ result = newImmediate;
+ }
+ else
+ {
+ // Non-zero constant. Weird case, just do an actual MOV
+ result = FrameAlloc(toType);
+ EmitSizedOp(CeOp_Const_8, result, NULL, true);
+ int64 val = mcValue.mImmediate;
+ Emit(&val, toType->mSize);
+ }
+ }
+ else
+ {
+ if (toType->mSize != mcValue.mType->mSize)
+ Fail("Invalid bitcast");
+
+ result = mcValue;
+ result.mType = toType;
+ }
}
break;
case BeNumericCastInst::TypeId:
@@ -1259,46 +1355,210 @@ void CeBuilder::Build()
}
else
{
- auto toType = castedInst->mToType;
- if ((toType->IsIntable()) && (fromType->IsIntable()) && (toType->mSize < fromType->mSize))
+ auto toType = castedInst->mToType;
+ if ((toType->IsIntable()) && (fromType->IsIntable()) && (toType->mSize <= fromType->mSize))
{
// For truncating values, no actual instructions are needed
+ // Note that a copy is not needed because of SSA rules
result = ceValue;
- result.mType = toType;
+ result.mType = toType;
}
else
- {
- bool doSignExtension = (toType->IsIntable()) && (fromType->IsIntable()) && (toType->mSize > fromType->mSize) && (castedInst->mToSigned) && (castedInst->mValSigned);
-// if ((toType->IsFloat()) && (fromType->IsIntable()) && (castedInst->mValSigned))
-// doSignExtension = true;
-
+ {
result = FrameAlloc(toType);
CeOp op = CeOp_InvalidOp;
-
- if (doSignExtension)
- {
- switch (fromType->mTypeCode)
+
+ BeTypeCode fromTypeCode = fromType->mTypeCode;
+ BeTypeCode toTypeCode = toType->mTypeCode;
+
+ if (castedInst->mToSigned)
+ {
+ switch (fromTypeCode)
{
+ case BeTypeCode_Int8:
+ switch (toTypeCode)
+ {
+ case BeTypeCode_Int16:
+ op = CeOp_Conv_I8_I16;
+ break;
+ case BeTypeCode_Int32:
+ op = CeOp_Conv_I8_I32;
+ break;
+ case BeTypeCode_Int64:
+ op = CeOp_Conv_I8_I64;
+ break;
+ case BeTypeCode_Float:
+ op = CeOp_Conv_I8_F32;
+ break;
+ case BeTypeCode_Double:
+ op = CeOp_Conv_I8_F64;
+ break;
+ }
+ break;
+ case BeTypeCode_Int16:
+ switch (toTypeCode)
+ {
+ case BeTypeCode_Int32:
+ op = CeOp_Conv_I16_I32;
+ break;
+ case BeTypeCode_Int64:
+ op = CeOp_Conv_I16_I64;
+ break;
+ case BeTypeCode_Float:
+ op = CeOp_Conv_I16_F32;
+ break;
+ case BeTypeCode_Double:
+ op = CeOp_Conv_I16_F64;
+ break;
+ }
+ break;
case BeTypeCode_Int32:
- switch (toType->mTypeCode)
+ switch (toTypeCode)
{
case BeTypeCode_Int64:
op = CeOp_Conv_I32_I64;
+ break;
+ case BeTypeCode_Float:
+ op = CeOp_Conv_I32_F32;
+ break;
+ case BeTypeCode_Double:
+ op = CeOp_Conv_I32_F64;
+ break;
}
+ break;
+ case BeTypeCode_Int64:
+ switch (toTypeCode)
+ {
+ case BeTypeCode_Float:
+ op = CeOp_Conv_I64_F32;
+ break;
+ case BeTypeCode_Double:
+ op = CeOp_Conv_I64_F64;
+ break;
+ }
+ break;
+ case BeTypeCode_Float:
+ switch (toTypeCode)
+ {
+ case BeTypeCode_Int8:
+ op = CeOp_Conv_F32_I8;
+ break;
+ case BeTypeCode_Int16:
+ op = CeOp_Conv_F32_I16;
+ break;
+ case BeTypeCode_Int32:
+ op = CeOp_Conv_F32_I32;
+ break;
+ case BeTypeCode_Int64:
+ op = CeOp_Conv_F32_I64;
+ break;
+ case BeTypeCode_Double:
+ op = CeOp_Conv_F32_F64;
+ break;
+ }
+ break;
+ case BeTypeCode_Double:
+ switch (toTypeCode)
+ {
+ case BeTypeCode_Int8:
+ op = CeOp_Conv_F64_I8;
+ break;
+ case BeTypeCode_Int16:
+ op = CeOp_Conv_F64_I16;
+ break;
+ case BeTypeCode_Int32:
+ op = CeOp_Conv_F64_I32;
+ break;
+ case BeTypeCode_Int64:
+ op = CeOp_Conv_F64_I64;
+ break;
+ case BeTypeCode_Float:
+ op = CeOp_Conv_F64_F32;
+ break;
+ }
+ break;
}
}
else
{
-
+ switch (fromTypeCode)
+ {
+ case BeTypeCode_Int8:
+ switch (toTypeCode)
+ {
+ case BeTypeCode_Int16:
+ op = CeOp_Conv_U8_U16;
+ break;
+ case BeTypeCode_Int32:
+ op = CeOp_Conv_U8_U32;
+ break;
+ case BeTypeCode_Int64:
+ op = CeOp_Conv_U8_U64;
+ break;
+ case BeTypeCode_Float:
+ op = CeOp_Conv_I8_F32;
+ break;
+ case BeTypeCode_Double:
+ op = CeOp_Conv_I8_F64;
+ break;
+ }
+ break;
+ case BeTypeCode_Int16:
+ switch (toTypeCode)
+ {
+ case BeTypeCode_Int32:
+ op = CeOp_Conv_U16_U32;
+ break;
+ case BeTypeCode_Int64:
+ op = CeOp_Conv_U16_U64;
+ break;
+ case BeTypeCode_Float:
+ op = CeOp_Conv_U16_F32;
+ break;
+ case BeTypeCode_Double:
+ op = CeOp_Conv_U16_F64;
+ break;
+ }
+ break;
+ case BeTypeCode_Int32:
+ switch (toTypeCode)
+ {
+ case BeTypeCode_Int64:
+ op = CeOp_Conv_U32_U64;
+ break;
+ case BeTypeCode_Float:
+ op = CeOp_Conv_U32_F32;
+ break;
+ case BeTypeCode_Double:
+ op = CeOp_Conv_U32_F64;
+ break;
+ }
+ break;
+ case BeTypeCode_Int64:
+ switch (toTypeCode)
+ {
+ case BeTypeCode_Float:
+ op = CeOp_Conv_I64_F32;
+ break;
+ case BeTypeCode_Double:
+ op = CeOp_Conv_I64_F64;
+ break;
+ }
+ break;
+ }
}
if (op == CeOp_InvalidOp)
+ {
Fail("Invalid conversion op");
-
- Emit(op);
- EmitFrameOffset(result);
- EmitFrameOffset(ceValue);
+ }
+ else
+ {
+ Emit(op);
+ EmitFrameOffset(result);
+ EmitFrameOffset(ceValue);
+ }
}
}
}
@@ -1310,7 +1570,7 @@ void CeBuilder::Build()
auto mcPtr = GetOperand(castedInst->mPtr, true);
if (mcPtr.mKind == CeOperandKind_AllocaAddr)
- {
+ {
EmitSizedOp(CeOp_Move_8, mcVal, NULL, true);
Emit((int32)mcPtr.mFrameOfs);
}
@@ -1346,6 +1606,15 @@ void CeBuilder::Build()
switch (castedInst->mCmpKind)
{
+ case BeCmpKind_EQ:
+ iOp = CeOp_Cmp_EQ_I8;
+ fOp = CeOp_Cmp_EQ_F32;
+ break;
+ case BeCmpKind_NE:
+ iOp = CeOp_Cmp_NE_I8;
+ fOp = CeOp_Cmp_NE_F32;
+ break;
+
case BeCmpKind_SLT:
iOp = CeOp_Cmp_SLT_I8;
fOp = CeOp_Cmp_SLT_F32;
@@ -1360,6 +1629,21 @@ void CeBuilder::Build()
case BeCmpKind_ULE:
iOp = CeOp_Cmp_ULE_I8;
break;
+
+ case BeCmpKind_SGT:
+ iOp = CeOp_Cmp_SGT_I8;
+ fOp = CeOp_Cmp_SGT_F32;
+ break;
+ case BeCmpKind_UGT:
+ iOp = CeOp_Cmp_UGT_I8;
+ break;
+ case BeCmpKind_SGE:
+ iOp = CeOp_Cmp_SGE_I8;
+ fOp = CeOp_Cmp_SGE_F32;
+ break;
+ case BeCmpKind_UGE:
+ iOp = CeOp_Cmp_UGE_I8;
+ break;
}
if (iOp == CeOp_InvalidOp)
@@ -1434,32 +1718,46 @@ void CeBuilder::Build()
{
auto ptrValue = FrameAlloc(elementPtrType);
result = ptrValue;
- }
-// auto ptrValue = AllocVirtualReg(elementPtrType);
-// auto ptrInfo = GetVRegInfo(ptrValue);
-// ptrInfo->mIsExpr = true;
-// ptrInfo->mRelTo = result;
-// CreateDefineVReg(ptrValue);
-// result = ptrValue;
-//
-// BeMCOperand mcRelOffset;
-// int relScale = 1;
-// if (mcIdx1.IsImmediate())
-// {
-// mcRelOffset = BeMCOperand::FromImmediate(mcIdx1.mImmediate * arrayType->mElementType->mSize);
-// }
-// else
-// {
-// mcRelOffset = mcIdx1;
-// relScale = arrayType->mElementType->mSize;
-// }
-//
-// result = AllocRelativeVirtualReg(elementPtrType, result, mcRelOffset, relScale);
-// // The def is primary to create a single 'master location' for the GEP vreg to become legalized before use
-// CreateDefineVReg(result);
-// //TODO: Always correct?
-// result.mKind = BeMCOperandKind_VReg;
+ result = FrameAlloc(elementPtrType);
+
+ if (mPtrSize == 4)
+ {
+ auto mcElementSize = FrameAlloc(mIntPtrType);
+ Emit(CeOp_Const_32);
+ EmitFrameOffset(mcElementSize);
+ Emit((int32)arrayType->mElementType->mSize);
+
+ auto ofsValue = FrameAlloc(mIntPtrType);
+ Emit(CeOp_Mul_I32);
+ EmitFrameOffset(ofsValue);
+ EmitFrameOffset(ceIdx1);
+ EmitFrameOffset(mcElementSize);
+
+ Emit(CeOp_Add_I32);
+ EmitFrameOffset(result);
+ EmitFrameOffset(ceVal);
+ EmitFrameOffset(ofsValue);
+ }
+ else
+ {
+ auto mcElementSize = FrameAlloc(mIntPtrType);
+ Emit(CeOp_Const_64);
+ EmitFrameOffset(mcElementSize);
+ Emit((int64)arrayType->mElementType->mSize);
+
+ auto ofsValue = FrameAlloc(mIntPtrType);
+ Emit(CeOp_Mul_I64);
+ EmitFrameOffset(ofsValue);
+ EmitFrameOffset(ceIdx1);
+ EmitFrameOffset(mcElementSize);
+
+ Emit(CeOp_Add_I64);
+ EmitFrameOffset(result);
+ EmitFrameOffset(ceVal);
+ EmitFrameOffset(ofsValue);
+ }
+ }
}
else
Fail("Invalid GEP");
@@ -1493,7 +1791,7 @@ void CeBuilder::Build()
Fail("Invalid gep target");
}
- auto elementPtrType = beModule->mContext->GetPointerTo(elementType);
+ auto elementPtrType = beModule->mContext->GetPointerTo(elementType);
if (byteOffset != 0)
{
@@ -1510,29 +1808,61 @@ void CeBuilder::Build()
}
}
else
- {
- // It's temping to do a (IsNonZero) precondition, but if we make a reference to a VReg that is NOT in Addr form,
- // then this will encode that so we will know we need to do a Load on that value at the Def during legalization
+ {
+ CeOperand mcRelOffset;
+ int relScale = 1;
+ if (ceIdx0.IsImmediate())
+ {
+ int byteOffset = ceIdx0.mImmediate * ptrType->mElementType->mSize;
+ if (byteOffset != 0)
+ {
+ result = FrameAlloc(ptrType);
+ Emit((CeOp)(CeOp_AddConst_I32));
+ EmitFrameOffset(result);
+ EmitFrameOffset(ceVal);
+ Emit((int32)byteOffset);
+ }
+ }
+ else
+ {
+ result = FrameAlloc(ptrType);
+ if (mPtrSize == 4)
+ {
+ auto mcElementSize = FrameAlloc(mIntPtrType);
+ Emit(CeOp_Const_32);
+ EmitFrameOffset(mcElementSize);
+ Emit((int32)ptrType->mElementType->mSize);
- Fail("Unhandled gep");
+ auto ofsValue = FrameAlloc(mIntPtrType);
+ Emit(CeOp_Mul_I32);
+ EmitFrameOffset(ofsValue);
+ EmitFrameOffset(ceIdx0);
+ EmitFrameOffset(mcElementSize);
-// BeMCOperand mcRelOffset;
-// int relScale = 1;
-// if (mcIdx0.IsImmediate())
-// {
-// mcRelOffset = BeMCOperand::FromImmediate(mcIdx0.mImmediate * ptrType->mElementType->mSize);
-// }
-// else
-// {
-// mcRelOffset = mcIdx0;
-// relScale = ptrType->mElementType->mSize;
-// }
-//
-// result = AllocRelativeVirtualReg(ptrType, result, mcRelOffset, relScale);
-// // The def is primary to create a single 'master location' for the GEP vreg to become legalized before use
-// CreateDefineVReg(result);
-// //TODO: Always correct?
-// result.mKind = BeMCOperandKind_VReg;
+ Emit(CeOp_Add_I32);
+ EmitFrameOffset(result);
+ EmitFrameOffset(ceVal);
+ EmitFrameOffset(ofsValue);
+ }
+ else
+ {
+ auto mcElementSize = FrameAlloc(mIntPtrType);
+ Emit(CeOp_Const_64);
+ EmitFrameOffset(mcElementSize);
+ Emit((int64)ptrType->mElementType->mSize);
+
+ auto ofsValue = FrameAlloc(mIntPtrType);
+ Emit(CeOp_Mul_I64);
+ EmitFrameOffset(ofsValue);
+ EmitFrameOffset(ceIdx0);
+ EmitFrameOffset(mcElementSize);
+
+ Emit(CeOp_Add_I64);
+ EmitFrameOffset(result);
+ EmitFrameOffset(ceVal);
+ EmitFrameOffset(ofsValue);
+ }
+ }
}
}
break;
@@ -1577,11 +1907,21 @@ void CeBuilder::Build()
break;
case BeNegInst::TypeId:
{
- auto castedInst = (BeNumericCastInst*)inst;
+ auto castedInst = (BeNegInst*)inst;
auto ceValue = GetOperand(castedInst->mValue);
EmitUnaryOp(CeOp_Neg_I8, CeOp_Neg_F32, ceValue, result);
}
break;
+ case BeNotInst::TypeId:
+ {
+ auto castedInst = (BeNotInst*)inst;
+ auto ceValue = GetOperand(castedInst->mValue);
+ if (ceValue.mType->mTypeCode == BeTypeCode_Boolean)
+ EmitUnaryOp(CeOp_Not_I1, CeOp_InvalidOp, ceValue, result);
+ else
+ EmitUnaryOp(CeOp_Not_I8, CeOp_InvalidOp, ceValue, result);
+ }
+ break;
case BeSwitchInst::TypeId:
{
auto castedInst = (BeSwitchInst*)inst;
@@ -1613,43 +1953,158 @@ void CeBuilder::Build()
//SizedArray args;
int callIdx = -1;
+ BeFunctionType* beFuncType = NULL;
+ CeOperand virtTarget;
+ int ifaceTypeId = -1;
+ int virtualTableIdx = -1;
if (auto intrin = BeValueDynCast(castedInst->mFunc))
{
- Fail("Intrinsics not allowed");
+ switch (intrin->mKind)
+ {
+ case BfIRIntrinsic_Cast:
+ {
+ result = GetOperand(castedInst->mArgs[0].mValue);
+ result.mType = intrin->mReturnType;
+ }
+ break;
+ case BfIRIntrinsic_MemCpy:
+ {
+ CeOperand ceDestPtr = GetOperand(castedInst->mArgs[0].mValue);
+ CeOperand ceSrcPtr = GetOperand(castedInst->mArgs[1].mValue);
+ CeOperand ceSize = GetOperand(castedInst->mArgs[2].mValue);
+
+ Emit(CeOp_MemCpy);
+ EmitFrameOffset(ceDestPtr);
+ EmitFrameOffset(ceSrcPtr);
+ EmitFrameOffset(ceSize);
+ }
+ break;
+ default:
+ Emit(CeOp_Error);
+ Emit((int32)CeErrorKind_Intrinsic);
+ break;
+ }
}
else if (auto beFunction = BeValueDynCast(castedInst->mFunc))
{
+ beFuncType = beFunction->GetFuncType();
+
+ if (beFunction->mName == "malloc")
+ {
+ result = FrameAlloc(beFuncType->mReturnType);
+ auto ceSize = GetOperand(castedInst->mArgs[0].mValue);
+ Emit(CeOp_Malloc);
+ EmitFrameOffset(result);
+ EmitFrameOffset(ceSize);
+ break;
+ }
+
+ if (beFunction->mName == "free")
+ {
+ auto cePtr = GetOperand(castedInst->mArgs[0].mValue);
+ Emit(CeOp_Free);
+ EmitFrameOffset(cePtr);
+ break;
+ }
+
int* callIdxPtr = NULL;
if (mFunctionMap.TryAdd(beFunction, NULL, &callIdxPtr))
{
+ CeFunctionInfo* ceFunctionInfo = NULL;
+ mCeMachine->mNamedFunctionMap.TryGetValue(beFunction->mName, &ceFunctionInfo);
+ if (ceFunctionInfo != NULL)
+ ceFunctionInfo->mRefCount++;
+ else
+ {
+ Fail(StrFormat("Unable to locate method %s", beFunction->mName.c_str()));
+ }
+
CeCallEntry callEntry;
- callEntry.mFunctionName = beFunction->mName;
+ callEntry.mFunctionInfo = ceFunctionInfo;
*callIdxPtr = (int)mCeFunction->mCallTable.size();
mCeFunction->mCallTable.Add(callEntry);
}
+
+ callIdx = *callIdxPtr;
+ }
+ else if (auto beGetVirtualFunc = BeValueDynCast(castedInst->mFunc))
+ {
+ virtTarget = GetOperand(beGetVirtualFunc->mValue);
+ virtualTableIdx = beGetVirtualFunc->mVirtualTableIdx;
+
+ auto resultType = beGetVirtualFunc->GetType();
+ BF_ASSERT(resultType->IsPointer());
+ beFuncType = (BeFunctionType*)((BePointerType*)resultType)->mElementType;
+ }
+ else if (auto beGetInterfaceFunc = BeValueDynCast(castedInst->mFunc))
+ {
+ virtTarget = GetOperand(beGetInterfaceFunc->mValue);
+ ifaceTypeId = beGetInterfaceFunc->mIFaceTypeId;
+ virtualTableIdx = beGetInterfaceFunc->mVirtualTableIdx;
- callIdx = *callIdxPtr;
+ auto resultType = beGetInterfaceFunc->GetType();
+ BF_ASSERT(resultType->IsPointer());
+ beFuncType = (BeFunctionType*)((BePointerType*)resultType)->mElementType;
+ }
+ else
+ {
+ Emit(CeOp_Error);
+ Emit((int32)CeErrorKind_FunctionPointer);
+
+ auto funcType = castedInst->mFunc->GetType();
+ if (funcType->IsPointer())
+ {
+ auto ptrType = (BePointerType*)funcType;
+ if (ptrType->mElementType->mTypeCode == BeTypeCode_Function)
+ {
+ auto beFuncType = (BeFunctionType*)ptrType->mElementType;
+ if (beFuncType->mReturnType->mSize > 0)
+ result = FrameAlloc(beFuncType->mReturnType);
+ }
+ }
+ }
+
+ if ((callIdx != -1) || (virtualTableIdx != -1))
+ {
+ CeOperand thisOperand;
for (int argIdx = (int)castedInst->mArgs.size() - 1; argIdx >= 0; argIdx--)
{
auto& arg = castedInst->mArgs[argIdx];
auto ceArg = GetOperand(arg.mValue);
+ if (argIdx == 0)
+ thisOperand = ceArg;
EmitSizedOp(CeOp_Push_8, ceArg, NULL, true);
}
int stackAdjust = 0;
-
- auto beFuncType = beFunction->GetFuncType();
+
if (beFuncType->mReturnType->mSize > 0)
{
- Emit(CeOp_AdjustSP);
+ Emit(CeOp_AdjustSPConst);
Emit((int32)-beFuncType->mReturnType->mSize);
stackAdjust += beFuncType->mReturnType->mSize;
}
-
- Emit(CeOp_Call);
- Emit((int32)callIdx);
+
+ if (ifaceTypeId != -1)
+ {
+ Emit(CeOp_Call_IFace);
+ EmitFrameOffset(thisOperand);
+ Emit((int32)ifaceTypeId);
+ Emit((int32)virtualTableIdx);
+ }
+ else if (virtualTableIdx != -1)
+ {
+ Emit(CeOp_Call_Virt);
+ EmitFrameOffset(thisOperand);
+ Emit((int32)virtualTableIdx);
+ }
+ else
+ {
+ Emit(CeOp_Call);
+ Emit((int32)callIdx);
+ }
if (beFuncType->mReturnType->mSize > 0)
{
@@ -1659,26 +2114,79 @@ void CeBuilder::Build()
if (stackAdjust > 0)
{
- Emit(CeOp_AdjustSP);
+ Emit(CeOp_AdjustSPConst);
Emit(stackAdjust);
}
}
- else
+ }
+ break;
+ case BeMemSetInst::TypeId:
+ {
+ auto castedInst = (BeMemSetInst*)inst;
+ auto ceAddr = GetOperand(castedInst->mAddr);
+
+ if (auto constVal = BeValueDynCast(castedInst->mVal))
{
- Fail("Cannot call through function pointers");
-// auto funcPtrType = castedInst->mFunc->GetType();
-// if (funcPtrType->IsPointer())
-// {
-// auto elementType = ((BePointerType*)funcPtrType)->mElementType;
-// if (elementType->mTypeCode == BeTypeCode_Function)
-// {
-// isVarArg = ((BeFunctionType*)elementType)->mIsVarArg;
-// }
-// }
-//
-// returnType = castedInst->GetType();
-// ceFunc = GetOperand(castedInst->mFunc);
- }
+ if (auto constSize = BeValueDynCast(castedInst->mSize))
+ {
+ if (constVal->mUInt8 == 0)
+ {
+ Emit(CeOp_MemSet_Const);
+ EmitFrameOffset(ceAddr);
+ Emit((uint8)0);
+ Emit((int32)constSize->mUInt32);
+ break;
+ }
+ }
+ }
+
+ auto ceVal = GetOperand(castedInst->mVal);
+ auto ceSize = GetOperand(castedInst->mSize);
+
+ Emit(CeOp_MemSet);
+ EmitFrameOffset(ceAddr);
+ EmitFrameOffset(ceVal);
+ EmitFrameOffset(ceSize);
+ }
+ break;
+ case BeFenceInst::TypeId:
+ break;
+ case BeStackSaveInst::TypeId:
+ {
+ result = FrameAlloc(mIntPtrType);
+ Emit(CeOp_GetSP);
+ EmitFrameOffset(result);
+ }
+ break;
+ case BeStackRestoreInst::TypeId:
+ {
+ auto castedInst = (BeStackRestoreInst*)inst;
+
+ auto mcStackVal = GetOperand(castedInst->mStackVal);
+ Emit(CeOp_SetSP);
+ EmitFrameOffset(mcStackVal);
+ }
+ break;
+ case BeConstEvalGetType::TypeId:
+ {
+ auto castedInst = (BeConstEvalGetType*)inst;
+ result.mKind = CeOperandKind_Immediate;
+ result.mImmediate = castedInst->mTypeId;
+ result.mType = beModule->mContext->GetPrimitiveType(BeTypeCode_Int32);
+ }
+ break;
+ case BeConstEvalDynamicCastCheck::TypeId:
+ {
+ auto castedInst = (BeConstEvalDynamicCastCheck*)inst;
+ auto mcValue = GetOperand(castedInst->mValue);
+
+ auto ptrType = beModule->mContext->GetPrimitiveType(BeTypeCode_NullPtr);
+ result = FrameAlloc(ptrType);
+
+ Emit(CeOp_DynamicCastCheck);
+ EmitFrameOffset(result);
+ EmitFrameOffset(mcValue);
+ Emit((int32)castedInst->mTypeId);
}
break;
default:
@@ -1702,7 +2210,10 @@ void CeBuilder::Build()
if (mDbgFileMap.TryAdd(dbgFile, NULL, &valuePtr))
{
fileIdx = (int)mCeFunction->mFiles.size();
- mCeFunction->mFiles.Add(dbgFile->mFileName);
+ String filePath = dbgFile->mDirectory;
+ filePath.Append(DIR_SEP_CHAR);
+ filePath += dbgFile->mFileName;
+ mCeFunction->mFiles.Add(filePath);
*valuePtr = fileIdx;
}
else
@@ -1749,21 +2260,90 @@ void CeBuilder::Build()
CeMachine::CeMachine(BfCompiler* compiler)
{
mCompiler = compiler;
- mCeModule = NULL;
- mStackMin = NULL;
+ mCeModule = NULL;
mRevision = 0;
+ mExecuteId = 0;
mCurTargetSrc = NULL;
mCurModule = NULL;
+ mHeap = NULL;
}
CeMachine::~CeMachine()
{
delete mCeModule;
+ delete mHeap;
+
+ for (auto kv : mFunctions)
+ {
+ auto functionInfo = kv.mValue;
+ delete functionInfo;
+ }
}
BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str)
{
- return mCurModule->Fail(str, mCurTargetSrc);
+ auto bfError = mCurModule->Fail("Unable to const-evaluate function", mCurTargetSrc);
+ if (bfError == NULL)
+ return NULL;
+
+ auto passInstance = mCompiler->mPassInstance;
+
+ for (int stackIdx = mCallStack.size(); stackIdx >= 0; stackIdx--)
+ {
+ bool isHeadEntry = stackIdx == mCallStack.size();
+ auto* ceFrame = (isHeadEntry) ? &curFrame : &mCallStack[stackIdx];
+
+ auto ceFunction = ceFrame->mFunction;
+
+ int i = 0;
+ CeEmitEntry* emitEntry = NULL;
+
+ if (!ceFunction->mCode.IsEmpty())
+ {
+ int lo = 0;
+ int hi = ceFunction->mEmitTable.size() - 1;
+ int instIdx = ceFrame->mInstPtr - &ceFunction->mCode[0] - 1;
+ while (lo <= hi)
+ {
+ i = (lo + hi) / 2;
+ emitEntry = &ceFunction->mEmitTable.mVals[i];
+ //int c = midVal <=> value;
+ if (emitEntry->mCodePos == instIdx) break;
+ if (emitEntry->mCodePos < instIdx)
+ lo = i + 1;
+ else
+ hi = i - 1;
+ }
+ if ((emitEntry != NULL) && (emitEntry->mCodePos > instIdx) && (i > 0))
+ emitEntry = &ceFunction->mEmitTable.mVals[i - 1];
+ }
+
+ StringT<256> err;
+ if (isHeadEntry)
+ err = str;
+ else
+ {
+ StrFormat("in const evaluation of");
+ err += mCeModule->MethodToString(ceFunction->mMethodInstance, BfMethodNameFlag_OmitParams);
+ //err += "(";
+ //err += ")";
+ }
+
+ if (emitEntry != NULL)
+ err += StrFormat(" at line% d:%d in %s", emitEntry->mLine + 1, emitEntry->mColumn + 1, ceFunction->mFiles[emitEntry->mFile].c_str());
+
+ auto moreInfo = passInstance->MoreInfo(err);
+ if ((moreInfo != NULL) && (emitEntry != NULL))
+ {
+ BfErrorLocation* location = new BfErrorLocation();
+ location->mFile = ceFunction->mFiles[emitEntry->mFile];
+ location->mLine = emitEntry->mLine;
+ location->mColumn = emitEntry->mColumn;
+ moreInfo->mLocation = location;
+ }
+ }
+
+ return bfError;
}
void CeMachine::Init()
@@ -1783,6 +2363,30 @@ void CeMachine::Init()
mCeModule->mWantsIRIgnoreWrites = false;
}
+uint8* CeMachine::CeMalloc(int size)
+{
+#ifdef CE_ENABLE_HEAP
+ auto heapRef = mHeap->Alloc(size);
+ auto ceAddr = BF_CE_STACK_SIZE + heapRef;
+ int sizeDelta = (ceAddr + size) - mMemory.mSize;
+ if (sizeDelta > 0)
+ mMemory.GrowUninitialized(sizeDelta);
+ return mMemory.mVals + ceAddr;
+#else
+ return mMemory.GrowUninitialized(size);
+#endif
+}
+
+bool CeMachine::CeFree(addr_ce addr)
+{
+#ifdef CE_ENABLE_HEAP
+ ContiguousHeap::AllocRef heapRef = addr - BF_CE_STACK_SIZE;
+ return mHeap->Free(heapRef);
+#else
+ return true;
+#endif
+}
+
BeContext* CeMachine::GetBeContext()
{
if (mCeModule == NULL)
@@ -1807,14 +2411,44 @@ void CeMachine::CompileStarted()
}
}
+void CeMachine::DerefMethodInfo(CeFunctionInfo* ceFunctionInfo)
+{
+ ceFunctionInfo->mRefCount--;
+ if (ceFunctionInfo->mRefCount > 0)
+ return;
+ BF_ASSERT(ceFunctionInfo->mMethodInstance == NULL);
+
+ auto itr = mNamedFunctionMap.Find(ceFunctionInfo->mName);
+ if (itr->mValue == ceFunctionInfo)
+ mNamedFunctionMap.Remove(itr);
+ delete ceFunctionInfo;
+}
+
void CeMachine::RemoveMethod(BfMethodInstance* methodInstance)
{
auto itr = mFunctions.Find(methodInstance);
- auto ceFunction = itr->mValue;
+ auto ceFunctionInfo = itr->mValue;
BF_ASSERT(itr != mFunctions.end());
if (itr != mFunctions.end())
- {
- mNamedFunctionMap.Remove(ceFunction->mName);
+ {
+ auto ceFunction = ceFunctionInfo->mCeFunction;
+ for (auto& callEntry : ceFunction->mCallTable)
+ {
+ if (callEntry.mFunctionInfo != NULL)
+ DerefMethodInfo(callEntry.mFunctionInfo);
+ }
+ delete ceFunction;
+ ceFunctionInfo->mCeFunction = NULL;
+ ceFunctionInfo->mMethodInstance = NULL;
+
+ if (ceFunctionInfo->mRefCount > 1)
+ {
+ // Generate a methodref
+ ceFunctionInfo->mMethodRef = methodInstance;
+ }
+
+ DerefMethodInfo(ceFunctionInfo);
+
mFunctions.Remove(itr);
}
}
@@ -1888,15 +2522,21 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant)
}
}
#define CE_CHECKSTACK() \
- if (stackPtr < mStackMin) \
+ if (stackPtr < memStart) \
{ \
_Fail("Stack overflow"); \
return false; \
}
+#define CE_CHECKALLOC(SIZE) \
+ if ((uintptr)memSize + (uintptr)SIZE > BF_CE_MAX_MEMORY) \
+ { \
+ _Fail("Maximum memory size exceeded"); \
+ }
+
// This check will fail for addresses < 64K (null pointer), or out-of-bounds
#define CE_CHECKADDR(ADDR, SIZE) \
- if (((ADDR) - 0x10000) + sizeof(uint32) > (BF_CE_STACK_SIZE - 0x10000)) \
+ if (((ADDR) - 0x10000) + (SIZE) > (memSize - 0x10000)) \
{ \
_Fail("Access violation"); \
return false; \
@@ -1911,6 +2551,25 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant)
auto rhs = CE_GETFRAME(T); \
result = lhs OP rhs; \
}
+#define CEOP_BIN_DIV(OP, T) \
+ { \
+ auto& result = CE_GETFRAME(T); \
+ auto lhs = CE_GETFRAME(T); \
+ auto rhs = CE_GETFRAME(T); \
+ if (rhs == 0) \
+ { \
+ _Fail("Division by zero"); \
+ return false; \
+ } \
+ result = lhs OP rhs; \
+ }
+#define CEOP_BIN2(OP, TLHS, TRHS) \
+ { \
+ auto& result = CE_GETFRAME(TLHS); \
+ auto lhs = CE_GETFRAME(TLHS); \
+ auto rhs = CE_GETFRAME(TRHS); \
+ result = lhs OP rhs; \
+ }
#define CEOP_BIN_CONST(OP, T) \
{ \
auto& result = CE_GETFRAME(T); \
@@ -1940,14 +2599,14 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant)
#define CE_LOAD(T) \
{ \
auto& result = CE_GETFRAME(T); \
- auto ceAddr = CE_GETFRAME(uint32); \
+ auto ceAddr = CE_GETFRAME(addr_ce); \
CE_CHECKADDR(ceAddr, sizeof(T)); \
result = *(T*)(memStart + ceAddr); \
}
#define CE_STORE(T) \
{ \
auto val = CE_GETFRAME(T); \
- auto ceAddr = CE_GETFRAME(uint32); \
+ auto ceAddr = CE_GETFRAME(addr_ce); \
CE_CHECKADDR(ceAddr, sizeof(T)); \
*(T*)(memStart + ceAddr) = val; \
}
@@ -1970,11 +2629,26 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant)
result = *((T*)stackPtr); \
stackPtr += sizeof(T); \
}
+#define CE_CALL(CEFUNC) \
+ if (CEFUNC == NULL) \
+ { \
+ _Fail("Unable to locate function entry"); \
+ return false; \
+ } \
+ mCallStack.Add(_GetCurFrame()); \
+ ceFunction = CEFUNC; \
+ framePtr = stackPtr; \
+ stackPtr -= ceFunction->mFrameSize; \
+ instPtr = &ceFunction->mCode[0]; \
+ CE_CHECKSTACK();
bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr)
-{
+{
+ mExecuteId++;
+
CeFunction* ceFunction = startFunction;
uint8* memStart = &mMemory[0];
+ int memSize = mMemory.mSize;
uint8* instPtr = (ceFunction->mCode.IsEmpty()) ? NULL : &ceFunction->mCode[0];
uint8* stackPtr = startStackPtr;
uint8* framePtr = startFramePtr;
@@ -1983,34 +2657,134 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
{
CeFrame ceFrame;
ceFrame.mFunction = ceFunction;
- ceFrame.mFramePtr = framePtr;
- ceFrame.mStackPtr = stackPtr;
+ ceFrame.mFrameAddr = framePtr - memStart;
+ ceFrame.mStackAddr = stackPtr - memStart;
ceFrame.mInstPtr = instPtr;
return ceFrame;
};
+ auto _FixVariables = [&]()
+ {
+ memSize = mMemory.mSize;
+ intptr memOffset = &mMemory[0] - memStart;
+ if (memOffset == 0)
+ return;
+ memStart += memOffset;
+ stackPtr += memOffset;
+ framePtr += memOffset;
+ };
+
auto _Fail = [&](const StringImpl& error)
{
Fail(_GetCurFrame(), error);
};
- auto _CheckFunction = [&](CeFunction* checkFunction)
+ auto _CheckFunction = [&](CeFunction* checkFunction, bool& handled)
{
+ if (checkFunction == NULL)
+ {
+ Fail(_GetCurFrame(), "Const method not available");
+ return false;
+ }
+ if (checkFunction->mFunctionKind == CeFunctionKind_OOB)
+ {
+ Fail(_GetCurFrame(), "Array out of bounds");
+ return false;
+ }
+ else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite)
+ {
+ int32 ptrVal = *(int32*)((uint8*)stackPtr + 0);
+ auto size = *(int32*)(stackPtr + mCeModule->mSystem->mPtrSize);
+ CE_CHECKADDR(ptrVal, size);
+ char* strPtr = (char*)(ptrVal + memStart);
+ String str;
+ str.Insert(0, strPtr, size);
+ OutputDebugStr(str);
+ handled = true;
+ return true;
+ }
+ else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite_Int)
+ {
+ int32 intVal = *(int32*)((uint8*)stackPtr + 0);
+ OutputDebugStrF("Debug Val: %d\n", intVal);
+ handled = true;
+ return true;
+ }
+ else if (checkFunction->mFunctionKind == CeFunctionKind_FatalError)
+ {
+ int32 strInstAddr = *(int32*)((uint8*)stackPtr + 0);
+ CE_CHECKADDR(strInstAddr, 0);
+
+ BfTypeInstance* stringTypeInst = (BfTypeInstance*)mCeModule->ResolveTypeDef(mCompiler->mStringTypeDef, BfPopulateType_Data);
+
+ auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize;
+ auto lenOffset = stringTypeInst->mFieldInstances[0].mDataOffset;
+ auto allocSizeOffset = stringTypeInst->mFieldInstances[1].mDataOffset;
+ auto ptrOffset = stringTypeInst->mFieldInstances[2].mDataOffset;
+
+ uint8* strInst = (uint8*)(strInstAddr + memStart);
+ int32 lenVal = *(int32*)(strInst + lenOffset);
+
+ char* charPtr = NULL;
+
+ if (lenByteCount == 4)
+ {
+ int32 allocSizeVal = *(int32*)(strInst + allocSizeOffset);
+ if ((allocSizeVal & 0x40000000) != 0)
+ {
+ int32 ptrVal = *(int32*)(strInst + ptrOffset);
+ charPtr = (char*)(ptrVal + memStart);
+ }
+ else
+ {
+ charPtr = (char*)(strInst + ptrOffset);
+ }
+ }
+
+ int32 ptrVal = *(int32*)(strInst + ptrOffset);
+
+ String error = "Fatal Error: ";
+ if (charPtr != NULL)
+ error.Insert(error.length(), charPtr, lenVal);
+ _Fail(error);
+
+ return false;
+ }
+ else if (checkFunction->mFunctionKind != CeFunctionKind_Normal)
+ {
+ Fail(_GetCurFrame(), StrFormat("Unable to invoke extern method '%s'", mCeModule->MethodToString(checkFunction->mMethodInstance).c_str()));
+ return false;
+ }
+
if (!checkFunction->mFailed)
return true;
auto error = Fail(_GetCurFrame(), "Method call failed");
if ((error != NULL) && (!checkFunction->mGenError.IsEmpty()))
- mCeModule->mCompiler->mPassInstance->MoreInfo("Const Method Generation Error: " + checkFunction->mGenError);
+ mCompiler->mPassInstance->MoreInfo("Const Method Generation Error: " + checkFunction->mGenError);
return false;
};
+
+ //
+ {
+ bool handled = false;
+ if (!_CheckFunction(ceFunction, handled))
+ return false;
+ if (handled)
+ return true;
+ }
- if (!_CheckFunction(ceFunction))
- return false;
+ volatile bool* cancelPtr = &mCompiler->mCanceling;
int callCount = 0;
while (true)
{
+ if (*cancelPtr)
+ {
+ _Fail("Cancelled");
+ return false;
+ }
+
CeOp op = CE_GETINST(CeOp);
switch (op)
{
@@ -2022,8 +2796,8 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
auto& ceFrame = mCallStack.back();
ceFunction = ceFrame.mFunction;
instPtr = ceFrame.mInstPtr;
- stackPtr = ceFrame.mStackPtr;
- framePtr = ceFrame.mFramePtr;
+ stackPtr = memStart + ceFrame.mStackAddr;
+ framePtr = memStart + ceFrame.mFrameAddr;
mCallStack.pop_back();
}
@@ -2050,6 +2824,138 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
instPtr += relOfs - 4;
}
break;
+ case CeOp_Error:
+ {
+ auto errorKind = (CeErrorKind)CE_GETINST(int32);
+ switch (errorKind)
+ {
+ case CeErrorKind_GlobalVariable:
+ _Fail("Global variable access not allowed");
+ break;
+ case CeErrorKind_FunctionPointer:
+ _Fail("Function pointer calls not allowed");
+ break;
+ case CeErrorKind_Intrinsic:
+ _Fail("Intrinsic not allowed");
+ break;
+ default:
+ _Fail("Operation not allowed");
+ break;
+ }
+ }
+ break;
+ case CeOp_DynamicCastCheck:
+ {
+ auto& result = CE_GETFRAME(uint32);
+ auto valueAddr = CE_GETFRAME(addr_ce);
+ int32 ifaceId = CE_GETINST(int32);
+
+ CE_CHECKADDR(valueAddr, sizeof(int32));
+
+ auto ifaceType = mCeModule->mContext->mTypes[ifaceId];
+ int32 objTypeId = *(int32*)(memStart + valueAddr);
+ auto valueType = mCeModule->mContext->mTypes[objTypeId];
+ if (mCeModule->TypeIsSubTypeOf(valueType->ToTypeInstance(), ifaceType->ToTypeInstance(), false))
+ result = valueAddr;
+ else
+ result = 0;
+ }
+ break;
+ case CeOp_GetString:
+ {
+ auto frameOfs = CE_GETINST(int32);
+ auto stringTableIdx = CE_GETINST(int32);
+ auto& ceStringEntry = ceFunction->mStringTable[stringTableIdx];
+ if (ceStringEntry.mBindExecuteId != mExecuteId)
+ {
+ addr_ce* ceAddrPtr = NULL;
+ if (mStringMap.TryAdd(ceStringEntry.mStringId, NULL, &ceAddrPtr))
+ {
+ String str;
+ BfStringPoolEntry* entry = NULL;
+ if (mCeModule->mContext->mStringObjectIdMap.TryGetValue(ceStringEntry.mStringId, &entry))
+ {
+ str = entry->mString;
+ }
+
+ BfTypeInstance* stringTypeInst = (BfTypeInstance*)mCeModule->ResolveTypeDef(mCompiler->mStringTypeDef, BfPopulateType_Data);
+
+ int allocSize = stringTypeInst->mInstSize + (int)str.length() + 1;
+ int charsOffset = stringTypeInst->mInstSize;
+
+ CE_CHECKALLOC(allocSize);
+ uint8* mem = CeMalloc(allocSize);
+ _FixVariables();
+
+ memset(mem, 0, allocSize);
+
+ auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize;
+ auto lenOffset = stringTypeInst->mFieldInstances[0].mDataOffset;
+ auto allocSizeOffset = stringTypeInst->mFieldInstances[1].mDataOffset;
+ auto ptrOffset = stringTypeInst->mFieldInstances[2].mDataOffset;
+
+ // Write TypeId into there
+ *(int32*)(mem) = stringTypeInst->mTypeId;
+ *(int32*)(mem + lenOffset) = (int)str.length();
+ if (lenByteCount == 4)
+ *(int32*)(mem + allocSizeOffset) = 0x40000000 + (int)str.length() + 1;
+ else
+ *(int64*)(mem + allocSizeOffset) = 0x4000000000000000LL + (int)str.length() + 1;
+ *(int32*)(mem + ptrOffset) = (mem + charsOffset) - memStart;
+ memcpy(mem + charsOffset, str.c_str(), str.length());
+
+ *ceAddrPtr = mem - memStart;
+ }
+
+ ceStringEntry.mStringAddr = *ceAddrPtr;
+ ceStringEntry.mBindExecuteId = mExecuteId;
+ }
+
+ *(addr_ce*)(framePtr + frameOfs) = ceStringEntry.mStringAddr;
+ }
+ break;
+ case CeOp_Malloc:
+ {
+ auto frameOfs = CE_GETINST(int32);
+ int32 size = CE_GETFRAME(int32);
+ CE_CHECKALLOC(size);
+ uint8* mem = CeMalloc(size);
+ _FixVariables();
+ *(addr_ce*)(framePtr + frameOfs) = mem - memStart;
+ }
+ break;
+ case CeOp_Free:
+ {
+ auto freeAddr = CE_GETFRAME(addr_ce);
+ bool success = CeFree(freeAddr);
+ if (!success)
+ _Fail("Invalid heap address");
+ }
+ break;
+ case CeOp_MemSet:
+ {
+ auto destAddr = CE_GETFRAME(addr_ce);
+ uint8 setValue = CE_GETFRAME(uint8);
+ int32 setSize = CE_GETFRAME(int32);
+ memset(memStart + destAddr, setValue, setSize);
+ }
+ break;
+ case CeOp_MemSet_Const:
+ {
+ auto destAddr = CE_GETFRAME(addr_ce);
+ uint8 setValue = CE_GETINST(uint8);
+ int32 setSize = CE_GETINST(int32);
+ memset(memStart + destAddr, setValue, setSize);
+ }
+ break;
+ case CeOp_MemCpy:
+ {
+ auto destAddr = CE_GETFRAME(addr_ce);
+ auto srcAddr = CE_GETFRAME(addr_ce);
+ int32 size = CE_GETFRAME(int32);
+ memcpy(memStart + destAddr, memStart + srcAddr, size);
+ }
+ break;
case CeOp_FrameAddr_64:
{
auto& result = CE_GETFRAME(int64);
@@ -2096,18 +3002,39 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
instPtr += constSize;
}
break;
+ case CeOp_Load_8:
+ CE_LOAD(uint8);
+ break;
+ case CeOp_Load_16:
+ CE_LOAD(uint16);
+ break;
case CeOp_Load_32:
- CE_LOAD(uint32);
+ CE_LOAD(uint32);
break;
case CeOp_Load_64:
CE_LOAD(uint64);
break;
+ case CeOp_Store_8:
+ CE_STORE(uint8);
+ break;
+ case CeOp_Store_16:
+ CE_STORE(uint16);
+ break;
case CeOp_Store_32:
CE_STORE(uint32);
break;
case CeOp_Store_64:
CE_STORE(uint64);
break;
+ case CeOp_Store_X:
+ {
+ auto size = CE_GETINST(int32);
+ auto srcPtr = &CE_GETFRAME(uint8);
+ auto ceAddr = CE_GETFRAME(addr_ce);
+ CE_CHECKADDR(ceAddr, size);
+ memcpy(memStart + ceAddr, srcPtr, size);
+ }
+ break;
case CeOp_Move_8:
CEOP_MOVE(int8);
break;
@@ -2153,11 +3080,35 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
CEOP_POP(int64);
break;
case CeOp_AdjustSP:
+ {
+ int32 adjust = CE_GETFRAME(int32);
+ stackPtr += adjust;
+ }
+ break;
+ case CeOp_AdjustSPNeg:
+ {
+ int32 adjust = CE_GETFRAME(int32);
+ stackPtr -= adjust;
+ }
+ break;
+ case CeOp_AdjustSPConst:
{
int32 adjust = CE_GETINST(int32);
stackPtr += adjust;
}
break;
+ case CeOp_GetSP:
+ {
+ auto& result = CE_GETFRAME(int32);
+ result = stackPtr - memStart;
+ }
+ break;
+ case CeOp_SetSP:
+ {
+ auto addr = CE_GETFRAME(int32);
+ stackPtr = memStart + addr;
+ }
+ break;
case CeOp_Call:
{
callCount++;
@@ -2167,94 +3118,595 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
if (callEntry.mBindRevision != mRevision)
{
callEntry.mFunction = NULL;
- mNamedFunctionMap.TryGetValue(callEntry.mFunctionName, &callEntry.mFunction);
+ //mNamedFunctionMap.TryGetValue(callEntry.mFunctionName, &callEntry.mFunction);
+
+ if (callEntry.mFunctionInfo == NULL)
+ {
+ _Fail("Unable to locate function entry");
+ break;
+ }
- if ((callEntry.mFunction != NULL) && (!callEntry.mFunction->mInitialized))
+ if ((callEntry.mFunctionInfo->mCeFunction == NULL) && (!callEntry.mFunctionInfo->mMethodRef.IsNull()))
+ {
+ auto methodRef = callEntry.mFunctionInfo->mMethodRef;
+ auto methodDef = methodRef.mTypeInstance->mTypeDef->mMethods[methodRef.mMethodNum];
+ auto moduleMethodInstance = mCeModule->GetMethodInstance(methodRef.mTypeInstance, methodDef,
+ methodRef.mMethodGenericArguments);
+
+ if (moduleMethodInstance)
+ {
+ QueueMethod(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc);
+ }
+ }
+
+ if (callEntry.mFunctionInfo->mCeFunction == NULL)
+ {
+ _Fail("Method not generated");
+ break;
+ }
+
+ callEntry.mFunction = callEntry.mFunctionInfo->mCeFunction;
+ if (!callEntry.mFunction->mInitialized)
{
PrepareFunction(callEntry.mFunction);
}
- if (!_CheckFunction(callEntry.mFunction))
- return false;
+ bool handled = false;
+ if (!_CheckFunction(callEntry.mFunction, handled))
+ return false;
+ if (handled)
+ break;
callEntry.mBindRevision = mRevision;
}
- if (callEntry.mFunction == NULL)
- {
- _Fail("Unable to locate function entry");
- break;
- }
+ CE_CALL(callEntry.mFunction);
+
// if (callEntry.mFunction->mName.Contains("__static_dump"))
// {
// int32 val = *(int32*)(stackPtr);
// OutputDebugStrF("__static_dump: %d\n", val);
-// }
-
- if (callEntry.mFunction != NULL)
- {
- mCallStack.Add(_GetCurFrame());
-
- ceFunction = callEntry.mFunction;
- framePtr = stackPtr;
- stackPtr -= ceFunction->mFrameSize;
- instPtr = &ceFunction->mCode[0];
- CE_CHECKSTACK();
- }
+// }
}
break;
+ case CeOp_Call_Virt:
+ {
+ auto valueAddr = CE_GETFRAME(addr_ce);
+ int32 virtualIdx = CE_GETINST(int32);
+
+ CE_CHECKADDR(valueAddr, sizeof(int32));
+ int32 objTypeId = *(int32*)(memStart + valueAddr);
+ auto valueType = mCeModule->mContext->mTypes[objTypeId]->ToTypeInstance();
+ if (valueType->mVirtualMethodTable.IsEmpty())
+ mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods);
+ auto methodInstance = (BfMethodInstance*)valueType->mVirtualMethodTable[virtualIdx].mImplementingMethod;
+
+ auto callFunction = GetPreparedFunction(methodInstance);
+ CE_CALL(callFunction);
+ }
+ break;
+ case CeOp_Conv_I8_I16:
+ CE_CAST(int8, int16);
+ break;
+ case CeOp_Conv_I8_I32:
+ CE_CAST(int8, int32);
+ break;
+ case CeOp_Conv_I8_I64:
+ CE_CAST(int8, int64);
+ break;
+ case CeOp_Conv_I8_F32:
+ CE_CAST(int8, float);
+ break;
+ case CeOp_Conv_I8_F64:
+ CE_CAST(int8, double);
+ break;
+ case CeOp_Conv_I16_I32:
+ CE_CAST(int16, int32);
+ break;
+ case CeOp_Conv_I16_I64:
+ CE_CAST(int16, int64);
+ break;
+ case CeOp_Conv_I16_F32:
+ CE_CAST(int16, float);
+ break;
+ case CeOp_Conv_I16_F64:
+ CE_CAST(int16, double);
+ break;
case CeOp_Conv_I32_I64:
CE_CAST(int32, int64);
break;
+ case CeOp_Conv_I32_F32:
+ CE_CAST(int32, float);
+ break;
+ case CeOp_Conv_I32_F64:
+ CE_CAST(int32, double);
+ break;
+ case CeOp_Conv_I64_F32:
+ CE_CAST(int64, float);
+ break;
+ case CeOp_Conv_I64_F64:
+ CE_CAST(int64, double);
+ break;
+ case CeOp_Conv_U8_U16:
+ CE_CAST(uint8, uint16);
+ break;
+ case CeOp_Conv_U8_U32:
+ CE_CAST(uint8, uint32);
+ break;
+ case CeOp_Conv_U8_U64:
+ CE_CAST(uint8, uint64);
+ break;
+ case CeOp_Conv_U8_F32:
+ CE_CAST(uint8, float);
+ break;
+ case CeOp_Conv_U8_F64:
+ CE_CAST(uint8, double);
+ break;
+ case CeOp_Conv_U16_U32:
+ CE_CAST(uint16, uint32);
+ break;
+ case CeOp_Conv_U16_U64:
+ CE_CAST(uint16, uint64);
+ break;
+ case CeOp_Conv_U16_F32:
+ CE_CAST(uint16, float);
+ break;
+ case CeOp_Conv_U16_F64:
+ CE_CAST(uint16, double);
+ break;
+ case CeOp_Conv_U32_U64:
+ CE_CAST(uint32, uint64);
+ break;
+ case CeOp_Conv_U32_F32:
+ CE_CAST(uint32, float);
+ break;
+ case CeOp_Conv_U32_F64:
+ CE_CAST(uint32, double);
+ break;
+ case CeOp_Conv_U64_F32:
+ CE_CAST(uint64, float);
+ break;
+ case CeOp_Conv_U64_F64:
+ CE_CAST(uint64, double);
+ break;
+ case CeOp_Conv_F32_I8:
+ CE_CAST(float, int8);
+ break;
+ case CeOp_Conv_F32_I16:
+ CE_CAST(float, int16);
+ break;
+ case CeOp_Conv_F32_I32:
+ CE_CAST(float, int32);
+ break;
+ case CeOp_Conv_F32_I64:
+ CE_CAST(float, int64);
+ break;
+ case CeOp_Conv_F32_F64:
+ CE_CAST(float, double);
+ break;
+ case CeOp_Conv_F64_I8:
+ CE_CAST(double, int8);
+ break;
+ case CeOp_Conv_F64_I16:
+ CE_CAST(double, int16);
+ break;
+ case CeOp_Conv_F64_I32:
+ CE_CAST(double, int32);
+ break;
+ case CeOp_Conv_F64_I64:
+ CE_CAST(double, int64);
+ break;
+ case CeOp_Conv_F64_F32:
+ CE_CAST(double, float);
+ break;
+ case CeOp_AddConst_I8:
+ CEOP_BIN_CONST(+, int8);
+ break;
+ case CeOp_AddConst_I16:
+ CEOP_BIN_CONST(+, int16);
+ break;
case CeOp_AddConst_I32:
CEOP_BIN_CONST(+, int32);
break;
case CeOp_AddConst_I64:
CEOP_BIN_CONST(+, int64);
break;
+ case CeOp_Add_I8:
+ CEOP_BIN(+, int8);
+ break;
+ case CeOp_Add_I16:
+ CEOP_BIN(+, int16);
+ break;
case CeOp_Add_I32:
CEOP_BIN(+, int32);
break;
case CeOp_Add_I64:
CEOP_BIN(+, int64);
break;
+ case CeOp_Add_F32:
+ CEOP_BIN(+, float);
+ break;
+ case CeOp_Add_F64:
+ CEOP_BIN(+, double);
+ break;
+ case CeOp_Sub_I8:
+ CEOP_BIN(-, int8);
+ break;
+ case CeOp_Sub_I16:
+ CEOP_BIN(-, int16);
+ break;
case CeOp_Sub_I32:
CEOP_BIN(-, int32);
break;
case CeOp_Sub_I64:
CEOP_BIN(-, int64);
break;
+ case CeOp_Sub_F32:
+ CEOP_BIN(-, float);
+ break;
+ case CeOp_Sub_F64:
+ CEOP_BIN(-, double);
+ break;
+ case CeOp_Mul_I8:
+ CEOP_BIN(*, int8);
+ break;
+ case CeOp_Mul_I16:
+ CEOP_BIN(*, int16);
+ break;
case CeOp_Mul_I32:
CEOP_BIN(*, int32);
break;
case CeOp_Mul_I64:
CEOP_BIN(*, int64);
break;
+ case CeOp_Mul_F32:
+ CEOP_BIN(*, float);
+ break;
+ case CeOp_Mul_F64:
+ CEOP_BIN(*, double);
+ break;
+ case CeOp_Div_I8:
+ CEOP_BIN_DIV(/, int8);
+ break;
+ case CeOp_Div_I16:
+ CEOP_BIN_DIV(/, int16);
+ break;
+ case CeOp_Div_I32:
+ CEOP_BIN_DIV(/, int32);
+ break;
+ case CeOp_Div_I64:
+ CEOP_BIN_DIV(/, int64);
+ break;
+ case CeOp_Div_F32:
+ CEOP_BIN_DIV(/, float);
+ break;
+ case CeOp_Div_F64:
+ CEOP_BIN_DIV(/, double);
+ break;
+ case CeOp_Div_U8:
+ CEOP_BIN_DIV(/, uint8);
+ break;
+ case CeOp_Div_U16:
+ CEOP_BIN_DIV(/, uint16);
+ break;
+ case CeOp_Div_U32:
+ CEOP_BIN_DIV(/, uint32);
+ break;
+ case CeOp_Div_U64:
+ CEOP_BIN_DIV(/, uint64);
+ break;
+ case CeOp_Mod_I8:
+ CEOP_BIN_DIV(%, int8);
+ break;
+ case CeOp_Mod_I16:
+ CEOP_BIN_DIV(%, int16);
+ break;
+ case CeOp_Mod_I32:
+ CEOP_BIN_DIV(%, int32);
+ break;
+ case CeOp_Mod_I64:
+ CEOP_BIN_DIV(%, int64);
+ break;
+ case CeOp_Mod_F32:
+ {
+ auto& result = CE_GETFRAME(float);
+ auto lhs = CE_GETFRAME(float);
+ auto rhs = CE_GETFRAME(float);
+ if (rhs == 0)
+ {
+ _Fail("Division by zero");
+ return false;
+ }
+ result = fmodf(lhs, rhs);
+ }
+ break;
+ case CeOp_Mod_F64:
+ {
+ auto& result = CE_GETFRAME(double);
+ auto lhs = CE_GETFRAME(double);
+ auto rhs = CE_GETFRAME(double);
+ if (rhs == 0)
+ {
+ _Fail("Division by zero");
+ return false;
+ }
+ result = fmod(lhs, rhs);
+ }
+ break;
+ case CeOp_Mod_U8:
+ CEOP_BIN_DIV(%, uint8);
+ break;
+ case CeOp_Mod_U16:
+ CEOP_BIN_DIV(%, uint16);
+ break;
+ case CeOp_Mod_U32:
+ CEOP_BIN_DIV(%, uint32);
+ break;
+ case CeOp_Mod_U64:
+ CEOP_BIN_DIV(%, uint64);
+ break;
+
+ case CeOp_And_I8:
+ CEOP_BIN(&, uint8);
+ break;
+ case CeOp_And_I16:
+ CEOP_BIN(&, uint16);
+ break;
+ case CeOp_And_I32:
+ CEOP_BIN(&, uint32);
+ break;
+ case CeOp_And_I64:
+ CEOP_BIN(&, uint64);
+ break;
+ case CeOp_Or_I8:
+ CEOP_BIN(|, uint8);
+ break;
+ case CeOp_Or_I16:
+ CEOP_BIN(|, uint16);
+ break;
+ case CeOp_Or_I32:
+ CEOP_BIN(|, uint32);
+ break;
+ case CeOp_Or_I64:
+ CEOP_BIN(|, uint64);
+ break;
+ case CeOp_Xor_I8:
+ CEOP_BIN(^, uint8);
+ break;
+ case CeOp_Xor_I16:
+ CEOP_BIN(^, uint16);
+ break;
+ case CeOp_Xor_I32:
+ CEOP_BIN(^, uint32);
+ break;
+ case CeOp_Xor_I64:
+ CEOP_BIN(^, uint64);
+ break;
+ case CeOp_Shl_I8:
+ CEOP_BIN2(<<, int8, uint8);
+ break;
+ case CeOp_Shl_I16:
+ CEOP_BIN2(<<, int16, uint8);
+ break;
+ case CeOp_Shl_I32:
+ CEOP_BIN2(<<, int32, uint8);
+ break;
+ case CeOp_Shl_I64:
+ CEOP_BIN2(<<, int64, uint8);
+ break;
+ case CeOp_Shr_I8:
+ CEOP_BIN2(>>, int8, uint8);
+ break;
+ case CeOp_Shr_I16:
+ CEOP_BIN2(>>, int16, uint8);
+ break;
+ case CeOp_Shr_I32:
+ CEOP_BIN2(>>, int32, uint8);
+ break;
+ case CeOp_Shr_I64:
+ CEOP_BIN2(>>, int64, uint8);
+ break;
+ case CeOp_Shr_U8:
+ CEOP_BIN2(>>, uint8, uint8);
+ break;
+ case CeOp_Shr_U16:
+ CEOP_BIN2(>>, uint16, uint8);
+ break;
+ case CeOp_Shr_U32:
+ CEOP_BIN2(>>, uint32, uint8);
+ break;
+ case CeOp_Shr_U64:
+ CEOP_BIN2(>>, uint64, uint8);
+ break;
+ case CeOp_Cmp_NE_I8:
+ CEOP_CMP(!= , int8);
+ break;
+ case CeOp_Cmp_NE_I16:
+ CEOP_CMP(!= , int16);
+ break;
+ case CeOp_Cmp_NE_I32:
+ CEOP_CMP(!=, int32);
+ break;
+ case CeOp_Cmp_NE_I64:
+ CEOP_CMP(!=, int64);
+ break;
+ case CeOp_Cmp_NE_F32:
+ CEOP_CMP(!= , float);
+ break;
+ case CeOp_Cmp_NE_F64:
+ CEOP_CMP(!= , double);
+ break;
+ case CeOp_Cmp_EQ_I8:
+ CEOP_CMP(==, int8);
+ break;
+ case CeOp_Cmp_EQ_I16:
+ CEOP_CMP(==, int16);
+ break;
case CeOp_Cmp_EQ_I32:
CEOP_CMP(==, int32);
break;
+ case CeOp_Cmp_EQ_I64:
+ CEOP_CMP(==, int64);
+ break;
+ case CeOp_Cmp_EQ_F32:
+ CEOP_CMP(== , float);
+ break;
+ case CeOp_Cmp_EQ_F64:
+ CEOP_CMP(== , double);
+ break;
+ case CeOp_Cmp_SLT_I8:
+ CEOP_CMP(< , int8);
+ break;
+ case CeOp_Cmp_SLT_I16:
+ CEOP_CMP(< , int16);
+ break;
case CeOp_Cmp_SLT_I32:
CEOP_CMP(<, int32);
break;
+ case CeOp_Cmp_SLT_I64:
+ CEOP_CMP(<, int64);
+ break;
+ case CeOp_Cmp_SLT_F32:
+ CEOP_CMP(<, float);
+ break;
+ case CeOp_Cmp_SLT_F64:
+ CEOP_CMP(< , double);
+ break;
+ case CeOp_Cmp_ULT_I8:
+ CEOP_CMP(<, uint8);
+ break;
+ case CeOp_Cmp_ULT_I16:
+ CEOP_CMP(<, uint16);
+ break;
case CeOp_Cmp_ULT_I32:
CEOP_CMP(<, uint32);
break;
+ case CeOp_Cmp_ULT_I64:
+ CEOP_CMP(<, uint64);
+ break;
+ case CeOp_Cmp_SLE_I8:
+ CEOP_CMP(<=, int8);
+ break;
+ case CeOp_Cmp_SLE_I16:
+ CEOP_CMP(<=, int16);
+ break;
case CeOp_Cmp_SLE_I32:
CEOP_CMP(<=, int32);
break;
case CeOp_Cmp_SLE_I64:
- CEOP_CMP(<= , int64);
+ CEOP_CMP(<=, int64);
+ break;
+ case CeOp_Cmp_SLE_F32:
+ CEOP_CMP(<= , float);
+ break;
+ case CeOp_Cmp_SLE_F64:
+ CEOP_CMP(<= , double);
+ break;
+ case CeOp_Cmp_ULE_I8:
+ CEOP_CMP(<=, uint8);
+ break;
+ case CeOp_Cmp_ULE_I16:
+ CEOP_CMP(<=, uint16);
break;
case CeOp_Cmp_ULE_I32:
CEOP_CMP(<=, uint32);
break;
+ case CeOp_Cmp_ULE_I64:
+ CEOP_CMP(<=, uint64);
+ break;
+ case CeOp_Cmp_SGT_I8:
+ CEOP_CMP(>, int8);
+ break;
+ case CeOp_Cmp_SGT_I16:
+ CEOP_CMP(>, int16);
+ break;
+ case CeOp_Cmp_SGT_I32:
+ CEOP_CMP(>, int32);
+ break;
+ case CeOp_Cmp_SGT_I64:
+ CEOP_CMP(>, int64);
+ break;
+ case CeOp_Cmp_SGT_F32:
+ CEOP_CMP(>, float);
+ break;
+ case CeOp_Cmp_SGT_F64:
+ CEOP_CMP(>, double);
+ break;
+ case CeOp_Cmp_UGT_I8:
+ CEOP_CMP(>, uint8);
+ break;
+ case CeOp_Cmp_UGT_I16:
+ CEOP_CMP(>, uint16);
+ break;
+ case CeOp_Cmp_UGT_I32:
+ CEOP_CMP(>, uint32);
+ break;
+ case CeOp_Cmp_UGT_I64:
+ CEOP_CMP(>, uint64);
+ break;
+ case CeOp_Cmp_SGE_I8:
+ CEOP_CMP(>=, int8);
+ break;
+ case CeOp_Cmp_SGE_I16:
+ CEOP_CMP(>=, int16);
+ break;
+ case CeOp_Cmp_SGE_I32:
+ CEOP_CMP(>=, int32);
+ break;
+ case CeOp_Cmp_SGE_I64:
+ CEOP_CMP(>=, int64);
+ break;
+ case CeOp_Cmp_SGE_F32:
+ CEOP_CMP(>=, float);
+ break;
+ case CeOp_Cmp_SGE_F64:
+ CEOP_CMP(>=, double);
+ break;
+ case CeOp_Cmp_UGE_I8:
+ CEOP_CMP(>=, uint8);
+ break;
+ case CeOp_Cmp_UGE_I16:
+ CEOP_CMP(>=, uint16);
+ break;
+ case CeOp_Cmp_UGE_I32:
+ CEOP_CMP(>=, uint32);
+ break;
+ case CeOp_Cmp_UGE_I64:
+ CEOP_CMP(>=, uint64);
+ break;
+ case CeOp_Neg_I8:
+ CEOP_UNARY(-, int8);
+ break;
+ case CeOp_Neg_I16:
+ CEOP_UNARY(-, int16);
+ break;
case CeOp_Neg_I32:
CEOP_UNARY(-, int32);
break;
case CeOp_Neg_I64:
CEOP_UNARY(-, int64);
break;
+ case CeOp_Neg_F32:
+ CEOP_UNARY(-, float);
+ case CeOp_Neg_F64:
+ CEOP_UNARY(-, double);
+ break;
+ case CeOp_Not_I1:
+ CEOP_UNARY(!, bool);
+ break;
+ case CeOp_Not_I8:
+ CEOP_UNARY(~, int8);
+ break;
+ case CeOp_Not_I16:
+ CEOP_UNARY(~, int16);
+ break;
+ case CeOp_Not_I32:
+ CEOP_UNARY(~, int32);
+ break;
+ case CeOp_Not_I64:
+ CEOP_UNARY(~, int64);
+ break;
default:
_Fail("Unhandled op");
return false;
@@ -2265,9 +3717,39 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
}
void CeMachine::PrepareFunction(CeFunction* ceFunction)
-{
- if (mCeModule == NULL)
- Init();
+{
+ auto methodDef = ceFunction->mMethodInstance->mMethodDef;
+ if (methodDef->mIsExtern)
+ {
+ ceFunction->mFunctionKind = CeFunctionKind_Extern;
+
+ auto owner = ceFunction->mMethodInstance->GetOwner();
+ if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef))
+ {
+ if (methodDef->mName == "Write")
+ {
+ if (ceFunction->mMethodInstance->GetParamCount() == 1)
+ ceFunction->mFunctionKind = CeFunctionKind_DebugWrite_Int;
+ else
+ ceFunction->mFunctionKind = CeFunctionKind_DebugWrite;
+ }
+
+ //MAKE CeFunctionKind_DebugWrite_Int
+ }
+ else if (owner->IsInstanceOf(mCeModule->mCompiler->mInternalTypeDef))
+ {
+ if (methodDef->mName == "ThrowIndexOutOfRange")
+ {
+ ceFunction->mFunctionKind = CeFunctionKind_OOB;
+ }
+ else if (methodDef->mName == "FatalError")
+ {
+ ceFunction->mFunctionKind = CeFunctionKind_FatalError;
+ }
+ }
+
+ return;
+ }
BF_ASSERT(!ceFunction->mInitialized);
ceFunction->mInitialized = true;
@@ -2292,32 +3774,80 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction)
}
CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue func, bool& added)
-{
- CeFunction** functionValuePtr = NULL;
+{
+ if (func)
+ {
+ if ((func.IsConst()) || (func.IsFake()))
+ return NULL;
+ }
+
+ CeFunctionInfo** functionInfoPtr = NULL;
+ CeFunctionInfo* ceFunctionInfo = NULL;
CeFunction* ceFunction = NULL;
- if (mFunctions.TryAdd(methodInstance, NULL, &functionValuePtr))
+ if (!mFunctions.TryAdd(methodInstance, NULL, &functionInfoPtr))
+ {
+ ceFunctionInfo = *functionInfoPtr;
+ BF_ASSERT(ceFunctionInfo->mCeFunction != NULL);
+ return ceFunctionInfo->mCeFunction;
+ }
+
+ if (!func)
+ {
+ ceFunctionInfo = new CeFunctionInfo();
+ }
+ else
+ {
+ auto funcVal = mCeModule->mBfIRBuilder->mBeIRCodeGen->GetBeValue(func.mId);
+
+ if (auto function = BeValueDynCast(funcVal))
+ {
+ CeFunctionInfo** namedFunctionInfoPtr = NULL;
+ if (mNamedFunctionMap.TryAdd(function->mName, NULL, &namedFunctionInfoPtr))
+ {
+ ceFunctionInfo = new CeFunctionInfo();
+ ceFunctionInfo->mName = function->mName;
+ *namedFunctionInfoPtr = ceFunctionInfo;
+ }
+ else
+ {
+ ceFunctionInfo = *namedFunctionInfoPtr;
+ }
+ }
+ else
+ {
+ ceFunctionInfo = new CeFunctionInfo();
+ }
+ }
+
+ ceFunctionInfo->mRefCount++;
+ *functionInfoPtr = ceFunctionInfo;
+
+ if (ceFunctionInfo->mMethodInstance == NULL)
{
added = true;
auto module = methodInstance->GetOwner()->mModule;
BF_ASSERT(!methodInstance->mInCEMachine);
- methodInstance->mInCEMachine = true;
+ methodInstance->mInCEMachine = true;
ceFunction = new CeFunction();
- ceFunction->mMethodInstance = methodInstance;
+ ceFunction->mCeFunctionInfo = ceFunctionInfo;
+ ceFunction->mMethodInstance = methodInstance;
- if ((func) && (!func.IsConst()) && (!func.IsFake()))
- {
- if (auto function = BeValueDynCast(mCeModule->mBfIRBuilder->mBeIRCodeGen->GetBeValue(func.mId)))
- {
- mNamedFunctionMap[function->mName] = ceFunction;
- }
- }
-
- *functionValuePtr = ceFunction;
+ ceFunctionInfo->mMethodInstance = methodInstance;
+ ceFunctionInfo->mCeFunction = ceFunction;
}
- else
- ceFunction = *functionValuePtr;
+ return ceFunction;
+}
+
+CeFunction* CeMachine::GetPreparedFunction(BfMethodInstance* methodInstance)
+{
+ bool added = false;
+ auto ceFunction = GetFunction(methodInstance, BfIRValue(), added);
+ if (ceFunction == NULL)
+ return NULL;
+ if (!ceFunction->mInitialized)
+ PrepareFunction(ceFunction);
return ceFunction;
}
@@ -2327,6 +3857,11 @@ void CeMachine::QueueMethod(BfMethodInstance* methodInstance, BfIRValue func)
auto ceFunction = GetFunction(methodInstance, func, added);
}
+void CeMachine::QueueMethod(BfModuleMethodInstance moduleMethodInstance)
+{
+ QueueMethod(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc);
+}
+
BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray& args, CeEvalFlags flags)
{
// for (int argIdx = 0; argIdx < (int)args.size(); argIdx++)
@@ -2351,14 +3886,20 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
return BfTypedValue();
}
+ if (mCeModule == NULL)
+ Init();
+
bool added = false;
CeFunction* ceFunction = GetFunction(methodInstance, BfIRValue(), added);
if (!ceFunction->mInitialized)
PrepareFunction(ceFunction);
-
+
+ if (mHeap == NULL)
+ mHeap = new ContiguousHeap();
mMemory.Resize(BF_CE_STACK_SIZE);
- auto stackPtr = &mMemory[0] + mMemory.mSize;
- mStackMin = &mMemory[0];
+
+ auto stackPtr = &mMemory[0] + mMemory.mSize;
+ auto* memStart = &mMemory[0];
for (int argIdx = (int)args.size() - 1; argIdx >= 0; argIdx--)
{
@@ -2375,26 +3916,28 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
WriteConstant(stackPtr, constant);
}
- uint8* retPtr = NULL;
+ addr_ce retAddr = 0;
auto returnType = methodInstance->mReturnType;
if (!returnType->IsValuelessType())
{
int retSize = methodInstance->mReturnType->mSize;
stackPtr -= retSize;
- retPtr = stackPtr;
+ retAddr = stackPtr - memStart;
}
bool success = Execute(ceFunction, stackPtr - ceFunction->mFrameSize, stackPtr);
-
- mCallStack.Clear();
-
+ memStart = &mMemory[0];
+
auto constHolder = module->mBfIRBuilder;
+ BfTypedValue returnValue;
+
if (success)
{
BfTypedValue retValue;
- if (retPtr != NULL)
+ if (retAddr != 0)
{
+ auto* retPtr = memStart + retAddr;
BfIRValue constVal;
if (returnType->IsPrimitiveType())
@@ -2441,13 +3984,18 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
}
if (constVal)
- return BfTypedValue(constVal, returnType);
+ returnValue = BfTypedValue(constVal, returnType);
}
else
{
- return BfTypedValue(module->mBfIRBuilder->GetFakeVal(), returnType);
+ returnValue = BfTypedValue(module->mBfIRBuilder->GetFakeVal(), returnType);
}
}
+
+ mStringMap.Clear();
+ mMemory.Clear();
+ mCallStack.Clear();
+ mHeap->Clear();
- return BfTypedValue();
+ return returnValue;
}
diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h
index 990e6347..e3c02630 100644
--- a/IDEHelper/Compiler/CeMachine.h
+++ b/IDEHelper/Compiler/CeMachine.h
@@ -2,6 +2,8 @@
#include "BfSystem.h"
#include "BfModule.h"
+#include "BeefySysLib/util/Heap.h"
+#include "BeefySysLib/util/AllocDebug.h"
NS_BF_BEGIN
@@ -19,6 +21,8 @@ class BeSwitchInst;
class CeMachine;
class CeFunction;
+typedef int addr_ce;
+
#define CEOP_SIZED(OPNAME) \
CeOp_##OPNAME##_8, \
CeOp_##OPNAME##_16, \
@@ -32,6 +36,12 @@ class CeFunction;
CeOp_##OPNAME##_I32, \
CeOp_##OPNAME##_I64
+#define CEOP_SIZED_UNUMERIC(OPNAME) \
+ CeOp_##OPNAME##_U8, \
+ CeOp_##OPNAME##_U16, \
+ CeOp_##OPNAME##_U32, \
+ CeOp_##OPNAME##_U64
+
#define CEOP_SIZED_NUMERIC_PLUSF(OPNAME) \
CeOp_##OPNAME##_I8, \
CeOp_##OPNAME##_I16, \
@@ -40,6 +50,14 @@ class CeFunction;
CeOp_##OPNAME##_F32, \
CeOp_##OPNAME##_F64
+enum CeErrorKind
+{
+ CeErrorKind_None,
+ CeErrorKind_GlobalVariable,
+ CeErrorKind_FunctionPointer,
+ CeErrorKind_Intrinsic
+};
+
enum CeOp : int16
{
CeOp_InvalidOp,
@@ -48,6 +66,16 @@ enum CeOp : int16
CeOp_JmpIf,
CeOp_JmpIfNot,
+ CeOp_Error,
+ CeOp_DynamicCastCheck,
+ CeOp_GetString,
+ CeOp_Malloc,
+ CeOp_Free,
+
+ CeOp_MemSet,
+ CeOp_MemSet_Const,
+ CeOp_MemCpy,
+
CeOp_FrameAddr_32,
CeOp_FrameAddr_64,
@@ -60,25 +88,82 @@ enum CeOp : int16
CEOP_SIZED(Pop),
CeOp_AdjustSP,
+ CeOp_AdjustSPNeg,
+ CeOp_AdjustSPConst,
+ CeOp_GetSP,
+ CeOp_SetSP,
CeOp_Call,
-
+ CeOp_Call_Virt,
+ CeOp_Call_IFace,
+
+ CeOp_Conv_I8_I16,
+ CeOp_Conv_I8_I32,
+ CeOp_Conv_I8_I64,
+ CeOp_Conv_I8_F32,
+ CeOp_Conv_I8_F64,
+ CeOp_Conv_I16_I32,
+ CeOp_Conv_I16_I64,
+ CeOp_Conv_I16_F32,
+ CeOp_Conv_I16_F64,
CeOp_Conv_I32_I64,
+ CeOp_Conv_I32_F32,
+ CeOp_Conv_I32_F64,
+ CeOp_Conv_I64_F32,
+ CeOp_Conv_I64_F64,
+ CeOp_Conv_U8_U16,
+ CeOp_Conv_U8_U32,
+ CeOp_Conv_U8_U64,
+ CeOp_Conv_U8_F32,
+ CeOp_Conv_U8_F64,
+ CeOp_Conv_U16_U32,
+ CeOp_Conv_U16_U64,
+ CeOp_Conv_U16_F32,
+ CeOp_Conv_U16_F64,
+ CeOp_Conv_U32_U64,
+ CeOp_Conv_U32_F32,
+ CeOp_Conv_U32_F64,
+ CeOp_Conv_U64_F32,
+ CeOp_Conv_U64_F64,
+ CeOp_Conv_F32_I8,
+ CeOp_Conv_F32_I16,
+ CeOp_Conv_F32_I32,
+ CeOp_Conv_F32_I64,
+ CeOp_Conv_F32_F64,
+ CeOp_Conv_F64_I8,
+ CeOp_Conv_F64_I16,
+ CeOp_Conv_F64_I32,
+ CeOp_Conv_F64_I64,
+ CeOp_Conv_F64_F32,
CEOP_SIZED_NUMERIC_PLUSF(AddConst),
CEOP_SIZED_NUMERIC_PLUSF(Add),
CEOP_SIZED_NUMERIC_PLUSF(Sub),
CEOP_SIZED_NUMERIC_PLUSF(Mul),
- CEOP_SIZED_NUMERIC_PLUSF(SDiv),
- CEOP_SIZED_NUMERIC(UDiv),
- CEOP_SIZED_NUMERIC_PLUSF(SMod),
- CEOP_SIZED_NUMERIC(UMod),
+ CEOP_SIZED_NUMERIC_PLUSF(Div),
+ CEOP_SIZED_UNUMERIC(Div),
+ CEOP_SIZED_NUMERIC_PLUSF(Mod),
+ CEOP_SIZED_UNUMERIC(Mod),
+ CEOP_SIZED_NUMERIC(And),
+ CEOP_SIZED_NUMERIC(Or),
+ CEOP_SIZED_NUMERIC(Xor),
+ CEOP_SIZED_NUMERIC(Shl),
+ CEOP_SIZED_NUMERIC(Shr),
+ CEOP_SIZED_UNUMERIC(Shr),
+
CEOP_SIZED_NUMERIC_PLUSF(Cmp_EQ),
+ CEOP_SIZED_NUMERIC_PLUSF(Cmp_NE),
CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLT),
CEOP_SIZED_NUMERIC(Cmp_ULT),
CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLE),
CEOP_SIZED_NUMERIC(Cmp_ULE),
+ CEOP_SIZED_NUMERIC_PLUSF(Cmp_SGT),
+ CEOP_SIZED_NUMERIC(Cmp_UGT),
+ CEOP_SIZED_NUMERIC_PLUSF(Cmp_SGE),
+ CEOP_SIZED_NUMERIC(Cmp_UGE),
CEOP_SIZED_NUMERIC_PLUSF(Neg),
+ CeOp_Not_I1,
+ CEOP_SIZED_NUMERIC(Not),
CeOp_COUNT
};
@@ -91,43 +176,95 @@ struct CeEmitEntry
int mColumn;
};
+class CeFunctionInfo
+{
+public:
+ String mName;
+ BfMethodInstance* mMethodInstance;
+ BfMethodRef mMethodRef;
+ CeFunction* mCeFunction;
+ int mRefCount;
+
+public:
+ CeFunctionInfo()
+ {
+ mMethodInstance = NULL;
+ mCeFunction = NULL;
+ mRefCount = 0;
+ }
+};
+
class CeCallEntry
{
public:
- String mFunctionName;
+ CeFunctionInfo* mFunctionInfo;
int mBindRevision;
CeFunction* mFunction;
public:
CeCallEntry()
{
+ mFunctionInfo = NULL;
mBindRevision = -1;
mFunction = NULL;
}
};
+class CeStringEntry
+{
+public:
+ int mStringId;
+ int mBindExecuteId;
+ addr_ce mStringAddr;
+
+public:
+ CeStringEntry()
+ {
+ mStringId = -1;
+ mBindExecuteId = -1;
+ mStringAddr = 0;
+ }
+};
+
+enum CeFunctionKind
+{
+ CeFunctionKind_Normal,
+ CeFunctionKind_Extern,
+ CeFunctionKind_OOB,
+ CeFunctionKind_FatalError,
+ CeFunctionKind_DebugWrite,
+ CeFunctionKind_DebugWrite_Int,
+};
+
class CeFunction
{
public:
+ CeFunctionInfo* mCeFunctionInfo;
BfMethodInstance* mMethodInstance;
- String mName;
+ CeFunctionKind mFunctionKind;
bool mInitialized;
bool mFailed;
Array mCode;
Array mFiles;
Array mEmitTable;
Array mCallTable;
+ Array mStringTable;
+ Array mTypeTable;
String mGenError;
- int mFrameSize;
+ int mFrameSize;
public:
CeFunction()
{
+ mCeFunctionInfo = NULL;
+ mFunctionKind = CeFunctionKind_Normal;
mInitialized = false;
mMethodInstance = NULL;
mFailed = false;
mFrameSize = 0;
}
+
+ ~CeFunction();
};
enum CeEvalFlags
@@ -176,6 +313,7 @@ public:
};
#define BF_CE_STACK_SIZE 1024*1024
+#define BF_CE_MAX_MEMORY 128*1024*1024
enum CeOperandInfoKind
{
@@ -247,7 +385,7 @@ public:
class CeBuilder
{
public:
- CeMachine* mCeMachine;
+ CeMachine* mCeMachine;
CeFunction* mCeFunction;
BeFunction* mBeFunction;
CeOperand mReturnVal;
@@ -262,6 +400,7 @@ public:
int mFrameSize;
Dictionary mDbgFileMap;
Dictionary mFunctionMap;
+ Dictionary mStringMap;
public:
CeBuilder()
@@ -277,14 +416,16 @@ public:
void Fail(const StringImpl& error);
CeOperand FrameAlloc(BeType* type);
+ CeOperand EmitConst(int64 val, int size);
CeOperand GetOperand(BeValue* value, bool allowAlloca = false, bool allowImmediate = false);
CeSizeClass GetSizeClass(int size);
int GetCodePos();
void HandleParams();
-
- void Emit(uint8 val);
+
+ void Emit(uint8 val);
void Emit(CeOp val);
+ void EmitSizedOp(CeOp val, int size);
void Emit(int32 val);
void Emit(int64 val);
void Emit(bool val);
@@ -305,35 +446,42 @@ class CeFrame
{
public:
CeFunction* mFunction;
- uint8* mStackPtr;
- uint8* mFramePtr;
+ addr_ce mStackAddr;
+ addr_ce mFrameAddr;
uint8* mInstPtr;
public:
CeFrame()
{
mFunction = NULL;
- mStackPtr = NULL;
- mFramePtr = NULL;
+ mStackAddr = NULL;
+ mFrameAddr = NULL;
mInstPtr = NULL;
}
};
+class CeFunctionRef
+{
+ //CeFunction* ;
+};
+
class CeMachine
{
public:
- Dictionary mFunctions;
- Dictionary mNamedFunctionMap;
+ Dictionary mFunctions;
+ Dictionary mNamedFunctionMap;
BfCompiler* mCompiler;
BfModule* mCeModule;
int mRevision;
-
- Array mCallStack;
- Array mMemory;
- uint8* mStackMin;
+ int mExecuteId;
+ ContiguousHeap* mHeap;
+ Array mCallStack;
+ Array mMemory;
+ Dictionary mStringMap;
+
BfAstNode* mCurTargetSrc;
- BfModule* mCurModule;
+ BfModule* mCurModule;
public:
CeMachine(BfCompiler* compiler);
@@ -342,8 +490,12 @@ public:
BfError* Fail(const CeFrame& curFrame, const StringImpl& error);
void Init();
+ uint8* CeMalloc(int size);
+ bool CeFree(addr_ce addr);
+
BeContext* GetBeContext();
BeModule* GetBeModule();
+ void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo);
void RemoveMethod(BfMethodInstance* methodInstance);
int GetConstantSize(BfConstant* constant);
void WriteConstant(uint8* ptr, BfConstant* constant);
@@ -352,10 +504,12 @@ public:
void PrepareFunction(CeFunction* methodInstance);
CeFunction* GetFunction(BfMethodInstance* methodInstance, BfIRValue func, bool& added);
+ CeFunction* GetPreparedFunction(BfMethodInstance* methodInstance);
public:
void CompileStarted();
void QueueMethod(BfMethodInstance* methodInstance, BfIRValue func);
+ void QueueMethod(BfModuleMethodInstance moduleMethodInstance);
BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray& args, CeEvalFlags flags);
};