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

Fleshing out comptime debugging

This commit is contained in:
Brian Fiete 2022-03-15 16:33:30 -07:00
parent ff2e40e3bf
commit b334423106
28 changed files with 2079 additions and 780 deletions

View file

@ -93,7 +93,7 @@ namespace System.Reflection
.Double:
let attrData = Decode!<int64>(data);
args[argIdx] = scope:AttrBlock box attrData;
case (TypeCode)typeof(TypeCode).MaxValue + 8: //BfConstType_TypeOf
case (TypeCode)typeof(TypeCode).MaxValue + 9: //BfConstType_TypeOf
let argTypeId = Decode!<int32>(data);
args[argIdx] = Type.[Friend]GetType((.)argTypeId);
case (TypeCode)255:

View file

@ -406,6 +406,9 @@ namespace System
public static void AddErrorHandler(ErrorHandler handler)
{
if (Compiler.IsComptime)
return;
using (sMonitor.Val.Enter())
{
if (sErrorHandlers == null)
@ -416,6 +419,9 @@ namespace System
public static Result<void> RemoveErrorHandler(ErrorHandler handler)
{
if (Compiler.IsComptime)
return .Ok;
using (sMonitor.Val.Enter())
{
if (sErrorHandlers.RemoveStrict(handler))
@ -426,6 +432,9 @@ namespace System
public static ErrorHandlerResult CheckErrorHandlers(Error error)
{
if (Compiler.IsComptime)
return .ContinueFailure;
using (sMonitor.Val.Enter())
{
if (sInsideErrorHandler)

View file

@ -864,6 +864,7 @@
<ClCompile Include="util\CabUtil.cpp" />
<ClCompile Include="util\CatmullRom.cpp" />
<ClCompile Include="util\ChunkedDataBuffer.cpp" />
<ClCompile Include="util\Compress.cpp" />
<ClCompile Include="util\CubicFuncSpline.cpp" />
<ClCompile Include="util\CubicSpline.cpp" />
<ClCompile Include="util\FileEnumerator.cpp" />
@ -1025,6 +1026,7 @@
<ClInclude Include="util\BSpline.h" />
<ClInclude Include="util\CabUtil.h" />
<ClInclude Include="util\CatmullRom.h" />
<ClInclude Include="util\Compress.h" />
<ClInclude Include="util\CritSect.h" />
<ClInclude Include="util\CubicFuncSpline.h" />
<ClInclude Include="util\CubicSpline.h" />

View file

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

View file

@ -5644,7 +5644,7 @@ namespace IDE
subMenu = root.AddMenuItem("&Build");
AddMenuItem(subMenu, "&Build Workspace", "Build Workspace", new => UpdateMenuItem_HasWorkspace);
AddMenuItem(subMenu, "&Debug Comptime", "Debug Comptime", new => UpdateMenuItem_HasWorkspace);
AddMenuItem(subMenu, "&Debug Comptime", "Debug Comptime", new => UpdateMenuItem_DebugStopped_HasWorkspace);
AddMenuItem(subMenu, "&Clean", "Clean", new => UpdateMenuItem_DebugStopped_HasWorkspace);
AddMenuItem(subMenu, "Clean Beef", "Clean Beef", new => UpdateMenuItem_DebugStopped_HasWorkspace);
//subMenu.AddMenuItem("Compile Current File", null, new (menu) => { CompileCurrentFile(); });

View file

@ -796,7 +796,7 @@ namespace IDE.ui
//if (!vals[0].IsEmpty)
String.NewOrSet!(valueSubItem.mLabel, vals[0]);
if (vals[0] == "!sideeffects")
if ((vals[0] == "!sideeffects") || (vals[0] == "!incomplete"))
{
if (useListViewItem.mWatchRefreshButton == null)
{

View file

@ -246,6 +246,7 @@ namespace IDE.ui
public override void Draw(Graphics g)
{
bool atError = gApp.mDebugger.GetRunState() == DebugManager.RunState.Exception;
var debugState = gApp.mDebugger.GetRunState();
uint32 bkgColor = 0xFF404040;
if (atError)
@ -321,13 +322,13 @@ namespace IDE.ui
float statusLabelPos = (int)GS!(-1.3f);
if ((gApp.mDebugger?.mIsComptimeDebug == true) && (gApp.mDebugger.IsPaused()))
{
completionPct = null;
}
//completionPct = 0.4f;
if (completionPct.HasValue)
if ((gApp.mDebugger?.mIsComptimeDebug == true) &&
((gApp.mDebugger.IsPaused()) || (debugState == .DebugEval)))
{
g.DrawString("Debugging Comptime", GS!(200), statusLabelPos, FontAlign.Centered, GS!(120));
}
else if (completionPct.HasValue)
{
Rect completionRect = Rect(GS!(200), GS!(2), GS!(120), GS!(15));
using (g.PushColor(0xFF000000))
@ -336,10 +337,6 @@ namespace IDE.ui
using (g.PushColor(0xFF00FF00))
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth * completionPct.Value, completionRect.mHeight);
}
else if ((gApp.mDebugger?.mIsComptimeDebug == true) && (gApp.mDebugger.IsPaused()))
{
g.DrawString("Debugging Comptime", GS!(200), statusLabelPos, FontAlign.Centered, GS!(120));
}
else if ((gApp.mDebugger.mIsRunning) && (gApp.HaveSourcesChanged()))
{
Rect completionRect = Rect(GS!(200), GS!(1), GS!(120), GS!(17));

View file

@ -2207,11 +2207,6 @@ bool BeCOFFObject::Generate(BeModule* module, const StringImpl& fileName)
void BeCOFFObject::Finish()
{
if (mBeModule->mModuleName.Contains("vdata"))
{
NOP;
}
BP_ZONE("BeCOFFObject::Finish");
//AutoPerf perf("BeCOFFObject::Finish", mPerfManager);

View file

@ -2883,7 +2883,9 @@ void BeIRCodeGen::HandleNextCmd()
case BfIRCmd_DbgGetTypeInst:
{
CMD_PARAM(int, typeId);
SetResult(curId, GetTypeEntry(typeId).mInstDIType);
auto result = GetTypeEntry(typeId).mInstDIType;
//BF_ASSERT(result);
SetResult(curId, result);
}
break;
case BfIRCmd_DbgTrackDITypes:

View file

@ -7172,7 +7172,7 @@ void TestPDB(const StringImpl& fileName, WinDebugger* debugger)
COFF coff(debugTarget);
coff.mDebugger = debugger;
uint8 wantGuid[16];
coff.LoadPDB(fileName, wantGuid, -1);
coff.TryLoadPDB(fileName, wantGuid, -1);
coff.ParseTypeData();
coff.CvParseIPI();
coff.ParseGlobalsData();

View file

@ -752,7 +752,7 @@ public:
bool IsNoValueType() const
{
return (mKind == BfTypedValueKind_NoValue);
return (mKind == BfTypedValueKind_NoValue) && (mType != NULL);
}
bool IsParams()

View file

@ -5,6 +5,8 @@
#include "BfResolvePass.h"
#include "BfFixits.h"
#include "BfResolvedTypeUtils.h"
#include "CeMachine.h"
#include "CeDebugger.h"
#define FTS_FUZZY_MATCH_IMPLEMENTATION
#include "../third_party/FtsFuzzyMatch.h"
@ -274,7 +276,7 @@ int BfAutoComplete::GetCursorIdx(BfAstNode* node)
if (node == NULL)
return -1;
if ((!mCompiler->mIsResolveOnly) || (!node->IsFromParser(mCompiler->mResolvePassData->mParser)))
if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
return -1;
auto bfParser = node->GetSourceData()->ToParser();
@ -288,8 +290,8 @@ bool BfAutoComplete::IsAutocompleteNode(BfAstNode* node, int lengthAdd, int star
{
if (node == NULL)
return false;
if ((!mCompiler->mIsResolveOnly) || (!node->IsFromParser(mCompiler->mResolvePassData->mParser)))
if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
return false;
auto bfParser = node->GetSourceData()->ToParser();
@ -311,7 +313,7 @@ bool BfAutoComplete::IsAutocompleteNode(BfAstNode* startNode, BfAstNode* endNode
if ((startNode == NULL) || (endNode == NULL))
return false;
if ((!mCompiler->mIsResolveOnly) || (!startNode->IsFromParser(mCompiler->mResolvePassData->mParser)))
if (!startNode->IsFromParser(mCompiler->mResolvePassData->mParser))
return false;
auto bfParser = startNode->GetSourceData()->ToParser();
@ -333,7 +335,7 @@ bool BfAutoComplete::IsAutocompleteLineNode(BfAstNode* node)
if (node == NULL)
return false;
if ((!mCompiler->mIsResolveOnly) || (!node->IsFromParser(mCompiler->mResolvePassData->mParser)))
if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
return false;
auto bfParser = node->GetSourceData()->ToParser();
@ -1555,6 +1557,22 @@ void BfAutoComplete::CheckIdentifier(BfAstNode* identifierNode, bool isInExpress
}
}
if (auto ceDbgState = mModule->GetCeDbgState())
{
auto ceDebugger = mModule->mCompiler->mCeMachine->mDebugger;
auto ceContext = ceDebugger->mCurDbgState->mCeContext;
auto activeFrame = ceDebugger->mCurDbgState->mActiveFrame;
if (activeFrame->mFunction->mDbgInfo != NULL)
{
int instIdx = activeFrame->GetInstIdx();
for (auto& dbgVar : activeFrame->mFunction->mDbgInfo->mVariables)
{
if ((instIdx >= dbgVar.mStartCodePos) && (instIdx < dbgVar.mEndCodePos))
AddEntry(AutoCompleteEntry(GetTypeName(dbgVar.mType), dbgVar.mName), filter);
}
}
}
//////////////////////////////////////////////////////////////////////////
BfMethodInstance* curMethodInstance = mModule->mCurMethodInstance;

View file

@ -30,6 +30,7 @@
#include "../LLVMUtils.h"
#include "BfNamespaceVisitor.h"
#include "CeMachine.h"
#include "CeDebugger.h"
#pragma warning(pop)
@ -479,15 +480,15 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mLastAutocompleteModule = NULL;
//if (isResolveOnly)
//mCEMachine = NULL;
mCEMachine = new CeMachine(this);
//mCeMachine = NULL;
mCeMachine = new CeMachine(this);
mCurCEExecuteId = -1;
}
BfCompiler::~BfCompiler()
{
delete mCEMachine;
mCEMachine = NULL;
delete mCeMachine;
mCeMachine = NULL;
delete mContext;
delete mHotData;
delete mHotState;
@ -5749,6 +5750,20 @@ void BfCompiler::PopulateReified()
}
}
bool BfCompiler::IsCePaused()
{
return (mCeMachine != NULL) && (mCeMachine->mDbgPaused);
}
bool BfCompiler::EnsureCeUnpaused(BfType* refType)
{
if ((mCeMachine == NULL) || (!mCeMachine->mDbgPaused))
return true;
mCeMachine->mDebugger->mCurDbgState->mReferencedIncompleteTypes = true;
//mPassInstance->Fail(StrFormat("Use of incomplete type '%s'", mCeMachine->mCeModule->TypeToString(refType).c_str()));
return false;
}
void BfCompiler::HotCommit()
{
if (mHotState == NULL)
@ -6668,8 +6683,8 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
else
mContext->mUnreifiedModule->mIsReified = false;
if (mCEMachine != NULL)
mCEMachine->CompileStarted();
if (mCeMachine != NULL)
mCeMachine->CompileStarted();
if (mOptions.mAllowHotSwapping)
{
@ -7476,7 +7491,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
}
mCodeGen.ProcessErrors(mPassInstance, mCanceling);
mCEMachine->CompileDone();
mCeMachine->CompileDone();
// This has to happen after codegen because we may delete modules that are referenced in codegen
mContext->Cleanup();
@ -7541,9 +7556,9 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
numModulesWritten, (numModulesWritten != 1) ? "s" : "",
numObjFilesWritten, (numObjFilesWritten != 1) ? "s" : ""));
if ((mCEMachine != NULL) && (!mIsResolveOnly) && (mCEMachine->mRevisionExecuteTime > 0))
if ((mCeMachine != NULL) && (!mIsResolveOnly) && (mCeMachine->mRevisionExecuteTime > 0))
{
mPassInstance->OutputLine(StrFormat(":med Comptime execution time: %0.2fs", mCEMachine->mRevisionExecuteTime / 1000.0f));
mPassInstance->OutputLine(StrFormat(":med Comptime execution time: %0.2fs", mCeMachine->mRevisionExecuteTime / 1000.0f));
}
BpLeave();
@ -7658,10 +7673,10 @@ void BfCompiler::Cancel()
mCanceling = true;
mFastFinish = true;
mHadCancel = true;
if (mCEMachine != NULL)
if (mCeMachine != NULL)
{
AutoCrit autoCrit(mCEMachine->mCritSect);
mCEMachine->mSpecialCheck = true;
AutoCrit autoCrit(mCeMachine->mCritSect);
mCeMachine->mSpecialCheck = true;
mFastFinish = true;
}
BfLogSysM("BfCompiler::Cancel\n");
@ -7671,8 +7686,8 @@ void BfCompiler::Cancel()
void BfCompiler::RequestFastFinish()
{
mFastFinish = true;
if (mCEMachine != NULL)
mCEMachine->mSpecialCheck = true;
if (mCeMachine != NULL)
mCeMachine->mSpecialCheck = true;
BfLogSysM("BfCompiler::RequestFastFinish\n");
BpEvent("BfCompiler::RequestFastFinish", "");
}

View file

@ -315,7 +315,7 @@ public:
BfPassInstance* mPassInstance;
FILE* mCompileLogFP;
CeMachine* mCEMachine;
CeMachine* mCeMachine;
int mCurCEExecuteId;
BfSystem* mSystem;
bool mIsResolveOnly;
@ -507,6 +507,8 @@ public:
void AddDepsToRebuildTypeList(BfTypeInstance* typeInst, HashSet<BfTypeInstance*>& rebuildTypeInstList);
void CompileReified();
void PopulateReified();
bool IsCePaused();
bool EnsureCeUnpaused(BfType* refType);
void HotCommit();
void HotResolve_Start(HotResolveFlags flags);

View file

@ -1719,14 +1719,14 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds)
for (auto& methodInstGroup : typeInst->mMethodInstanceGroups)
{
if ((methodInstGroup.mDefault != NULL) && (methodInstGroup.mDefault->mInCEMachine))
mCompiler->mCEMachine->RemoveMethod(methodInstGroup.mDefault);
mCompiler->mCeMachine->RemoveMethod(methodInstGroup.mDefault);
if (methodInstGroup.mMethodSpecializationMap != NULL)
{
for (auto& methodSpecializationItr : *methodInstGroup.mMethodSpecializationMap)
{
auto methodInstance = methodSpecializationItr.mValue;
if (methodInstance->mInCEMachine)
mCompiler->mCEMachine->RemoveMethod(methodInstance);
mCompiler->mCeMachine->RemoveMethod(methodInstance);
}
}
}

View file

@ -14,6 +14,7 @@
#include "BeefySysLib/util/BeefPerf.h"
#include "BfParser.h"
#include "BfMangler.h"
#include "BfDemangler.h"
#include "BfResolvePass.h"
#include "BfUtil.h"
#include "BfDeferEvalChecker.h"
@ -1647,8 +1648,9 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
BfMethodInstance* methodInstance = mModule->GetRawMethodInstance(typeInstance, checkMethod);
if (methodInstance == NULL)
{
BFMODULE_FATAL(mModule, "Failed to get raw method in BfMethodMatcher::CheckMethod");
{
if (!mModule->mCompiler->IsCePaused())
BFMODULE_FATAL(mModule, "Failed to get raw method in BfMethodMatcher::CheckMethod");
return false;
}
BfMethodInstance* typeUnspecMethodInstance = mModule->GetUnspecializedMethodInstance(methodInstance, true);
@ -4020,9 +4022,9 @@ BfTypedValue BfExprEvaluator::LoadLocal(BfLocalVariable* varDecl, bool allowRef)
BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringImpl& findName, bool ignoreInitialError, bool* hadError)
{
if ((mModule->mCompiler->mCEMachine != NULL) && (mModule->mCompiler->mCEMachine->mDebugger != NULL) && (mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
if ((mModule->mCompiler->mCeMachine != NULL) && (mModule->mCompiler->mCeMachine->mDebugger != NULL) && (mModule->mCompiler->mCeMachine->mDebugger->mCurDbgState != NULL))
{
auto ceDebugger = mModule->mCompiler->mCEMachine->mDebugger;
auto ceDebugger = mModule->mCompiler->mCeMachine->mDebugger;
auto ceContext = ceDebugger->mCurDbgState->mCeContext;
auto activeFrame = ceDebugger->mCurDbgState->mActiveFrame;
if (activeFrame->mFunction->mDbgInfo != NULL)
@ -4032,9 +4034,13 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
{
if (dbgVar.mName == findName)
{
if (dbgVar.mValue.mKind == CeOperandKind_AllocaAddr)
if ((dbgVar.mValue.mKind == CeOperandKind_AllocaAddr) || (dbgVar.mValue.mKind == CeOperandKind_FrameOfs))
{
return BfTypedValue(mModule->mBfIRBuilder->CreateConstAggCE(mModule->mBfIRBuilder->MapType(dbgVar.mType), activeFrame->mFrameAddr + dbgVar.mValue.mFrameOfs), dbgVar.mType, true);
if ((instIdx >= dbgVar.mStartCodePos) && (instIdx < dbgVar.mEndCodePos))
{
return BfTypedValue(mModule->mBfIRBuilder->CreateConstAggCE(mModule->mBfIRBuilder->MapType(dbgVar.mType), activeFrame->mFrameAddr + dbgVar.mValue.mFrameOfs),
dbgVar.mType, dbgVar.mIsConst ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Addr);
}
}
}
}
@ -4699,7 +4705,10 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe
if (fieldInstance->mResolvedType == NULL)
{
BF_ASSERT((typeInstance->mTypeFailed) || (isResolvingFields));
if (mModule->mCompiler->EnsureCeUnpaused(typeInstance))
{
BF_ASSERT((typeInstance->mTypeFailed) || (isResolvingFields));
}
return BfTypedValue();
}
@ -5234,6 +5243,15 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
mModule->PopulateType(curCheckType, BfPopulateType_Data);
}
if (field->mIdx >= (int)curCheckType->mFieldInstances.size())
{
if (mModule->mCompiler->EnsureCeUnpaused(curCheckType))
{
BF_DBG_FATAL("OOB in DoLookupField");
}
return mModule->GetDefaultTypedValue(mModule->GetPrimitiveType(BfTypeCode_Var));
}
BF_ASSERT(field->mIdx < (int)curCheckType->mFieldInstances.size());
auto fieldInstance = &curCheckType->mFieldInstances[field->mIdx];
if (!fieldInstance->mFieldIncluded)
@ -6034,7 +6052,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
bool forceBind = false;
if (mModule->mCompiler->mCEMachine != NULL)
if (mModule->mCompiler->mCeMachine != NULL)
{
bool doConstReturn = false;
@ -6072,14 +6090,14 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
if ((mBfEvalExprFlags & BfEvalExprFlags_NoCeRebuildFlags) != 0)
evalFlags = (CeEvalFlags)(evalFlags | CeEvalFlags_NoRebuild);
if ((mModule->mIsComptimeModule) && (mModule->mCompiler->mCEMachine->mDebugger != NULL) && (mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
if ((mModule->mIsComptimeModule) && (mModule->mCompiler->mCeMachine->mDebugger != NULL) && (mModule->mCompiler->mCeMachine->mDebugger->mCurDbgState != NULL))
{
auto ceDbgState = mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState;
auto ceDbgState = mModule->mCompiler->mCeMachine->mDebugger->mCurDbgState;
if ((ceDbgState->mDbgExpressionFlags & DwEvalExpressionFlag_AllowCalls) != 0)
{
ceDbgState->mHadSideEffects = true;
SetAndRestoreValue<CeDebugger*> prevDebugger(mModule->mCompiler->mCEMachine->mDebugger, NULL);
//SetAndRestoreValue<CeDebugger*> prevDebugger(mModule->mCompiler->mCeMachine->mDebugger, NULL);
evalFlags = (CeEvalFlags)(evalFlags | CeEvalFlags_DbgCall);
auto result = ceDbgState->mCeContext->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
@ -6093,7 +6111,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
}
else
{
auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
auto constRet = mModule->mCompiler->mCeMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
if (constRet)
{
auto constant = mModule->mBfIRBuilder->GetConstant(constRet.mValue);
@ -6121,7 +6139,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
}
else
{
mModule->mCompiler->mCEMachine->QueueMethod(methodInstance, func);
mModule->mCompiler->mCeMachine->QueueMethod(methodInstance, func);
}
}
@ -12678,7 +12696,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
}
auto bindFuncVal = bindResult.mFunc;
if (mModule->mCompiler->mOptions.mAllowHotSwapping)
if ((mModule->mCompiler->mOptions.mAllowHotSwapping) && (!mModule->mIsComptimeModule))
bindFuncVal = mModule->mBfIRBuilder->RemapBindFunction(bindFuncVal);
auto callResult = mModule->mBfIRBuilder->CreateCall(bindFuncVal, irArgs);
auto destCallingConv = mModule->GetIRCallingConvention(bindMethodInstance);
@ -13022,7 +13040,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
}
auto bindFuncVal = bindResult.mFunc;
if (mModule->mCompiler->mOptions.mAllowHotSwapping)
if ((mModule->mCompiler->mOptions.mAllowHotSwapping) && (!mModule->mIsComptimeModule))
bindFuncVal = mModule->mBfIRBuilder->RemapBindFunction(bindFuncVal);
auto callInst = mModule->mBfIRBuilder->CreateCall(bindFuncVal, irArgs);
if (GetStructRetIdx(bindMethodInstance) != -1)
@ -13083,8 +13101,8 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
return;
}
if ((mModule->mCompiler->mOptions.mAllowHotSwapping) && (!bindResult.mMethodInstance->mMethodDef->mIsVirtual))
{
if ((mModule->mCompiler->mOptions.mAllowHotSwapping) && (!bindResult.mMethodInstance->mMethodDef->mIsVirtual) && (!mModule->mIsComptimeModule))
{
funcValue = mModule->mBfIRBuilder->RemapBindFunction(funcValue);
}
}
@ -15349,9 +15367,9 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
allocValue = mModule->AllocFromType(resolvedTypeRef, allocTarget, appendSizeValue, BfIRValue(), 0, BfAllocFlags_None, allocAlign);
}
if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCEMachine != NULL))
if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCeMachine != NULL))
{
mModule->mCompiler->mCEMachine->SetAppendAllocInfo(mModule, allocValue, appendSizeValue);
mModule->mCompiler->mCeMachine->SetAppendAllocInfo(mModule, allocValue, appendSizeValue);
}
mResult = BfTypedValue(allocValue, resultType);
}
@ -15480,9 +15498,9 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
}
}
if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCEMachine != NULL))
if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCeMachine != NULL))
{
mModule->mCompiler->mCEMachine->ClearAppendAllocInfo();
mModule->mCompiler->mCeMachine->ClearAppendAllocInfo();
}
}
@ -16584,13 +16602,13 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
// We can't flush scope state because we extend params in as arbitrary values
mModule->NewScopeState(true, false);
bool wantsDIData = (mModule->mBfIRBuilder->DbgHasInfo()) && (mModule->mHasFullDebugInfo);
bool wantsDIData = (mModule->mBfIRBuilder->DbgHasInfo()) && (mModule->mHasFullDebugInfo);
DISubprogram* diFunction = NULL;
int startLocalIdx = (int)mModule->mCurMethodState->mLocals.size();
int endLocalIdx = startLocalIdx;
if (wantsDIData)
if ((wantsDIData) || (mModule->mIsComptimeModule))
{
BfIRMDNode diFuncType = mModule->mBfIRBuilder->DbgCreateSubroutineType(methodInstance);
@ -16609,7 +16627,10 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
String methodName = methodDef->mName;
methodName += "!";
BfMangler::Mangle(methodName, mModule->mCompiler->GetMangleKind(), methodInstance);
curMethodState->mCurScope->mDIScope = mModule->mBfIRBuilder->DbgCreateFunction(diParentType, methodName, "", mModule->mCurFilePosition.mFileInstance->mDIFile,
String linkageName;
if ((mModule->mIsComptimeModule) && (mModule->mCompiler->mCeMachine->mCurBuilder != NULL))
linkageName = StrFormat("%d", mModule->mCompiler->mCeMachine->mCurBuilder->DbgCreateMethodRef(methodInstance, ""));
curMethodState->mCurScope->mDIScope = mModule->mBfIRBuilder->DbgCreateFunction(diParentType, methodName, linkageName, mModule->mCurFilePosition.mFileInstance->mDIFile,
defLine + 1, diFuncType, false, true, mModule->mCurFilePosition.mCurLine + 1, flags, false, BfIRValue());
scopeData.mAltDIFile = mModule->mCurFilePosition.mFileInstance->mDIFile;
}
@ -16739,7 +16760,7 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
{
//
}
else if (mModule->IsTargetingBeefBackend())
else if ((mModule->IsTargetingBeefBackend()) && (!mModule->mIsComptimeModule))
{
mModule->UpdateSrcPos(methodDeclaration->mNameNode);
mModule->SetIllegalSrcPos();
@ -16767,7 +16788,7 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
else if (newLocalVar->mConstValue)
value = newLocalVar->mConstValue;
auto aliasValue = mModule->mBfIRBuilder->CreateAliasValue(value);
auto aliasValue = mModule->mBfIRBuilder->CreateAliasValue(value);
if (mModule->WantsLifetimes())
scopeData.mDeferredLifetimeEnds.Add(aliasValue);
@ -17559,11 +17580,11 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
{
if (targetFunctionName.StartsWith("__"))
{
auto ceDebugger = mModule->mCompiler->mCEMachine->mDebugger;
auto ceDebugger = mModule->mCompiler->mCeMachine->mDebugger;
auto _ResolveArg = [&](int argIdx, BfType* type = NULL)
{
if (argIdx >= args.mSize)
if ((argIdx < 0) || (argIdx >= args.mSize))
return BfTypedValue();
return mModule->CreateValueFromExpression(args[argIdx], type);
};
@ -17597,6 +17618,141 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
return;
}
}
else if ((targetFunctionName == "__cast") || (targetFunctionName == "__bitcast"))
{
BfType* type = NULL;
String typeName;
for (int argIdx = 0; argIdx < args.mSize - 1; argIdx++)
{
auto arg = _ResolveArg(argIdx);
if (!arg)
continue;
if (arg.mType->IsInstanceOf(mModule->mCompiler->mStringTypeDef))
{
auto strPtr = mModule->GetStringPoolString(arg.mValue, mModule->mBfIRBuilder);
if (strPtr != NULL)
{
if ((type != NULL) && (*strPtr == "*"))
{
type = mModule->CreatePointerType(type);
}
else
typeName += *strPtr;
}
}
if (arg.mType->IsInteger())
{
int64 intVal = ceDebugger->ValueToInt(arg);
if (typeName.IsEmpty())
{
auto typeType = mModule->ResolveTypeDef(mModule->mCompiler->mTypeTypeDef)->ToTypeInstance();
auto fieldDef = typeType->mTypeDef->GetFieldByName("mTypeId");
if (fieldDef != NULL)
{
int typeId = ceDebugger->ReadMemory<int>((intptr)intVal + typeType->mFieldInstances[fieldDef->mIdx].mDataOffset);
type = mModule->mContext->FindTypeById(typeId);
}
}
else
typeName += StrFormat("%lld", intVal);
}
}
auto fromTypedVal = _ResolveArg(args.mSize - 1);
if (!typeName.IsEmpty())
type = ceDebugger->FindType(typeName);
if (type != NULL)
{
if (targetFunctionName == "__bitcast")
{
if ((type->IsObjectOrInterface()) || (type->IsPointer()))
{
auto ceAddrVal = ceDebugger->GetAddr(fromTypedVal);
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateIntToPtr(ceAddrVal.mAddr, mModule->mBfIRBuilder->MapType(type)), type);
}
else
{
Array<uint8> memArr;
memArr.Resize(BF_MAX(type->mSize, fromTypedVal.mType->mSize));
mModule->mBfIRBuilder->WriteConstant(fromTypedVal.mValue, memArr.mVals, fromTypedVal.mType);
auto newVal = mModule->mBfIRBuilder->ReadConstant(memArr.mVals, type);
mResult = BfTypedValue(newVal, type);
}
}
else
mResult = mModule->Cast(target, fromTypedVal, type, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail));
}
return;
}
else if (targetFunctionName == "__stringView")
{
auto ptrVal = _ResolveArg(0);
auto sizeVal = _ResolveArg(1);
if (ceDbgState->mFormatInfo != NULL)
ceDbgState->mFormatInfo->mOverrideCount = (int)ceDebugger->ValueToInt(sizeVal);
mResult = ptrVal;
return;
}
else if ((targetFunctionName == "__funcName") || (targetFunctionName == "__funcTarget"))
{
auto addrVal = _ResolveArg(0);
auto ceAddrVal = ceDebugger->GetAddr(addrVal);
CeFunction* ceFunction = NULL;
int functionId = 0;
if (mModule->mSystem->mPtrSize == 4)
{
functionId = (int)addrVal;
}
else
{
CeFunction* checkCeFunction = (CeFunction*)ceAddrVal.mAddr;
functionId = checkCeFunction->SafeGetId();
}
if (mModule->mCompiler->mCeMachine->mFunctionIdMap.TryGetValue(functionId, &ceFunction))
{
BfMethodInstance* methodInstance = ceFunction->mMethodInstance;
if (methodInstance != NULL)
{
if (targetFunctionName == "__funcTarget")
{
BfType* targetType = methodInstance->GetOwner();
if (targetType->IsValueType())
targetType = mModule->CreatePointerType(targetType);
auto targetVal = _ResolveArg(1);
auto ceTargetVal = ceDebugger->GetAddr(targetVal);
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateIntToPtr(ceTargetVal.mAddr, mModule->mBfIRBuilder->MapType(targetType)), targetType);
return;
}
else
{
mResult = BfTypedValue(mModule->GetStringObjectValue(mModule->MethodToString(methodInstance)),
mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef));
return;
}
}
else if ((ceFunction->mCeInnerFunctionInfo != NULL) && (targetFunctionName == "__funcName"))
{
mResult = BfTypedValue(mModule->GetStringObjectValue(BfDemangler::Demangle(ceFunction->mCeInnerFunctionInfo->mName, DbgLanguage_Beef)),
mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef));
return;
}
}
if (targetFunctionName == "__funcTarget")
mResult = _ResolveArg(1);
else
mResult = addrVal;
return;
}
}
}
}
@ -19475,9 +19631,9 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
}
else if (!alreadyWritten)
{
if ((mModule->mIsComptimeModule) && (mModule->mCompiler->mCEMachine->mDebugger != NULL) && (mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
if ((mModule->mIsComptimeModule) && (mModule->mCompiler->mCeMachine->mDebugger != NULL) && (mModule->mCompiler->mCeMachine->mDebugger->mCurDbgState != NULL))
{
auto ceDbgState = mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState;
auto ceDbgState = mModule->mCompiler->mCeMachine->mDebugger->mCurDbgState;
bool success = false;
if ((convVal.mValue.IsConst()) && (ptr.mValue.IsConst()))
@ -19485,20 +19641,20 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
auto constant = mModule->mBfIRBuilder->GetConstant(ptr.mValue);
auto valConstant = mModule->mBfIRBuilder->GetConstant(convVal.mValue);
auto ceTypedVal = mModule->mCompiler->mCEMachine->mDebugger->GetAddr(constant);
auto ceTypedVal = mModule->mCompiler->mCeMachine->mDebugger->GetAddr(constant);
if (!ceTypedVal)
{
mModule->Fail("Invalid assignment address", assignExpr);
return;
}
auto ceContext = mModule->mCompiler->mCEMachine->mCurContext;
if (ceContext->CheckMemory(ceTypedVal.mAddr, convVal.mType->mSize))
auto ceContext = mModule->mCompiler->mCeMachine->mCurContext;
if (ceContext->CheckMemory((addr_ce)ceTypedVal.mAddr, convVal.mType->mSize))
{
if ((ceDbgState->mDbgExpressionFlags & DwEvalExpressionFlag_AllowSideEffects) != 0)
{
ceDbgState->mHadSideEffects = true;
if (ceContext->WriteConstant(mModule, ceTypedVal.mAddr, valConstant, convVal.mType))
if (ceContext->WriteConstant(mModule, (addr_ce)ceTypedVal.mAddr, valConstant, convVal.mType))
success = true;
}
else
@ -20846,7 +21002,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
}*/
if (mModule->mIsComptimeModule)
mModule->mCompiler->mCEMachine->QueueMethod(oobFunc.mMethodInstance, oobFunc.mFunc);
mModule->mCompiler->mCeMachine->QueueMethod(oobFunc.mMethodInstance, oobFunc.mFunc);
SizedArray<BfIRValue, 1> args;
args.push_back(mModule->GetConstValue(0));

View file

@ -1737,8 +1737,8 @@ CeDbgState* BfModule::GetCeDbgState()
{
if (!mIsComptimeModule)
return NULL;
if ((mCompiler->mCEMachine != NULL) && (mCompiler->mCEMachine->mDebugger != NULL))
return mCompiler->mCEMachine->mDebugger->mCurDbgState;
if ((mCompiler->mCeMachine != NULL) && (mCompiler->mCeMachine->mDebugger != NULL))
return mCompiler->mCeMachine->mDebugger->mCurDbgState;
return NULL;
}
@ -2235,17 +2235,6 @@ bool BfModule::TryLocalVariableInit(BfLocalVariable* localVar)
void BfModule::LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit)
{
//if (localVar->mAddr == NULL)
/*if ((localVar->mValue) && (!localVar->mAddr) && (IsTargetingBeefBackend()))
{
if ((!localVar->mValue.IsConst()) && (!localVar->mValue.IsArg()) && (!localVar->mValue.IsFake()))
{
if (mCurMethodInstance->mMethodDef->mName == "FuncA")
mBfIRBuilder->CreateLifetimeEnd(localVar->mValue);
}
}*/
BfAstNode* localNameNode = localVar->mNameNode;
if (localVar->mIsThis)
{
@ -3076,19 +3065,26 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
//BF_ASSERT(refNode != NULL);
if ((mIsComptimeModule) && (!mCompiler->mCEMachine->mDbgPaused))
if (mIsComptimeModule)
{
mHadBuildError = true;
if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurTargetSrc != NULL))
if (auto ceDbgState = GetCeDbgState())
{
BfError* bfError = mCompiler->mPassInstance->Fail("Comptime method generation had errors", mCompiler->mCEMachine->mCurContext->mCurTargetSrc);
if (bfError != NULL)
mCompiler->mPassInstance->MoreInfo(error, refNode);
return bfError;
// Follow normal fail path
}
else
{
mHadBuildError = true;
if ((mCompiler->mCeMachine->mCurContext != NULL) && (mCompiler->mCeMachine->mCurContext->mCurTargetSrc != NULL))
{
BfError* bfError = mCompiler->mPassInstance->Fail("Comptime method generation had errors", mCompiler->mCeMachine->mCurContext->mCurTargetSrc);
if (bfError != NULL)
mCompiler->mPassInstance->MoreInfo(error, refNode);
return bfError;
}
return NULL;
}
return NULL;
}
if (mCurMethodInstance != NULL)
@ -4439,8 +4435,8 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
else if (fieldDef->mIsConst)
{
int ceExecuteId = -1;
if (mCompiler->mCEMachine != NULL)
ceExecuteId = mCompiler->mCEMachine->mExecuteId;
if (mCompiler->mCeMachine != NULL)
ceExecuteId = mCompiler->mCeMachine->mExecuteId;
BfTypeState typeState;
typeState.mType = mCurTypeInstance;
@ -4463,9 +4459,9 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
}
UpdateSrcPos(initializer);
auto result = constResolver.Resolve(initializer, fieldType, resolveFlags);
if ((mCompiler->mCEMachine != NULL) && (fieldInstance != NULL))
if ((mCompiler->mCeMachine != NULL) && (fieldInstance != NULL))
{
if (mCompiler->mCEMachine->mExecuteId != ceExecuteId)
if (mCompiler->mCeMachine->mExecuteId != ceExecuteId)
fieldInstance->mHadConstEval = true;
}
return result;
@ -5502,7 +5498,7 @@ BfIRValue BfModule::CreateFieldData(BfFieldInstance* fieldInstance, int customAt
{
bool isComptimeArg = mBfIRBuilder->mIgnoreWrites;
BfFieldDef* fieldDef = fieldInstance->GetFieldDef();
auto typeInstance = fieldInstance->mOwner;
BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
@ -10000,6 +9996,8 @@ bool BfModule::IsOptimized()
{
if (mProject == NULL)
return false;
if (mIsComptimeModule)
return false;
int optLevel = GetModuleOptions().mOptLevel;
return (optLevel >= BfOptLevel_O1) && (optLevel <= BfOptLevel_O3);
}
@ -10012,11 +10010,15 @@ bool BfModule::IsTargetingBeefBackend()
}
bool BfModule::WantsLifetimes()
{
if (mProject == NULL)
return false;
{
if (mBfIRBuilder->mIgnoreWrites)
return false;
if ((mIsComptimeModule) && (mBfIRBuilder->HasDebugLocation()))
return true;
else if (mProject == NULL)
return false;
return GetModuleOptions().mOptLevel == BfOptLevel_OgPlus;
}
@ -10086,10 +10088,14 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
void BfModule::EmitEnsureInstructionAt()
{
if (mProject == NULL)
if (mBfIRBuilder->mIgnoreWrites)
return;
if ((mBfIRBuilder->mIgnoreWrites) || (!mHasFullDebugInfo) || (IsOptimized()) || (mCompiler->mOptions.mOmitDebugHelpers))
if (mIsComptimeModule)
{
// Always add
}
else if ((mProject == NULL) || (!mHasFullDebugInfo) || (IsOptimized()) || (mCompiler->mOptions.mOmitDebugHelpers))
return;
mBfIRBuilder->CreateEnsureInstructionAt();
@ -10476,6 +10482,15 @@ BfMethodInstance* BfModule::GetRawMethodInstanceAtIdx(BfTypeInstance* typeInstan
BF_ASSERT(typeInstance->mTypeDef->mMethods[methodIdx]->mName == assertName);
}
if (methodIdx >= typeInstance->mMethodInstanceGroups.mSize)
{
if (mCompiler->EnsureCeUnpaused(typeInstance))
{
BF_FATAL("OOB in GetRawMethodInstanceAtIdx");
}
return NULL;
}
auto& methodGroup = typeInstance->mMethodInstanceGroups[methodIdx];
if (methodGroup.mDefault == NULL)
{
@ -12464,27 +12479,31 @@ BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bo
}
}
if ((mIsComptimeModule) && (mCompiler->mCEMachine->mDebugger != NULL) && (mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
if ((mIsComptimeModule) && (mCompiler->mCeMachine->mDebugger != NULL) && (mCompiler->mCeMachine->mDebugger->mCurDbgState != NULL))
{
auto ceDebugger = mCompiler->mCEMachine->mDebugger;
auto ceDebugger = mCompiler->mCeMachine->mDebugger;
auto ceContext = ceDebugger->mCurDbgState->mCeContext;
auto activeFrame = ceDebugger->mCurDbgState->mActiveFrame;
auto ceTypedValue = ceDebugger->GetAddr(constantValue);
if (ceTypedValue)
{
if ((typedValue.mType->IsObjectOrInterface()) || (typedValue.mType->IsPointer()))
if ((typedValue.mType->IsObjectOrInterface()) || (typedValue.mType->IsPointer()) || (typedValue.mType->IsRef()))
{
void* data = ceContext->GetMemoryPtr(ceTypedValue.mAddr, sizeof(addr_ce));
void* data = ceContext->GetMemoryPtr((addr_ce)ceTypedValue.mAddr, sizeof(addr_ce));
if (data == NULL)
{
Fail("Invalid address", refNode);
return GetDefaultTypedValue(typedValue.mType);
}
addr_ce dataAddr = *(addr_ce*)data;
uint64 dataAddr;
if (mSystem->mPtrSize == 4)
dataAddr = *(uint32*)data;
else
dataAddr = *(uint64*)data;
return BfTypedValue(mBfIRBuilder->CreateIntToPtr(
mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)dataAddr), mBfIRBuilder->MapType(typedValue.mType)), typedValue.mType);
mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, dataAddr), mBfIRBuilder->MapType(typedValue.mType)), typedValue.mType);
}
auto constVal = ceContext->CreateConstant(this, ceContext->mMemory.mVals + ceTypedValue.mAddr, typedValue.mType);
@ -13474,7 +13493,7 @@ BfModule* BfModule::GetOrCreateMethodModule(BfMethodInstance* methodInstance)
}
BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags, BfTypeInstance* foreignType)
{
{
if (methodDef->mMethodType == BfMethodType_Init)
return BfModuleMethodInstance();
@ -13534,7 +13553,16 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
PopulateType(typeInst, BfPopulateType_AllowStaticMethods);
}
else
PopulateType(typeInst, BfPopulateType_Full);
PopulateType(typeInst, BfPopulateType_Full);
if (typeInst->mDefineState < BfTypeDefineState_Defined)
{
if (!mCompiler->EnsureCeUnpaused(typeInst))
{
BfLogSysM("GetMethodInstance (DefineState < BfTypeDefineState_Defined)) bailing due to IsCePaused\n");
return BfModuleMethodInstance();
}
}
}
bool tryModuleMethodLookup = false;
@ -14134,6 +14162,12 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
if (methodInstance == NULL)
{
if (!mCompiler->EnsureCeUnpaused(typeInst))
{
BfLogSysM("GetMethodInstance (methodInstance == NULL) bailing due to IsCePaused\n");
return BfModuleMethodInstance();
}
if (lookupMethodGenericArguments.size() == 0)
{
BF_ASSERT(methodInstGroup->mDefault == NULL);
@ -14586,7 +14620,7 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance)
if (mIsComptimeModule)
{
mCompiler->mCEMachine->QueueStaticField(fieldInstance, staticVarName);
mCompiler->mCeMachine->QueueStaticField(fieldInstance, staticVarName);
}
PopulateType(typeType);
@ -14649,9 +14683,24 @@ void BfModule::MarkUsingThis()
BfTypedValue BfModule::GetThis(bool markUsing)
{
if ((mIsComptimeModule) && (mCompiler->mCEMachine->mDebugger != NULL) && (mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
if ((mIsComptimeModule) && (mCompiler->mCeMachine->mDebugger != NULL) && (mCompiler->mCeMachine->mDebugger->mCurDbgState != NULL))
{
return mCompiler->mCEMachine->mDebugger->mCurDbgState->mExplicitThis;
if (mCompiler->mCeMachine->mDebugger->mCurDbgState->mExplicitThis)
return mCompiler->mCeMachine->mDebugger->mCurDbgState->mExplicitThis;
auto ceDebugger = mCompiler->mCeMachine->mDebugger;
auto activeFrame = ceDebugger->mCurDbgState->mActiveFrame;
if ((activeFrame != NULL) && (activeFrame->mFunction->mDbgInfo != NULL))
{
for (auto& dbgVar : activeFrame->mFunction->mDbgInfo->mVariables)
{
if (dbgVar.mName == "this")
return BfTypedValue(mBfIRBuilder->CreateConstAggCE(mBfIRBuilder->MapType(dbgVar.mType), activeFrame->mFrameAddr + dbgVar.mValue.mFrameOfs), dbgVar.mType,
dbgVar.mIsConst ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Addr);
}
}
return BfTypedValue();
}
auto useMethodState = mCurMethodState;
@ -15028,7 +15077,7 @@ void BfModule::DoLocalVariableDebugInfo(BfLocalVariable* localVarDef, bool doAli
}
else
{
if ((IsTargetingBeefBackend()) && (doAliasValue))
if ((IsTargetingBeefBackend()) && (doAliasValue) && (!mIsComptimeModule))
{
diValue = mBfIRBuilder->CreateAliasValue(diValue);
mCurMethodState->mCurScope->mDeferredLifetimeEnds.Add(diValue);
@ -15936,6 +15985,8 @@ BfType* BfModule::GetDelegateReturnType(BfType* delegateType)
auto typeInst = delegateType->ToTypeInstance();
PopulateType(typeInst, BfPopulateType_DataAndMethods);
BfMethodInstance* invokeMethodInstance = GetRawMethodInstanceAtIdx(typeInst->ToTypeInstance(), 0, "Invoke");
if (invokeMethodInstance == NULL)
return GetPrimitiveType(BfTypeCode_Var);
return invokeMethodInstance->mReturnType;
}
@ -16578,7 +16629,7 @@ void BfModule::EmitDtorBody()
auto dtorFunc = GetMethodByName(mContext->mBfObjectType, "~this");
if (mIsComptimeModule)
mCompiler->mCEMachine->QueueMethod(dtorFunc.mMethodInstance, dtorFunc.mFunc);
mCompiler->mCeMachine->QueueMethod(dtorFunc.mMethodInstance, dtorFunc.mFunc);
auto basePtr = mBfIRBuilder->CreateBitCast(thisVal.mValue, mBfIRBuilder->MapTypeInstPtr(mContext->mBfObjectType));
SizedArray<BfIRValue, 1> vals = { basePtr };
result = mBfIRBuilder->CreateCall(dtorFunc.mFunc, vals);
@ -16762,7 +16813,7 @@ void BfModule::EmitDtorBody()
SizedArray<BfIRValue, 1> vals = { basePtr };
auto callInst = mBfIRBuilder->CreateCall(dtorMethodInstance.mFunc, vals);
if (mIsComptimeModule)
mCompiler->mCEMachine->QueueMethod(dtorMethodInstance.mMethodInstance, dtorMethodInstance.mFunc);
mCompiler->mCeMachine->QueueMethod(dtorMethodInstance.mMethodInstance, dtorMethodInstance.mFunc);
mBfIRBuilder->SetCallCallingConv(callInst, GetIRCallingConvention(dtorMethodInstance.mMethodInstance));
}
}
@ -17354,7 +17405,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
exprEvaluator.PushThis(NULL, GetThis(), moduleMethodInstance.mMethodInstance, irArgs);
exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
if (mIsComptimeModule)
mCompiler->mCEMachine->QueueMethod(moduleMethodInstance);
mCompiler->mCeMachine->QueueMethod(moduleMethodInstance);
calledCtorNoBody = true;
}
@ -17416,7 +17467,11 @@ void BfModule::EmitCtorBody(bool& skipBody)
mCurMethodState->mCurScope->mDIInlinedAt = mBfIRBuilder->DbgGetCurrentLocation();
BF_ASSERT(mCurMethodState->mCurScope->mDIInlinedAt);
// mCurMethodState->mCurScope->mDIInlinedAt may still be null ifwe don't have an explicit ctor
mCurMethodState->mCurScope->mDIScope = mBfIRBuilder->DbgCreateFunction(mBfIRBuilder->DbgGetTypeInst(mCurTypeInstance), "this$initFields", "", mCurFilePosition.mFileInstance->mDIFile,
String linkageName;
if ((mIsComptimeModule) && (mCompiler->mCeMachine->mCurBuilder != NULL))
linkageName = StrFormat("%d", mCompiler->mCeMachine->mCurBuilder->DbgCreateMethodRef(mCurMethodInstance, "$initFields"));
mCurMethodState->mCurScope->mDIScope = mBfIRBuilder->DbgCreateFunction(mBfIRBuilder->DbgGetTypeInst(mCurTypeInstance), "this$initFields", linkageName, mCurFilePosition.mFileInstance->mDIFile,
mCurFilePosition.mCurLine + 1, diFuncType, false, true, mCurFilePosition.mCurLine + 1, flags, false, BfIRValue());
UpdateSrcPos(node);
@ -17709,7 +17764,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
if (callingConv != BfIRCallingConv_CDecl)
mBfIRBuilder->SetCallCallingConv(callInst, callingConv);
if (mIsComptimeModule)
mCompiler->mCEMachine->QueueMethod(ctorBodyMethodInstance);
mCompiler->mCeMachine->QueueMethod(ctorBodyMethodInstance);
}
if (matchedMethod == NULL)
@ -19667,7 +19722,9 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
bool wantsDIData = (mBfIRBuilder->DbgHasInfo()) && (!methodDef->IsEmptyPartial()) && (!mBfIRBuilder->mIgnoreWrites) && (mHasFullDebugInfo);
if (methodDef->mMethodType == BfMethodType_Mixin)
wantsDIData = false;
if (mCurTypeInstance->IsUnspecializedType())
wantsDIData = false;
if ((mCurTypeInstance->IsBoxed()) && (methodDef->mMethodType != BfMethodType_Ctor))
wantsDIData = false;
@ -22661,6 +22718,8 @@ void BfModule::StartMethodDeclaration(BfMethodInstance* methodInstance, BfMethod
// methodDeclaration is NULL for default constructors
void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool isTemporaryFunc, bool addToWorkList)
{
BF_ASSERT((mCompiler->mCeMachine == NULL) || (!mCompiler->mCeMachine->mDbgPaused));
BP_ZONE("BfModule::DoMethodDeclaration");
// We could trigger a DoMethodDeclaration from a const resolver or other location, so we reset it here

View file

@ -1273,6 +1273,13 @@ public:
{
return !(*this == other);
}
BfModuleOptions()
{
mSIMDSetting = BfSIMDSetting_None;
mEmitDebugInfo = false;
mOptLevel = BfOptLevel_NotSet;
}
};
struct BfGenericParamSource
@ -1543,7 +1550,7 @@ public:
void SetFail();
void VerifyOnDemandMethods();
bool IsSkippingExtraResolveChecks();
bool AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool& isWhileSpecializing, bool isWarning);
bool AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool& isWhileSpecializing, bool isWarning);
CeDbgState* GetCeDbgState();
BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false, bool deferError = false);
BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL);

View file

@ -2220,8 +2220,8 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
if (methodInstance == NULL)
continue;
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCEMachine->mCurEmitContext, ceEmitContext);
auto ceContext = mCompiler->mCEMachine->AllocContext();
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCeMachine->mCurEmitContext, ceEmitContext);
auto ceContext = mCompiler->mCeMachine->AllocContext();
BfIRValue attrVal =ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute);
for (int baseIdx = 0; baseIdx < checkDepth; baseIdx++)
@ -2266,7 +2266,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred);
if (fieldInstance != NULL)
mCompiler->mCEMachine->mFieldInstanceSet.Add(fieldInstance);
mCompiler->mCeMachine->mFieldInstanceSet.Add(fieldInstance);
BfTypedValue result;
///
{
@ -2274,7 +2274,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_ForceReturnThis, NULL);
}
if (fieldInstance != NULL)
mCompiler->mCEMachine->mFieldInstanceSet.Remove(fieldInstance);
mCompiler->mCeMachine->mFieldInstanceSet.Remove(fieldInstance);
if (result.mType == methodInstance->GetOwner())
prevAttrInstances[methodInstance->GetOwner()] = result.mValue;
@ -2334,7 +2334,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
}
}
mCompiler->mCEMachine->ReleaseContext(ceContext);
mCompiler->mCeMachine->ReleaseContext(ceContext);
}
}
@ -2391,7 +2391,10 @@ void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code)
auto diParentType = mBfIRBuilder->DbgGetTypeInst(mCurTypeInstance);
if (!mBfIRBuilder->mIgnoreWrites)
{
String methodName = "Comptime_Mixin";
String methodName = "Comptime_Mixin";
String linkageName;
if (mIsComptimeModule)
linkageName = StrFormat("Comptime_Mixin:%llX", mCurMethodInstance);
mCurMethodState->mCurScope->mDIScope = mBfIRBuilder->DbgCreateFunction(diParentType, methodName, "", mCurFilePosition.mFileInstance->mDIFile,
defLine + 1, diFuncType, false, true, mCurFilePosition.mCurLine + 1, flags, false, BfIRValue());
mCurMethodState->mCurScope->mAltDIFile = mCurFilePosition.mFileInstance->mDIFile;
@ -2502,7 +2505,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
}
if (!wantsAttributes)
return;
continue;
auto customAttributes = GetCustomAttributes(methodDeclaration->mAttributes, BfAttributeTargets_Method);
defer({ delete customAttributes; });
@ -2533,15 +2536,15 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
continue;
}
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCEMachine->mCurEmitContext);
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCeMachine->mCurEmitContext);
if (onCompileKind == BfCEOnCompileKind_TypeInit)
{
mCompiler->mCEMachine->mCurEmitContext = ceEmitContext;
mCompiler->mCeMachine->mCurEmitContext = ceEmitContext;
}
DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred);
auto methodInstance = GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx);
auto result = mCompiler->mCEMachine->Call(methodDef->GetRefNode(), this, methodInstance, {}, (CeEvalFlags)(CeEvalFlags_PersistantError | CeEvalFlags_DeferIfNotOnlyError), NULL);
auto result = mCompiler->mCeMachine->Call(methodDef->GetRefNode(), this, methodInstance, {}, (CeEvalFlags)(CeEvalFlags_PersistantError | CeEvalFlags_DeferIfNotOnlyError), NULL);
if ((onCompileKind == BfCEOnCompileKind_TypeDone) && (typeInstance->mDefineState > BfTypeDefineState_CETypeInit))
{
@ -2670,8 +2673,8 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
if (applyMethodInstance == NULL)
continue;
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCEMachine->mCurEmitContext, &ceEmitContext);
auto ceContext = mCompiler->mCEMachine->AllocContext();
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCeMachine->mCurEmitContext, &ceEmitContext);
auto ceContext = mCompiler->mCeMachine->AllocContext();
BfIRValue attrVal = ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute);
for (int baseIdx = 0; baseIdx < checkDepth; baseIdx++)
@ -2707,7 +2710,7 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
continue;
}
mCompiler->mCEMachine->mMethodInstanceSet.Add(methodInstance);
mCompiler->mCeMachine->mMethodInstanceSet.Add(methodInstance);
auto activeTypeDef = typeInstance->mTypeDef;
BfTypedValue result;
@ -2783,7 +2786,7 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
}
}
mCompiler->mCEMachine->ReleaseContext(ceContext);
mCompiler->mCeMachine->ReleaseContext(ceContext);
}
}
@ -3184,6 +3187,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (populateType == BfPopulateType_Identity)
return;
if ((populateType <= BfPopulateType_Data) && (resolvedTypeRef->mDefineState >= BfTypeDefineState_Defined))
return;
auto typeInstance = resolvedTypeRef->ToTypeInstance();
auto typeDef = typeInstance->mTypeDef;
@ -3214,7 +3220,21 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (typeInstance->mResolvingConstField)
return;
// Partial population break out point
if ((populateType >= BfPopulateType_Identity) && (populateType <= BfPopulateType_IdentityNoRemapAlias))
return;
if ((populateType <= BfPopulateType_AllowStaticMethods) && (typeInstance->mDefineState >= BfTypeDefineState_HasInterfaces))
return;
if (!mCompiler->EnsureCeUnpaused(resolvedTypeRef))
{
// We need to avoid comptime reentry when the ceDebugger is paused
BfLogSysM("DoPopulateType %p bailing due to IsCePaused\n", resolvedTypeRef);
return;
}
auto _CheckTypeDone = [&]()
{
if (typeInstance->mNeedsMethodProcessing)
@ -3230,13 +3250,6 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
};
if (_CheckTypeDone())
return;
// Partial population break out point
if ((populateType >= BfPopulateType_Identity) && (populateType <= BfPopulateType_IdentityNoRemapAlias))
return;
if ((populateType <= BfPopulateType_AllowStaticMethods) && (typeInstance->mDefineState >= BfTypeDefineState_HasInterfaces))
return;
if (!resolvedTypeRef->IsValueType())
@ -4482,17 +4495,17 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if ((foundTypeCount >= 2) || (typeInstance->mTypeDef->IsEmitted()))
{
String error = "OnCompile const evaluation creates a data dependency during TypeInit";
if (mCompiler->mCEMachine->mCurBuilder != NULL)
if (mCompiler->mCeMachine->mCurBuilder != NULL)
{
error += StrFormat(" during const-eval generation of '%s'", MethodToString(mCompiler->mCEMachine->mCurBuilder->mCeFunction->mMethodInstance).c_str());
error += StrFormat(" during const-eval generation of '%s'", MethodToString(mCompiler->mCeMachine->mCurBuilder->mCeFunction->mMethodInstance).c_str());
}
auto refNode = typeDef->GetRefNode();
Fail(error, refNode);
if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurFrame != NULL))
mCompiler->mCEMachine->mCurContext->Fail(*mCompiler->mCEMachine->mCurContext->mCurFrame, error);
else if (mCompiler->mCEMachine->mCurContext != NULL)
mCompiler->mCEMachine->mCurContext->Fail(error);
if ((mCompiler->mCeMachine->mCurContext != NULL) && (mCompiler->mCeMachine->mCurContext->mCurFrame != NULL))
mCompiler->mCeMachine->mCurContext->Fail(*mCompiler->mCeMachine->mCurContext->mCurFrame, error);
else if (mCompiler->mCeMachine->mCurContext != NULL)
mCompiler->mCeMachine->mCurContext->Fail(error);
tryCE = false;
}
}
@ -11900,7 +11913,7 @@ BfIRValue BfModule::CastToFunction(BfAstNode* srcNode, const BfTypedValue& targe
}
bindFuncVal = methodRefMethod.mFunc;
}
if (mCompiler->mOptions.mAllowHotSwapping)
if ((mCompiler->mOptions.mAllowHotSwapping) && (!mIsComptimeModule))
bindFuncVal = mBfIRBuilder->RemapBindFunction(bindFuncVal);
return mBfIRBuilder->CreatePtrToInt(bindFuncVal, BfTypeCode_IntPtr);
}

View file

@ -617,8 +617,8 @@ void BfMethodInstance::Dispose(bool isDeleting)
if (mInCEMachine)
{
auto module = GetOwner()->mModule;
if (module->mCompiler->mCEMachine != NULL)
module->mCompiler->mCEMachine->RemoveMethod(this);
if (module->mCompiler->mCeMachine != NULL)
module->mCompiler->mCeMachine->RemoveMethod(this);
}
if (mMethodProcessRequest != NULL)

View file

@ -464,7 +464,7 @@ bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfSc
listEntry->mDynList.PushFront(deferredCallEntry);
}
if ((mBfIRBuilder->DbgHasInfo()) && (mCompiler->mOptions.mEmitDebugInfo) && (mCurMethodState->mCurScope->mDIScope))
if ((mBfIRBuilder->DbgHasInfo()) && (mHasFullDebugInfo) && (mCompiler->mOptions.mEmitDebugInfo) && (mCurMethodState->mCurScope->mDIScope))
{
auto int64Type = GetPrimitiveType(BfTypeCode_Int64);
auto moduleMethodInstance = deferredCallEntry->mModuleMethodInstance;
@ -511,7 +511,7 @@ bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfSc
diFieldTypes.push_back(memberType);
}
}
int diFlags = 0;
mBfIRBuilder->DbgMakePermanent(diForwardDecl, BfIRMDNode(), diFieldTypes);
deferDIType = mBfIRBuilder->DbgCreatePointerType(diForwardDecl);

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,15 @@ class CeFunction;
class BfReducer;
class CeDebugger;
class DebugVisualizerEntry;
class CeEvaluationContext;
class CeBreakpointCondition
{
public:
CeEvaluationContext* mDbgEvaluationContext;
String mExpr;
~CeBreakpointCondition();
};
class CeBreakpoint : public Breakpoint
{
@ -24,6 +33,7 @@ public:
uintptr mCurBindAddr;
bool mHasBound;
int mIdx;
CeBreakpointCondition* mCondition;
public:
CeBreakpoint()
@ -31,8 +41,10 @@ public:
mCurBindAddr = 1;
mHasBound = false;
mIdx = -1;
mCondition = NULL;
}
~CeBreakpoint();
virtual uintptr GetAddr() { return mCurBindAddr; }
virtual bool IsMemoryBreakpointBound() { return false; }
};
@ -98,7 +110,7 @@ public:
void Init(CeDebugger* winDebugger, const StringImpl& expr, CeFormatInfo* formatInfo = NULL, BfTypedValue contextValue = BfTypedValue());
bool HasExpression();
~CeEvaluationContext();
BfTypedValue EvaluateInContext(BfTypedValue contextTypedValue);
BfTypedValue EvaluateInContext(BfTypedValue contextTypedValue, CeDbgState* dbgState = NULL);
String GetErrorStr();
bool HadError();
};
@ -110,17 +122,21 @@ public:
CeContext* mCeContext;
BfTypedValue mExplicitThis;
DwEvalExpressionFlags mDbgExpressionFlags;
CeFormatInfo* mFormatInfo;
bool mHadSideEffects;
bool mBlockedSideEffects;
bool mReferencedIncompleteTypes;
public:
CeDbgState()
{
mActiveFrame = NULL;
mCeContext = NULL;
mFormatInfo = NULL;
mDbgExpressionFlags = DwEvalExpressionFlag_None;
mHadSideEffects = false;
mBlockedSideEffects = false;
mReferencedIncompleteTypes = false;
}
};
@ -128,6 +144,7 @@ class CePendingExpr
{
public:
int mThreadId;
BfPassInstance* mPassInstance;
BfParser* mParser;
BfType* mExplitType;
CeFormatInfo mFormatInfo;
@ -138,12 +155,21 @@ public:
int mCallStackIdx;
String mResult;
int mIdleTicks;
String mException;
String mException;
bool mDone;
CePendingExpr();
~CePendingExpr();
};
class CeDbgStackInfo
{
public:
int mFrameIdx;
int mScopeIdx;
int mInlinedFrom;
};
class CeFileInfo
{
public:
@ -182,7 +208,7 @@ public:
struct CeTypedValue
{
addr_ce mAddr;
int64 mAddr;
BfIRType mType;
CeTypedValue()
@ -191,7 +217,7 @@ struct CeTypedValue
mType = BfIRType();
}
CeTypedValue(addr_ce addr, BfIRType type)
CeTypedValue(int64 addr, BfIRType type)
{
mAddr = addr;
mType = type;
@ -203,6 +229,13 @@ struct CeTypedValue
}
};
enum CeTypeModKind
{
CeTypeModKind_Normal,
CeTypeModKind_Const,
CeTypeModKind_ReadOnly
};
class CeDebugger : public Debugger
{
public:
@ -212,8 +245,9 @@ public:
CePendingExpr* mDebugPendingExpr;
CeDbgState* mCurDbgState;
Array<CeBreakpoint*> mBreakpoints;
Dictionary<String, CeFileInfo*> mFileInfo;
Dictionary<String, CeFileInfo*> mFileInfo;
Dictionary<int, CeDbgTypeInfo> mDbgTypeInfoMap;
Array<CeDbgStackInfo> mDbgCallStack;
CeEvaluationContext* mCurEvaluationContext;
CeBreakpoint* mActiveBreakpoint;
@ -221,11 +255,23 @@ public:
bool mBreakpointCacheDirty;
bool mBreakpointFramesDirty;
int mCurDisasmFuncId;
int mPendingActiveFrameOffset;
public:
template<typename T> T ReadMemory(intptr addr, bool* failed = NULL)
{
T val;
memset(&val, 0, sizeof(T));
bool success = ReadMemory(addr, (int)sizeof(T), &val);
if (failed != NULL)
*failed = !success;
return val;
}
bool CheckConditionalBreakpoint(CeBreakpoint* breakpoint);
bool SetupStep(int frameIdx = 0);
CeFrame* GetFrame(int callStackIdx);
String EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& bfPassInstance);
CeFrame* GetFrame(int callStackIdx);
String DoEvaluate(CePendingExpr* pendingExpr, bool inCompilerThread);
String Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags);
DwDisplayInfo* GetDisplayInfo(const StringImpl& referenceId);
String GetMemberList(BfType* type, addr_ce addr, addr_ce addrInst, bool isStatic);
@ -239,12 +285,13 @@ public:
String GetDictionaryItems(DebugVisualizerEntry* debugVis, BfTypedValue dictValue, int bucketIdx, int nodeIdx, int& count, String* outContinuationData);
String GetTreeItems(DebugVisualizerEntry* debugVis, Array<addr_ce>& parentList, BfType*& valueType, BfTypedValue& curNode, int count, String* outContinuationData);
bool EvalCondition(DebugVisualizerEntry* debugVis, BfTypedValue typedVal, CeFormatInfo& formatInfo, const StringImpl& condition, const Array<String>& dbgVisWildcardCaptures, String& errorStr);
CeTypedValue GetAddr(BfConstant* constant);
CeTypedValue GetAddr(BfConstant* constant, BfType* type = NULL);
CeTypedValue GetAddr(const BfTypedValue typeVal);
String ReadString(BfTypeCode charType, intptr addr, intptr maxLength, CeFormatInfo& formatInfo);
void ProcessEvalString(BfTypedValue useTypedValue, String& evalStr, String& displayString, CeFormatInfo& formatInfo, DebugVisualizerEntry* debugVis, bool limitLength);
String TypedValueToString(const BfTypedValue& typedValue, const StringImpl& expr, CeFormatInfo& formatFlags, bool fullPrecision = false);
String TypedValueToString(const BfTypedValue& typedValue, const StringImpl& expr, CeFormatInfo& formatFlags, bool fullPrecision = false, CeTypeModKind typeModKind = CeTypeModKind_Normal);
void HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* debugVis, BfTypedValue typedValue, addr_ce addr, addr_ce addrInst, Array<String>& dbgVisWildcardCaptures, CeFormatInfo& formatInfo);
String GetAutocompleteOutput(BfAutoComplete& autoComplete);
void ClearBreakpointCache();
void UpdateBreakpointCache();
void UpdateBreakpointFrames();
@ -253,8 +300,11 @@ public:
void Continue();
CeDbgTypeInfo* GetDbgTypeInfo(int typeId);
CeDbgTypeInfo* GetDbgTypeInfo(BfIRType irType);
int64 ValueToInt(addr_ce addr, BfType* type);
int64 ValueToInt(const BfTypedValue& typedVal);
BfType* FindType(const StringImpl& name);
String TypeToString(const BfTypedValue& typedValue);
String TypeToString(BfType* type, CeTypeModKind typeModKind);
public:
CeDebugger(DebugManager* debugManager, BfCompiler* bfCompiler);

View file

@ -96,6 +96,7 @@ struct CeOpInfo
static CeOpInfo gOpInfo[] =
{
{"InvalidOp"},
{"Nop"},
{"DbgBreak"},
{"Ret"},
{"SetRet", CEOI_None, CEOI_IMM32},
@ -307,6 +308,35 @@ static int DoubleToString(double d, char* outStr)
//////////////////////////////////////////////////////////////////////////
String CeDbgMethodRef::ToString()
{
if (!mMethodRef)
return mNameMod;
BfMethodInstance* methodInstance = mMethodRef;
auto module = methodInstance->GetOwner()->mModule;
String name = module->MethodToString(methodInstance);
if (!mNameMod.IsEmpty())
{
for (int i = 1; i < (int)name.length(); i++)
{
if (name[i] == '(')
{
char prevC = name[i - 1];
if ((::isalnum((uint8)prevC)) || (prevC == '_'))
{
name.Insert(i, mNameMod);
break;
}
}
}
}
return name;
}
//////////////////////////////////////////////////////////////////////////
CeInternalData::~CeInternalData()
{
switch (mKind)
@ -391,6 +421,19 @@ CeEmitEntry* CeFunction::FindEmitEntry(int instIdx, int* entryIdx)
return emitEntry;
}
int CeFunction::SafeGetId()
{
__try
{
return mId;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
CeFunctionInfo::~CeFunctionInfo()
@ -643,7 +686,7 @@ void CeBuilder::Fail(const StringImpl& str)
if (!mCeFunction->mGenError.IsEmpty())
return;
String errStr = StrFormat("Failure during const code generation of %s: %s", mBeFunction->mName.c_str(), str.c_str());
String errStr = StrFormat("Failure during comptime generation of %s: %s", mBeFunction->mName.c_str(), str.c_str());
if (mCurDbgLoc != NULL)
{
String filePath;
@ -927,6 +970,51 @@ CeOperand CeBuilder::EmitConst(int64 val, int size)
return result;
}
int CeBuilder::GetCallTableIdx(BeFunction* beFunction, CeOperand* outOperand)
{
int* callIdxPtr = NULL;
if (mFunctionMap.TryAdd(beFunction, NULL, &callIdxPtr))
{
CeFunctionInfo* ceFunctionInfo = NULL;
mCeMachine->mNamedFunctionMap.TryGetValue(beFunction->mName, &ceFunctionInfo);
if (ceFunctionInfo != NULL)
ceFunctionInfo->mRefCount++;
else
{
if (outOperand != NULL)
{
auto checkBuilder = this;
if (checkBuilder->mParentBuilder != NULL)
checkBuilder = checkBuilder->mParentBuilder;
int innerFunctionIdx = 0;
if (checkBuilder->mInnerFunctionMap.TryGetValue(beFunction, &innerFunctionIdx))
{
auto innerFunction = checkBuilder->mCeFunction->mInnerFunctions[innerFunctionIdx];
if (innerFunction->mInitializeState < CeFunction::InitializeState_Initialized)
mCeMachine->PrepareFunction(innerFunction, checkBuilder);
CeOperand result = FrameAlloc(mCeMachine->GetBeContext()->GetPrimitiveType((sizeof(BfMethodInstance*) == 8) ? BeTypeCode_Int64 : BeTypeCode_Int32));
Emit(CeOp_GetMethod_Inner);
EmitFrameOffset(result);
Emit((int32)innerFunctionIdx);
*outOperand = result;
return -1;
}
}
Fail(StrFormat("Unable to locate method %s", beFunction->mName.c_str()));
}
CeCallEntry callEntry;
callEntry.mFunctionInfo = ceFunctionInfo;
*callIdxPtr = (int)mCeFunction->mCallTable.size();
mCeFunction->mCallTable.Add(callEntry);
}
return *callIdxPtr;
}
CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImmediate)
{
if (value == NULL)
@ -1281,55 +1369,25 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
case BeFunction::TypeId:
{
auto beFunction = (BeFunction*)value;
int* callIdxPtr = NULL;
if (mFunctionMap.TryAdd(beFunction, NULL, &callIdxPtr))
{
CeFunctionInfo* ceFunctionInfo = NULL;
mCeMachine->mNamedFunctionMap.TryGetValue(beFunction->mName, &ceFunctionInfo);
if (ceFunctionInfo != NULL)
ceFunctionInfo->mRefCount++;
else
{
auto checkBuilder = this;
if (checkBuilder->mParentBuilder != NULL)
checkBuilder = checkBuilder->mParentBuilder;
int innerFunctionIdx = 0;
if (checkBuilder->mInnerFunctionMap.TryGetValue(beFunction, &innerFunctionIdx))
{
auto innerFunction = checkBuilder->mCeFunction->mInnerFunctions[innerFunctionIdx];
if (innerFunction->mInitializeState < CeFunction::InitializeState_Initialized)
mCeMachine->PrepareFunction(innerFunction, checkBuilder);
CeOperand result = FrameAlloc(mCeMachine->GetBeContext()->GetPrimitiveType((sizeof(BfMethodInstance*) == 8) ? BeTypeCode_Int64 : BeTypeCode_Int32));
Emit(CeOp_GetMethod_Inner);
EmitFrameOffset(result);
Emit((int32)innerFunctionIdx);
return result;
}
Fail(StrFormat("Unable to locate method %s", beFunction->mName.c_str()));
}
CeCallEntry callEntry;
callEntry.mFunctionInfo = ceFunctionInfo;
*callIdxPtr = (int)mCeFunction->mCallTable.size();
mCeFunction->mCallTable.Add(callEntry);
}
CeOperand operand;
int callIdx = GetCallTableIdx(beFunction, &operand);
if (operand)
return operand;
if (allowImmediate)
{
CeOperand result;
result.mKind = CeOperandKind_CallTableIdx;
result.mCallTableIdx = *callIdxPtr;
result.mCallTableIdx = callIdx;
return result;
}
BF_ASSERT(callIdx <= mCeFunction->mCallTable.mSize);
CeOperand result = FrameAlloc(mCeMachine->GetBeContext()->GetPrimitiveType((sizeof(BfMethodInstance*) == 8) ? BeTypeCode_Int64 : BeTypeCode_Int32));
Emit(CeOp_GetMethod);
EmitFrameOffset(result);
Emit((int32)*callIdxPtr);
Emit((int32)callIdx);
return result;
}
break;
@ -1399,6 +1457,20 @@ CeSizeClass CeBuilder::GetSizeClass(int size)
}
}
int CeBuilder::DbgCreateMethodRef(BfMethodInstance* methodInstance, const StringImpl& nameMod)
{
CeDbgMethodRef dbgMethodRef;
dbgMethodRef.mNameMod = nameMod;
dbgMethodRef.mMethodRef = methodInstance;
int* valuePtr = NULL;
if (mDbgMethodRefMap.TryAdd(dbgMethodRef, NULL, &valuePtr))
{
*valuePtr = mCeFunction->mDbgMethodRefTable.mSize;
mCeFunction->mDbgMethodRefTable.Add(dbgMethodRef);
}
return *valuePtr;
}
void CeBuilder::HandleParams()
{
auto beModule = mBeFunction->mModule;
@ -1480,6 +1552,10 @@ void CeBuilder::ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance
void CeBuilder::Build()
{
SetAndRestoreValue<CeDbgState*> prevDbgState;
if (mCeMachine->mDebugger != NULL)
prevDbgState.Init(mCeMachine->mDebugger->mCurDbgState, NULL);
auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen;
auto irBuilder = mCeMachine->mCeModule->mBfIRBuilder;
auto beModule = irCodeGen->mBeModule;
@ -1493,7 +1569,7 @@ void CeBuilder::Build()
BfMethodInstance dupMethodInstance;
dupMethodInstance.CopyFrom(methodInstance);
auto methodDef = methodInstance->mMethodDef;
bool isGenericVariation = (methodInstance->mIsUnspecializedVariation) || (methodInstance->GetOwner()->IsUnspecializedTypeVariation());
int dependentGenericStartIdx = 0;
if ((((methodInstance->mMethodInfoEx != NULL) && ((int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size() > dependentGenericStartIdx)) ||
@ -1510,7 +1586,7 @@ void CeBuilder::Build()
}
// Clear this so we can properly get QueueStaticField calls
mCeMachine->mCeModule->mStaticFieldRefs.Clear();
mCeMachine->mCeModule->mStaticFieldRefs.Clear();
int startFunctionCount = (int)beModule->mFunctions.size();
ProcessMethod(methodInstance, &dupMethodInstance, true);
@ -1640,6 +1716,8 @@ void CeBuilder::Build()
}
}
int scopeIdx = -1;
// Primary instruction pass
BeDbgLoc* prevEmitDbgPos = NULL;
bool inHeadAlloca = true;
@ -1661,6 +1739,98 @@ void CeBuilder::Build()
int startCodePos = GetCodePos();
mCurDbgLoc = inst->mDbgLoc;
if ((prevEmitDbgPos != mCurDbgLoc) && (mCurDbgLoc != NULL))
{
auto _GetScope = [&](BeMDNode* mdNode, int inlinedAt)
{
BeDbgFile* dbgFile;
BeDbgFunction* dbgFunc = NULL;
String nameAdd;
while (auto dbgLexicalBlock = BeValueDynCast<BeDbgLexicalBlock>(mdNode))
mdNode = dbgLexicalBlock->mScope;
if (dbgFunc = BeValueDynCast<BeDbgFunction>(mdNode))
{
dbgFile = dbgFunc->mFile;
}
else if (auto dbgLoc = BeValueDynCast<BeDbgLoc>(mdNode))
dbgFile = dbgLoc->GetDbgFile();
else
dbgFile = BeValueDynCast<BeDbgFile>(mdNode);
int* valuePtr = NULL;
CeDbgInlineLookup lookupPair(dbgFile, inlinedAt);
if (mDbgScopeMap.TryAdd(lookupPair, NULL, &valuePtr))
{
int scopeIdx = (int)mCeFunction->mDbgScopes.size();
String filePath = dbgFile->mDirectory;
filePath.Append(DIR_SEP_CHAR);
filePath += dbgFile->mFileName;
CeDbgScope dbgScope;
dbgScope.mFilePath = filePath;
dbgScope.mInlinedAt = inlinedAt;
dbgScope.mMethodVal = -1;
if (dbgFunc != NULL)
{
if (dbgFunc->mValue == NULL)
{
if (!dbgFunc->mLinkageName.IsEmpty())
{
int methodRefIdx = atoi(dbgFunc->mLinkageName.c_str());
dbgScope.mMethodVal = methodRefIdx | CeDbgScope::MethodValFlag_MethodRef;
}
else
{
CeDbgMethodRef dbgMethodRef;
dbgMethodRef.mNameMod = dbgFunc->mName;
int* valuePtr = NULL;
if (mDbgMethodRefMap.TryAdd(dbgMethodRef, NULL, &valuePtr))
{
*valuePtr = mCeFunction->mDbgMethodRefTable.mSize;
mCeFunction->mDbgMethodRefTable.Add(dbgMethodRef);
}
dbgScope.mMethodVal = *valuePtr | CeDbgScope::MethodValFlag_MethodRef;
}
}
else if (dbgFunc->mValue != mBeFunction)
dbgScope.mMethodVal = GetCallTableIdx(dbgFunc->mValue, NULL);
}
mCeFunction->mDbgScopes.Add(dbgScope);
*valuePtr = scopeIdx;
return scopeIdx;
}
else
return *valuePtr;
};
std::function<int(BeDbgLoc*)> _GetInlinedScope = [&](BeDbgLoc* dbgLoc)
{
if (dbgLoc == NULL)
return -1;
int* valuePtr = NULL;
if (mDbgInlineMap.TryAdd(dbgLoc, NULL, &valuePtr))
{
CeDbgInlineEntry inlineEntry;
inlineEntry.mLine = dbgLoc->mLine;
inlineEntry.mColumn = dbgLoc->mColumn;
auto inlinedAt = _GetInlinedScope(dbgLoc->mDbgInlinedAt);
inlineEntry.mScope = _GetScope(dbgLoc->mDbgScope, inlinedAt);
*valuePtr = mCeFunction->mDbgInlineTable.mSize;
mCeFunction->mDbgInlineTable.Add(inlineEntry);
}
return *valuePtr;
};
int inlinedAt = _GetInlinedScope(mCurDbgLoc->mDbgInlinedAt);
scopeIdx = _GetScope(mCurDbgLoc->mDbgScope, inlinedAt);
}
int instType = inst->GetTypeId();
@ -1676,11 +1846,9 @@ void CeBuilder::Build()
}
switch (instType)
{
case BeEnsureInstructionAtInst::TypeId:
{
case BeNopInst::TypeId:
case BeLifetimeStartInst::TypeId:
case BeLifetimeEndInst::TypeId:
case BeLifetimeStartInst::TypeId:
case BeLifetimeExtendInst::TypeId:
case BeValueScopeStartInst::TypeId:
case BeValueScopeEndInst::TypeId:
@ -3007,21 +3175,55 @@ void CeBuilder::Build()
case BeDbgDeclareInst::TypeId:
{
auto castedInst = (BeDbgDeclareInst*)inst;
auto mcValue = GetOperand(castedInst->mValue, true);
auto mcValue = GetOperand(castedInst->mValue, true);
if (mCeFunction->mDbgInfo != NULL)
{
if (auto dbgTypeId = BeValueDynCast<BeDbgTypeId>(castedInst->mDbgVar->mType))
bool isConst = false;
auto beType = castedInst->mDbgVar->mType;
if (auto dbgConstType = BeValueDynCast<BeDbgConstType>(beType))
{
CeDbgVariable dbgVariable;
isConst = true;
beType = dbgConstType->mElement;
}
if (auto dbgTypeId = BeValueDynCast<BeDbgTypeId>(beType))
{
mDbgVariableMap[castedInst->mValue] = mCeFunction->mDbgInfo->mVariables.mSize;
CeDbgVariable dbgVariable;
dbgVariable.mName = castedInst->mDbgVar->mName;
dbgVariable.mValue = mcValue;
dbgVariable.mType = mCeMachine->mCeModule->mContext->mTypes[dbgTypeId->mTypeId];
dbgVariable.mScope = scopeIdx;
dbgVariable.mIsConst = isConst;
dbgVariable.mStartCodePos = mCeFunction->mCode.mSize;
dbgVariable.mEndCodePos = -1;
mCeFunction->mDbgInfo->mVariables.Add(dbgVariable);
}
}
}
break;
case BeLifetimeEndInst::TypeId:
{
auto castedInst = (BeLifetimeEndInst*)inst;
int varIdx = 0;
if (mDbgVariableMap.TryGetValue(castedInst->mPtr, &varIdx))
{
auto dbgVar = &mCeFunction->mDbgInfo->mVariables[varIdx];
dbgVar->mEndCodePos = mCeFunction->mCode.mSize;
}
}
break;
case BeEnsureInstructionAtInst::TypeId:
{
if (mCeMachine->mDebugger != NULL)
{
Emit(CeOp_Nop);
}
}
break;
default:
Fail("Unhandled instruction");
return;
@ -3031,32 +3233,11 @@ void CeBuilder::Build()
mValueToOperand[inst] = result;
if ((startCodePos != GetCodePos()) && (prevEmitDbgPos != mCurDbgLoc))
{
int scopeIdx = -1;
BeDbgFile* dbgFile = NULL;
if (mCurDbgLoc != NULL)
{
auto dbgFile = mCurDbgLoc->GetDbgFile();
int* valuePtr = NULL;
if (mDbgFileMap.TryAdd(dbgFile, NULL, &valuePtr))
{
scopeIdx = (int)mCeFunction->mDbgScopes.size();
String filePath = dbgFile->mDirectory;
filePath.Append(DIR_SEP_CHAR);
filePath += dbgFile->mFileName;
CeDbgScope dbgScope;
dbgScope.mFilePath = filePath;
mCeFunction->mDbgScopes.Add(dbgScope);
*valuePtr = scopeIdx;
}
else
scopeIdx = *valuePtr;
}
{
CeEmitEntry emitEntry;
emitEntry.mCodePos = startCodePos;
emitEntry.mScope = scopeIdx;
if (mCurDbgLoc != NULL)
if ((mCurDbgLoc != NULL) && (mCurDbgLoc->mLine != -1))
{
emitEntry.mLine = mCurDbgLoc->mLine;
emitEntry.mColumn = mCurDbgLoc->mColumn;
@ -3080,6 +3261,13 @@ void CeBuilder::Build()
}
}
if (mCeFunction->mDbgInfo != NULL)
{
for (auto& dbgVar : mCeFunction->mDbgInfo->mVariables)
if (dbgVar.mEndCodePos == -1)
dbgVar.mEndCodePos = mCeFunction->mCode.mSize;
}
for (auto& jumpEntry : mJumpTable)
{
auto& ceBlock = mBlocks[jumpEntry.mBlockIdx];
@ -3091,9 +3279,14 @@ void CeBuilder::Build()
Fail("No method definition available");
return;
}
if (mCeFunction->mGenError.IsEmpty())
mCeFunction->mFailed = false;
else
{
NOP;
}
mCeFunction->mFrameSize = mFrameSize;
}
@ -3135,7 +3328,11 @@ BfError* CeContext::Fail(const StringImpl& error)
auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0);
if (bfError == NULL)
return NULL;
mCeMachine->mCompiler->mPassInstance->MoreInfo(error, mCeMachine->mCompiler->GetAutoComplete() != NULL);
bool forceQueue = mCeMachine->mCompiler->GetAutoComplete() != NULL;
if ((mCeMachine->mDebugger != NULL) && (mCeMachine->mDebugger->mCurDbgState != NULL))
forceQueue = true;
mCeMachine->mCompiler->mPassInstance->MoreInfo(error, forceQueue);
return bfError;
}
@ -3158,7 +3355,7 @@ BfError* CeContext::Fail(const CeFrame& curFrame, const StringImpl& str)
auto ceFunction = ceFrame->mFunction;
CeEmitEntry* emitEntry = ceFunction->FindEmitEntry(ceFrame->mInstPtr - &ceFunction->mCode[0] - 1);
CeEmitEntry* emitEntry = ceFunction->FindEmitEntry(ceFrame->mInstPtr - ceFunction->mCode.mVals - 1);
StringT<256> err;
if (isHeadEntry)
{
@ -3175,38 +3372,97 @@ BfError* CeContext::Fail(const CeFrame& curFrame, const StringImpl& str)
contextTypeInstance = contextMethodInstance->GetOwner();
}
err += StrFormat("in comptime ");
//
auto _AddCeMethodInstance = [&](BfMethodInstance* methodInstance)
{
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, contextTypeInstance);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, contextMethodInstance);
if (ceFunction->mMethodInstance != NULL)
err += mCeMachine->mCeModule->MethodToString(ceFunction->mMethodInstance, BfMethodNameFlag_OmitParams);
else
{
err += mCeMachine->mCeModule->MethodToString(ceFunction->mCeInnerFunctionInfo->mOwner->mMethodInstance, BfMethodNameFlag_OmitParams);
}
}
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, contextMethodInstance);
err += mCeMachine->mCeModule->MethodToString(methodInstance, BfMethodNameFlag_OmitParams);
};
if ((emitEntry != NULL) && (emitEntry->mScope != -1))
auto _AddError = [&](const StringImpl& filePath, int line, int column)
{
err += StrFormat(" at line% d:%d in %s", emitEntry->mLine + 1, emitEntry->mColumn + 1, ceFunction->mDbgScopes[emitEntry->mScope].mFilePath.c_str());
err += StrFormat(" at line% d:%d in %s", line + 1, column + 1, filePath.c_str());
auto moreInfo = passInstance->MoreInfo(err, mCeMachine->mCeModule->mCompiler->GetAutoComplete() != NULL);
if ((moreInfo != NULL))
{
BfErrorLocation* location = new BfErrorLocation();
location->mFile = ceFunction->mDbgScopes[emitEntry->mScope].mFilePath;
location->mLine = emitEntry->mLine;
location->mColumn = emitEntry->mColumn;
location->mFile = filePath;
location->mLine = line;
location->mColumn = column;
moreInfo->mLocation = location;
}
};
if (emitEntry != NULL)
{
int scopeIdx = emitEntry->mScope;
int prevInlineIdx = -1;
while (scopeIdx != -1)
{
err += StrFormat("in comptime ");
int line = emitEntry->mLine;
int column = emitEntry->mColumn;
String fileName;
if (prevInlineIdx != -1)
{
auto dbgInlineInfo = &ceFunction->mDbgInlineTable[prevInlineIdx];
line = dbgInlineInfo->mLine;
column = dbgInlineInfo->mColumn;
}
CeDbgScope* ceScope = &ceFunction->mDbgScopes[scopeIdx];
if (ceScope->mMethodVal == -1)
{
if (ceFunction->mMethodInstance != NULL)
_AddCeMethodInstance(ceFunction->mMethodInstance);
else
_AddCeMethodInstance(ceFunction->mCeInnerFunctionInfo->mOwner->mMethodInstance);
}
else
{
if ((ceScope->mMethodVal & CeDbgScope::MethodValFlag_MethodRef) != 0)
{
auto dbgMethodRef = &ceFunction->mDbgMethodRefTable[ceScope->mMethodVal & CeDbgScope::MethodValFlag_IdxMask];
err += dbgMethodRef->ToString();
}
else
{
auto callTableEntry = &ceFunction->mCallTable[ceScope->mMethodVal];
_AddCeMethodInstance(callTableEntry->mFunctionInfo->mMethodInstance);
}
}
_AddError(ceFunction->mDbgScopes[emitEntry->mScope].mFilePath, line, column);
if (ceScope->mInlinedAt == -1)
break;
auto inlineInfo = &ceFrame->mFunction->mDbgInlineTable[ceScope->mInlinedAt];
scopeIdx = inlineInfo->mScope;
prevInlineIdx = ceScope->mInlinedAt;
err.Clear();
}
}
else
{
auto moreInfo = passInstance->MoreInfo(err, mCeMachine->mCeModule->mCompiler->GetAutoComplete() != NULL);
err += StrFormat("in comptime ");
if (ceFunction->mMethodInstance != NULL)
_AddCeMethodInstance(ceFunction->mMethodInstance);
else
_AddCeMethodInstance(ceFunction->mCeInnerFunctionInfo->mOwner->mMethodInstance);
if ((emitEntry != NULL) && (emitEntry->mScope != -1))
{
_AddError(ceFunction->mDbgScopes[emitEntry->mScope].mFilePath, emitEntry->mLine, emitEntry->mColumn);
}
else
{
auto moreInfo = passInstance->MoreInfo(err, mCeMachine->mCeModule->mCompiler->GetAutoComplete() != NULL);
}
}
}
@ -3694,6 +3950,8 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
switch (constant->mTypeCode)
{
case BfTypeCode_None:
return true;
case BfTypeCode_Int8:
case BfTypeCode_UInt8:
case BfTypeCode_Boolean:
@ -3966,12 +4224,21 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
if (constant->mConstType == BfConstType_PtrToInt)
{
auto ptrToIntConst = (BfConstantPtrToInt*)constant;
auto ptrToIntConst = (BfConstantPtrToInt*)constant;
auto constTarget = module->mBfIRBuilder->GetConstantById(ptrToIntConst->mTarget);
return WriteConstant(module, addr, constTarget, type);
}
if (constant->mConstType == BfConstType_IntToPtr)
{
auto ptrToIntConst = (BfConstantIntToPtr*)constant;
auto intType = mCeMachine->mCeModule->GetPrimitiveType(BfTypeCode_IntPtr);
auto constTarget = module->mBfIRBuilder->GetConstantById(ptrToIntConst->mTarget);
return WriteConstant(module, addr, constTarget, intType);
}
if (constant->mConstType == BfConstType_BitCastNull)
{
BF_ASSERT(type->IsPointer() || type->IsObjectOrInterface());
@ -4099,6 +4366,8 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
switch (typeCode)
{
case BfTypeCode_None:
return irBuilder->CreateConst(primType->mTypeDef->mTypeCode, 0);
case BfTypeCode_Int8:
CE_CREATECONST_CHECKPTR(ptr, sizeof(int8));
return irBuilder->CreateConst(primType->mTypeDef->mTypeCode, *(int8*)ptr);
@ -5091,6 +5360,8 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
ceFunction = CEFUNC; \
framePtr = stackPtr; \
stackPtr -= ceFunction->mFrameSize; \
if (isDebugging) \
memset(stackPtr, 0, ceFunction->mFrameSize); \
instPtr = &ceFunction->mCode[0]; \
CE_CHECKSTACK();
@ -5164,6 +5435,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
uint8* framePtr = startFramePtr;
bool needsFunctionIds = ceModule->mSystem->mPtrSize != 8;
int32 ptrSize = ceModule->mSystem->mPtrSize;
bool isDebugging = mCeMachine->mDebugger != NULL;
volatile bool* specialCheckPtr = &mCeMachine->mSpecialCheck;
volatile bool* fastFinishPtr = &mCeMachine->mCompiler->mFastFinish;
@ -5193,21 +5465,72 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
auto _DbgPause = [&]()
{
if (mCeMachine->mDebugger != NULL)
int itr = 0;
while (mCeMachine->mDebugger != NULL)
{
mCeMachine->mCritSect.Lock();
mCallStack.Add(_GetCurFrame());
mCeMachine->mDbgPaused = true;
mCeMachine->mCritSect.Unlock();
if (mCeMachine->mDbgPaused)
{
// This indicates a missed breakpoint, we should try to avoid this
// Re-entrancy can cause this, from populating a type during cedebugger autocomplete
OutputDebugStrF("CeMachine DbgPause reentry\n");
return;
}
CePendingExpr* prevPendingExpr = NULL;
///
{
AutoCrit autoCrit(mCeMachine->mCritSect);
if ((mCeMachine->mDebugger->mDebugPendingExpr != NULL) && (itr == 0))
{
// Abandon evaluating expression
prevPendingExpr = mCeMachine->mDebugger->mDebugPendingExpr;
mCeMachine->mDebugger->mDebugPendingExpr = NULL;
}
if (itr == 0)
mCallStack.Add(_GetCurFrame());
mCeMachine->mDbgPaused = true;
}
mCeMachine->mDebugEvent.WaitFor();
mCeMachine->mCritSect.Lock();
mCeMachine->mDbgPaused = false;
mCallStack.pop_back();
mCeMachine->mCritSect.Unlock();
CePendingExpr* pendingExpr = NULL;
_FixVariables();
///
{
AutoCrit autoCrit(mCeMachine->mCritSect);
mCeMachine->mDbgPaused = false;
if (mCeMachine->mStepState.mKind != CeStepState::Kind_Evaluate)
{
mCallStack.pop_back();
_FixVariables();
break;
}
mCeMachine->mStepState.mKind = CeStepState::Kind_None;
String result;
if (mCeMachine->mDebugger->mDebugPendingExpr != NULL)
pendingExpr = mCeMachine->mDebugger->mDebugPendingExpr;
}
if (pendingExpr == NULL)
continue;;
pendingExpr->mResult = mCeMachine->mDebugger->DoEvaluate(pendingExpr, true);
///
{
AutoCrit autoCrit(mCeMachine->mCritSect);
pendingExpr->mDone = true;
if (pendingExpr != mCeMachine->mDebugger->mDebugPendingExpr)
delete pendingExpr;
}
itr++;
}
};
@ -5280,7 +5603,11 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
}
else if (checkFunction->mFunctionKind == CeFunctionKind_FatalError)
{
int32 strInstAddr = *(int32*)((uint8*)stackPtr + 0);
int32 strInstAddr = *(int32*)((uint8*)stackPtr + 0);
int32 stackOffset = *(int32*)(stackPtr + ceModule->mSystem->mPtrSize);
if (mCeMachine->mDebugger != NULL)
mCeMachine->mDebugger->mPendingActiveFrameOffset = stackOffset;
String error = "Fatal Error: ";
GetStringFromAddr(strInstAddr, error);
@ -6590,7 +6917,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
if (!checkFunction->mFailed)
return true;
if (mCeMachine->mDebugger != NULL)
if ((mCeMachine->mDebugger != NULL) && (!mCallStack.IsEmpty()))
_Fail(StrFormat("Attempting to call failed method '%s'", ceModule->MethodToString(checkFunction->mMethodInstance).c_str()));
auto error = Fail(_GetCurFrame(), StrFormat("Method call preparation '%s' failed", ceModule->MethodToString(checkFunction->mMethodInstance).c_str()));
@ -6714,9 +7041,12 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
OpSwitch:
switch (op)
{
case CeOp_Nop:
break;
case CeOp_DbgBreak:
{
bool foundBreakpoint = false;
bool skipInst = false;
if (mCeMachine->mDebugger != NULL)
{
@ -6725,14 +7055,36 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
CeBreakpointBind* breakpointEntry = NULL;
if (ceFunction->mBreakpoints.TryGetValue(instIdx, &breakpointEntry))
{
bool doBreak = false;
mCallStack.Add(_GetCurFrame());
if (mCeMachine->mDebugger->CheckConditionalBreakpoint(breakpointEntry->mBreakpoint))
doBreak = true;
mCallStack.pop_back();
op = breakpointEntry->mPrevOpCode;
// Keep us from an infinite loop if we set a breakpoint on a manual Break
skipInst = op == CeOp_DbgBreak;
foundBreakpoint = true;
if (!doBreak)
{
_FixVariables();
if (skipInst)
break;
goto OpSwitch;
}
mCeMachine->mDebugger->mActiveBreakpoint = breakpointEntry->mBreakpoint;
}
}
_DbgPause();
if (mCeMachine->mStepState.mKind == CeStepState::Kind_Jmp)
goto SpecialCheck;
if (skipInst)
break;
if (foundBreakpoint)
goto OpSwitch;
}
@ -8182,7 +8534,8 @@ void CeMachine::Init()
mCeModule->mBfIRBuilder = new BfIRBuilder(mCeModule);
mCeModule->mBfIRBuilder->mDbgVerifyCodeGen = true;
mCeModule->FinishInit();
mCeModule->mBfIRBuilder->mHasDebugInfo = mDebugger != NULL; // We will still have line info even if this is false
mCeModule->mBfIRBuilder->mHasDebugInfo = true;
mCeModule->mHasFullDebugInfo = mDebugger != NULL;
mCeModule->mBfIRBuilder->mIgnoreWrites = false;
mCeModule->mWantsIRIgnoreWrites = false;
}

View file

@ -4,6 +4,7 @@
#include "BfModule.h"
#include "BeefySysLib/util/Heap.h"
#include "BeefySysLib/util/AllocDebug.h"
#include "BfMangler.h"
NS_BF_BEGIN
@ -71,6 +72,7 @@ enum CeErrorKind
enum CeOp : int16
{
CeOp_InvalidOp,
CeOp_Nop,
CeOp_DbgBreak,
CeOp_Ret,
CeOp_SetRetType,
@ -260,6 +262,49 @@ struct CeEmitEntry
int mColumn;
};
struct CeDbgMethodRef
{
BfMethodRef mMethodRef;
String mNameMod;
String ToString();
bool operator==(const CeDbgMethodRef& second) const
{
return (mMethodRef == second.mMethodRef) && (mNameMod == second.mNameMod);
}
};
struct CeDbgScope
{
public:
enum MethodValFlag
{
MethodValFlag_MethodRef = 0x40000000,
MethodValFlag_IdxMask = 0x3FFFFFFF
};
public:
String mFilePath;
BfMethodRef mMethodRef;
int mInlinedAt;
int mMethodVal; // call table idx or methodRef idx, depending on MethodValFlag_MethodRef
public:
CeDbgScope()
{
mInlinedAt = -1;
mMethodVal = -1;
}
};
struct CeDbgInlineEntry
{
int mScope;
int mLine;
int mColumn;
};
class CeFunctionInfo
{
public:
@ -540,10 +585,14 @@ public:
class CeDbgVariable
{
public:
public:
String mName;
CeOperand mValue;
BfType* mType;
int mScope;
bool mIsConst;
int mStartCodePos;
int mEndCodePos;
};
class CeDbgFunctionInfo
@ -559,19 +608,6 @@ public:
CeBreakpoint* mBreakpoint;
};
struct CeDbgScope
{
public:
String mFilePath;
int mInlinedAt;
public:
CeDbgScope()
{
mInlinedAt = -1;
}
};
class CeFunction
{
public:
@ -594,8 +630,10 @@ public:
bool mIsVarReturn;
Array<uint8> mCode;
Array<CeDbgScope> mDbgScopes;
Array<CeEmitEntry> mEmitTable;
Array<CeCallEntry> mCallTable;
Array<CeDbgInlineEntry> mDbgInlineTable;
Array<CeDbgMethodRef> mDbgMethodRefTable;
Array<CeEmitEntry> mEmitTable;
Array<CeCallEntry> mCallTable;
Array<CeStringEntry> mStringTable;
Array<CeConstStructData> mConstStructTable;
Array<CeStaticFieldEntry> mStaticFieldTable;
@ -631,6 +669,7 @@ public:
void Print();
void UnbindBreakpoints();
CeEmitEntry* FindEmitEntry(int loc, int* entryIdx = NULL);
int SafeGetId();
};
enum CeEvalFlags
@ -738,6 +777,29 @@ public:
int mBlockIdx;
};
struct CeDbgInlineLookup
{
BeDbgFile* mDbgFile;
int mInlineAtIdx;
CeDbgInlineLookup(BeDbgFile* dbgFile, int inlineAtIdx)
{
mDbgFile = dbgFile;
mInlineAtIdx = inlineAtIdx;
}
CeDbgInlineLookup()
{
mDbgFile = NULL;
mInlineAtIdx = -1;
}
bool operator==(const CeDbgInlineLookup& second) const
{
return (mDbgFile == second.mDbgFile) && (mDbgFile == second.mDbgFile);
}
};
class CeBuilder
{
public:
@ -755,14 +817,17 @@ public:
Array<CeJumpEntry> mJumpTable;
Dictionary<BeValue*, CeOperand> mValueToOperand;
int mFrameSize;
Dictionary<BeDbgFile*, int> mDbgFileMap;
Dictionary<BeDbgLoc*, int> mDbgInlineMap;
Dictionary<CeDbgInlineLookup, int> mDbgScopeMap;
Dictionary<CeDbgMethodRef, int> mDbgMethodRefMap;
Dictionary<BeFunction*, int> mFunctionMap;
Dictionary<int, int> mStringMap;
Dictionary<BeConstant*, int> mConstDataMap;
Dictionary<BeFunction*, int> mInnerFunctionMap;
Dictionary<BeGlobalVariable*, int> mStaticFieldMap;
Dictionary<String, BfFieldInstance*> mStaticFieldInstanceMap;
Dictionary<String, BfFieldInstance*> mStaticFieldInstanceMap;
Dictionary<BeValue*, int> mDbgVariableMap;
public:
CeBuilder()
{
@ -782,6 +847,9 @@ public:
CeErrorKind EmitConst(Array<uint8>& arr, BeConstant* constant);
CeOperand GetOperand(BeValue* value, bool allowAlloca = false, bool allowImmediate = false);
CeSizeClass GetSizeClass(int size);
int DbgCreateMethodRef(BfMethodInstance* methodInstance, const StringImpl& nameMod);
int GetCallTableIdx(BeFunction* beFunction, CeOperand* outOperand);
int GetCodePos();
void HandleParams();
@ -1011,7 +1079,8 @@ public:
Kind_StepInfo_Asm,
Kind_StepOut,
Kind_StepOut_Asm,
Kind_Jmp
Kind_Jmp,
Kind_Evaluate
};
Kind mKind;
@ -1035,8 +1104,7 @@ public:
Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit and debugging
Dictionary<BfType*, CeTypeInfo> mTypeInfoMap;
HashSet<BfMethodInstance*> mMethodInstanceSet;
HashSet<BfFieldInstance*> mFieldInstanceSet;
Array<BeFunction*> mFunctionList;
HashSet<BfFieldInstance*> mFieldInstanceSet;
Array<CeContext*> mContextList;
@ -1090,7 +1158,7 @@ public:
CeFunction* GetPreparedFunction(BfMethodInstance* methodInstance);
CeTypeInfo* GetTypeInfo(BfType* type);
BfMethodInstance* GetMethodInstance(int64 methodHandle);
BfFieldInstance* GetFieldInstance(int64 fieldHandle);
BfFieldInstance* GetFieldInstance(int64 fieldHandle);
public:
void CompileStarted();
@ -1119,4 +1187,22 @@ namespace std
return BeefHash<Beefy::String>()(key.mString) ^ (size_t)key.mKind;
}
};
template <>
struct hash<Beefy::CeDbgInlineLookup>
{
size_t operator()(const Beefy::CeDbgInlineLookup& key) const
{
return (intptr)key.mDbgFile ^ (intptr)key.mInlineAtIdx;
}
};
template <>
struct hash<Beefy::CeDbgMethodRef>
{
size_t operator()(const Beefy::CeDbgMethodRef& key) const
{
return BeefHash<Beefy::BfMethodRef>()(key.mMethodRef) ^ BeefHash<Beefy::String>()(key.mNameMod);
}
};
}

View file

@ -7403,7 +7403,14 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
}
else if ((arg.mType->mTypeCode == DbgType_i32) || (arg.mType->mTypeCode == DbgType_i64))
{
typeName += BfTypeUtils::HashEncode64(arg.mInt64);
if (typeName.IsEmpty())
{
// Fake this int as a type pointer
arg.mSrcAddress = arg.mUInt64;
BeefTypeToString(arg, typeName);
}
else
typeName += BfTypeUtils::HashEncode64(arg.mInt64);
}
else
{

View file

@ -667,7 +667,7 @@ BF_EXPORT void BF_CALLTYPE Debugger_Create()
::AllowSetForegroundWindow(ASFW_ANY);
#endif
//BeefyDbg64::TestPDB("c:\\temp\\dedkeni.pdb", (BeefyDbg64::WinDebugger*)gDebugManager->mDebugger64);
//BeefyDbg64::TestPDB("C:/Beef/IDE/dist/IDEHelper64_d.pdb", (BeefyDbg64::WinDebugger*)gDebugManager->mDebugger64);
}
BF_EXPORT void BF_CALLTYPE Debugger_SetCallbacks(void* callback)

View file

@ -515,7 +515,7 @@ public:
int SetProtection(intptr address, int size, int prot);
void EnableMemCache();
void DisableMemCache();
template<typename T> T ReadMemory(intptr addr, bool local = false, bool* failed = NULL);
template<typename T> T ReadMemory(intptr addr, bool local = false, bool* failed = NULL);
bool WriteInstructions(intptr address, void* src, uint64 length);
template<typename T> bool WriteMemory(intptr addr, T val);
virtual DbgMemoryFlags GetMemoryFlags(intptr address) override;