diff --git a/BeefLibs/corlib/src/Reflection/AttributeInfo.bf b/BeefLibs/corlib/src/Reflection/AttributeInfo.bf index a7f34f4f..c0fb5d9d 100644 --- a/BeefLibs/corlib/src/Reflection/AttributeInfo.bf +++ b/BeefLibs/corlib/src/Reflection/AttributeInfo.bf @@ -93,7 +93,7 @@ namespace System.Reflection .Double: let attrData = Decode!(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!(data); args[argIdx] = Type.[Friend]GetType((.)argTypeId); case (TypeCode)255: diff --git a/BeefLibs/corlib/src/Runtime.bf b/BeefLibs/corlib/src/Runtime.bf index 200f521a..b2861236 100644 --- a/BeefLibs/corlib/src/Runtime.bf +++ b/BeefLibs/corlib/src/Runtime.bf @@ -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 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) diff --git a/BeefySysLib/BeefySysLib_static.vcxproj b/BeefySysLib/BeefySysLib_static.vcxproj index b7398576..3cd1d3e7 100644 --- a/BeefySysLib/BeefySysLib_static.vcxproj +++ b/BeefySysLib/BeefySysLib_static.vcxproj @@ -864,6 +864,7 @@ + @@ -1025,6 +1026,7 @@ + diff --git a/BeefySysLib/BeefySysLib_static.vcxproj.filters b/BeefySysLib/BeefySysLib_static.vcxproj.filters index 486d3602..481a1346 100644 --- a/BeefySysLib/BeefySysLib_static.vcxproj.filters +++ b/BeefySysLib/BeefySysLib_static.vcxproj.filters @@ -572,6 +572,9 @@ src\util + + src\util + @@ -877,6 +880,9 @@ src\util + + src\util + diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 5d3c8c12..58e0c8e0 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -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(); }); diff --git a/IDE/src/ui/HoverWatch.bf b/IDE/src/ui/HoverWatch.bf index ca963871..1b80367a 100644 --- a/IDE/src/ui/HoverWatch.bf +++ b/IDE/src/ui/HoverWatch.bf @@ -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) { diff --git a/IDE/src/ui/StatusBar.bf b/IDE/src/ui/StatusBar.bf index 24a19284..f907e269 100644 --- a/IDE/src/ui/StatusBar.bf +++ b/IDE/src/ui/StatusBar.bf @@ -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)); diff --git a/IDEHelper/Backend/BeCOFFObject.cpp b/IDEHelper/Backend/BeCOFFObject.cpp index 7b8da43d..3a4cbaca 100644 --- a/IDEHelper/Backend/BeCOFFObject.cpp +++ b/IDEHelper/Backend/BeCOFFObject.cpp @@ -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); diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index 94faf3a3..99289e85 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -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: diff --git a/IDEHelper/COFF.cpp b/IDEHelper/COFF.cpp index 50c76008..81f167ae 100644 --- a/IDEHelper/COFF.cpp +++ b/IDEHelper/COFF.cpp @@ -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(); diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 35cc1d93..b0a3deab 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -752,7 +752,7 @@ public: bool IsNoValueType() const { - return (mKind == BfTypedValueKind_NoValue); + return (mKind == BfTypedValueKind_NoValue) && (mType != NULL); } bool IsParams() diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 5d971e9e..9964b222 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -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; diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 2ba99577..52eff695 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -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", ""); } diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index 5ddcb5e5..b694f5b0 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -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& rebuildTypeInstList); void CompileReified(); void PopulateReified(); + bool IsCePaused(); + bool EnsureCeUnpaused(BfType* refType); void HotCommit(); void HotResolve_Start(HotResolveFlags flags); diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index ab9d2001..e3bbe6e4 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -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); } } } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 36d1f69b..ce423727 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -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 prevDebugger(mModule->mCompiler->mCEMachine->mDebugger, NULL); + //SetAndRestoreValue 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((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 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 args; args.push_back(mModule->GetConstValue(0)); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 5b973999..7d9887de 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -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 vals = { basePtr }; result = mBfIRBuilder->CreateCall(dtorFunc.mFunc, vals); @@ -16762,7 +16813,7 @@ void BfModule::EmitDtorBody() SizedArray 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 diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index f7167bf3..bea38ef4 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -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); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 6892aa30..ff60eab8 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2220,8 +2220,8 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* if (methodInstance == NULL) continue; - SetAndRestoreValue prevEmitContext(mCompiler->mCEMachine->mCurEmitContext, ceEmitContext); - auto ceContext = mCompiler->mCEMachine->AllocContext(); + SetAndRestoreValue 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 prevEmitContext(mCompiler->mCEMachine->mCurEmitContext); + SetAndRestoreValue 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 prevEmitContext(mCompiler->mCEMachine->mCurEmitContext, &ceEmitContext); - auto ceContext = mCompiler->mCEMachine->AllocContext(); + SetAndRestoreValue 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); } diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index f86ea0e3..cbc26c78 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -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) diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 7a0e49b2..395bebfb 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -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); diff --git a/IDEHelper/Compiler/CeDebugger.cpp b/IDEHelper/Compiler/CeDebugger.cpp index 3e63ef12..a6b6493f 100644 --- a/IDEHelper/Compiler/CeDebugger.cpp +++ b/IDEHelper/Compiler/CeDebugger.cpp @@ -10,6 +10,8 @@ #include "BfExprEvaluator.h" #include "BeefySysLib/util/BitSet.h" #include "../DebugVisualizers.h" +#include "BfAutoComplete.h" +#include "BfDemangler.h" USING_NS_BF; @@ -22,21 +24,38 @@ static addr_ce DecodeTargetDataPtr(const char*& strRef) ////////////////////////////////////////////////////////////////////////// +CeBreakpointCondition::~CeBreakpointCondition() +{ + delete mDbgEvaluationContext; +} + +////////////////////////////////////////////////////////////////////////// + +CeBreakpoint::~CeBreakpoint() +{ + delete mCondition; +} + +////////////////////////////////////////////////////////////////////////// + CePendingExpr::CePendingExpr() { mThreadId = -1; mCallStackIdx = -1; + mPassInstance = NULL; mParser = NULL; mCursorPos = -1; mExprNode = NULL; mIdleTicks = 0; mExplitType = NULL; mExpressionFlags = DwEvalExpressionFlag_None; + mDone = false; } CePendingExpr::~CePendingExpr() { delete mParser; + delete mPassInstance; } ////////////////////////////////////////////////////////////////////////// @@ -166,7 +185,7 @@ CeEvaluationContext::~CeEvaluationContext() delete mPassInstance; } -BfTypedValue CeEvaluationContext::EvaluateInContext(BfTypedValue contextTypedValue) +BfTypedValue CeEvaluationContext::EvaluateInContext(BfTypedValue contextTypedValue, CeDbgState* dbgState) { if (mResultOverride) return mResultOverride; @@ -188,14 +207,17 @@ BfTypedValue CeEvaluationContext::EvaluateInContext(BfTypedValue contextTypedVal SetAndRestoreValue prevMethodState(module->mCurMethodState, &methodState); methodState.mTempKind = module->mCurMethodInstance->mMethodDef->mIsStatic ? BfMethodState::TempKind_Static : BfMethodState::TempKind_NonStatic; - CeDbgState dbgState; - dbgState.mActiveFrame = ceFrame; - dbgState.mCeContext = mDebugger->mCeMachine->mCurContext; + CeDbgState localDbgState; + if (dbgState == NULL) + dbgState = &localDbgState; + + dbgState->mActiveFrame = ceFrame; + dbgState->mCeContext = mDebugger->mCeMachine->mCurContext; if (contextTypedValue) - dbgState.mExplicitThis = contextTypedValue; + dbgState->mExplicitThis = contextTypedValue; else - dbgState.mExplicitThis = mExplicitThis; - SetAndRestoreValue prevDbgState(mDebugger->mCurDbgState, &dbgState); + dbgState->mExplicitThis = mExplicitThis; + SetAndRestoreValue prevDbgState(mDebugger->mCurDbgState, dbgState); BfTypedValue exprResult; mExprEvaluator->VisitChildNoRef(mExprNode); @@ -231,7 +253,7 @@ CeDebugger::CeDebugger(DebugManager* debugManager, BfCompiler* bfCompiler) { mDebugManager = debugManager; mCompiler = bfCompiler; - mCeMachine = bfCompiler->mCEMachine; + mCeMachine = bfCompiler->mCeMachine; mRunState = RunState_Running; mCeMachine->mDebugger = this; mCeMachine->mDebugEvent.Reset(); @@ -243,6 +265,29 @@ CeDebugger::CeDebugger(DebugManager* debugManager, BfCompiler* bfCompiler) mCurDisasmFuncId = 0; mActiveBreakpoint = NULL; mCurEvaluationContext = NULL; + mPendingActiveFrameOffset = 0; +} + +String CeDebugger::TypeToString(const BfTypedValue& typedValue) +{ + if (typedValue.mType == NULL) + return "null"; + if (typedValue.IsReadOnly()) + return String("readonly ") + mCeMachine->mCeModule->TypeToString(typedValue.mType); + return mCeMachine->mCeModule->TypeToString(typedValue.mType); +} + +String CeDebugger::TypeToString(BfType* type, CeTypeModKind typeModKind) +{ + if (type == NULL) + return "null"; + String str; + if (typeModKind == CeTypeModKind_ReadOnly) + str += "readonly "; + else if (typeModKind == CeTypeModKind_Const) + str += "const "; + str += mCeMachine->mCeModule->TypeToString(type); + return str; } CeDebugger::~CeDebugger() @@ -317,18 +362,22 @@ String CeDebugger::GetDbgAllocInfo() void CeDebugger::Update() { + AutoCrit autoCrit(mCeMachine->mCritSect); + if ((mRunState == RunState_Terminated) || (mRunState == RunState_Terminating)) return; - - AutoCrit autoCrit(mCeMachine->mCritSect); - if (mCeMachine->mDbgPaused) + + if (mDebugPendingExpr != NULL) { - mRunState = RunState_Paused; - } - else - { - mRunState = RunState_Running; + if (mDebugPendingExpr->mDone) + mRunState = RunState_DebugEval_Done; + else + mRunState = RunState_DebugEval; } + else if (mCeMachine->mDbgPaused) + mRunState = RunState_Paused; + else + mRunState = RunState_Running; } void CeDebugger::UpdateBreakpointFrames() @@ -344,8 +393,12 @@ void CeDebugger::UpdateBreakpointFrames() void CeDebugger::ContinueDebugEvent() { + AutoCrit autoCrit(mCeMachine->mCritSect); + mRunState = RunState_Running; mActiveBreakpoint = NULL; + mPendingActiveFrameOffset = 0; + mDbgCallStack.Clear(); if (mBreakpointFramesDirty) UpdateBreakpointFrames(); @@ -357,6 +410,120 @@ void CeDebugger::ForegroundTarget() { } +bool CeDebugger::CheckConditionalBreakpoint(CeBreakpoint* breakpoint) +{ + auto _SplitExpr = [&](const StringImpl& expr, StringImpl& outExpr, StringImpl& outSubject) + { + int crPos = (int)expr.IndexOf('\n'); + if (crPos != -1) + { + outExpr += expr.Substring(0, crPos); + outSubject += expr.Substring(crPos + 1); + } + else + { + outExpr += expr; + } + }; + + if (breakpoint->mCondition != NULL) + { + ClearCallStack(); + + auto conditional = breakpoint->mCondition; + if (conditional->mDbgEvaluationContext == NULL) + { + StringT<256> expr; + StringT<256> subjectExpr; + _SplitExpr(conditional->mExpr, expr, subjectExpr); + + conditional->mDbgEvaluationContext = new CeEvaluationContext(this, expr); + conditional->mDbgEvaluationContext->mCallStackIdx = -1; + } + + CeDbgState dbgState; + BfTypedValue result = conditional->mDbgEvaluationContext->EvaluateInContext(BfTypedValue(), &dbgState); + + if (conditional->mDbgEvaluationContext->mPassInstance->HasFailed()) + { + String errorStr = "FAILED"; + for (auto error : conditional->mDbgEvaluationContext->mPassInstance->mErrors) + { + if (!error->mIsWarning) + errorStr = error->mError; + + } + String condError = StrFormat("error Conditional breakpoint expression '%s' failed: %s", conditional->mExpr.c_str(), errorStr.c_str()); + mDebugManager->mOutMessages.push_back(condError); + return true; + } + else if (dbgState.mBlockedSideEffects) + { + mDebugManager->mOutMessages.push_back(StrFormat("error Conditional breakpoint expression '%s' contained function calls, which is not allowed", conditional->mExpr.c_str())); + return true; + } + else if ((!result) || (!result.mType->IsBoolean())) + { + mDebugManager->mOutMessages.push_back(StrFormat("error Conditional breakpoint expression '%s' must result in a boolean value", conditional->mExpr.c_str())); + return true; + } + else if (ValueToInt(result) <= 0) + return false; + } + + breakpoint->mHitCount++; + switch (breakpoint->mHitCountBreakKind) + { + case DbgHitCountBreakKind_Equals: + if (breakpoint->mHitCount != breakpoint->mTargetHitCount) + return false; + break; + case DbgHitCountBreakKind_GreaterEquals: + if (breakpoint->mHitCount < breakpoint->mTargetHitCount) + return false; + break; + case DbgHitCountBreakKind_Multiple: + if ((breakpoint->mHitCount % breakpoint->mTargetHitCount) != 0) + return false; + break; + } + + if (!breakpoint->mLogging.IsEmpty()) + { + auto ceContext = mCeMachine->mCurContext; + + CeDbgState dbgState; + dbgState.mActiveFrame = &ceContext->mCallStack[0]; + dbgState.mCeContext = mCeMachine->mCurContext; + SetAndRestoreValue prevDbgState(mCurDbgState, &dbgState); + + ClearCallStack(); + + CeFormatInfo formatInfo; + formatInfo.mCallStackIdx = -1; + + auto prevRunState = mRunState; + mRunState = RunState_Paused; // We need to be paused to avoid certain errors in the eval + String displayString; + + String expr; + _SplitExpr(breakpoint->mLogging, expr, formatInfo.mSubjectExpr); + + ProcessEvalString(BfTypedValue(), expr, displayString, formatInfo, NULL, false); + mRunState = prevRunState; + + displayString.Insert(0, "log "); + displayString.Append("\n"); + + mDebugManager->mOutMessages.push_back(displayString); + + if (!breakpoint->mBreakAfterLogging) + return false; + } + + return true; +} + Breakpoint* CeDebugger::CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset) { ClearBreakpointCache(); @@ -405,11 +572,40 @@ void CeDebugger::CheckBreakpoint(Breakpoint* breakpoint) void CeDebugger::HotBindBreakpoint(Breakpoint* breakpoint, int lineNum, int hotIdx) { + +} + +int64 CeDebugger::ValueToInt(addr_ce addr, BfType* type) +{ + if ((!type->IsInteger()) && (!type->IsBoolean())) + return 0; + + auto primType = (BfPrimitiveType*)type; + auto ceContext = mCeMachine->mCurContext; + + int64 val = 0; + memcpy(&val, ceContext->mMemory.mVals + addr, type->mSize); + + switch (primType->mTypeDef->mTypeCode) + { + case BfTypeCode_Int8: + val = *(int8*)&val; + break; + case BfTypeCode_Int16: + val = *(int16*)&val; + break; + case BfTypeCode_Int32: + val = *(int32*)&val; + break; + } + return val; } int64 CeDebugger::ValueToInt(const BfTypedValue& typedVal) { - auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(typedVal.mValue); + auto ceModule = mCeMachine->mCeModule; + + auto constant = ceModule->mBfIRBuilder->GetConstant(typedVal.mValue); if (constant == NULL) return 0; @@ -420,35 +616,36 @@ int64 CeDebugger::ValueToInt(const BfTypedValue& typedVal) type = type->GetUnderlyingType(); if ((type->IsInteger()) || (type->IsBoolean())) - { - auto primType = (BfPrimitiveType*)type; - + { auto ceTypedVal = GetAddr(constant); if (ceTypedVal) - { - auto ceContext = mCeMachine->mCurContext; - - int64 val = 0; - memcpy(&val, ceContext->mMemory.mVals + ceTypedVal.mAddr, type->mSize); - - switch (primType->mTypeDef->mTypeCode) - { - case BfTypeCode_Int8: - val = *(int8*)&val; - break; - case BfTypeCode_Int16: - val = *(int8*)&val; - break; - case BfTypeCode_Int32: - val = *(int8*)&val; - break; - } - return val; - } + return ValueToInt((addr_ce)ceTypedVal.mAddr, type); } return 0; - } + } + + if (constant->mConstType == BfConstType_ExtractValue) + { + auto fromConstGEP = (BfConstantExtractValue*)constant; + auto fromTarget = ceModule->mBfIRBuilder->GetConstantById(fromConstGEP->mTarget); + if (fromTarget->mConstType == BfConstType_AggCE) + { + auto aggCE = (BfConstantAggCE*)fromTarget; + + auto dbgTypeInfo = GetDbgTypeInfo(aggCE->mType); + if (dbgTypeInfo == NULL) + return 0; + + auto typeInst = dbgTypeInfo->mType->ToTypeInstance(); + if (typeInst == NULL) + return 0; + + auto fieldInfo = &dbgTypeInfo->mFieldOffsets[fromConstGEP->mIdx0]; + return ValueToInt(aggCE->mCEAddr + fieldInfo->mDataOffset, fieldInfo->mType); + } + } + if ((BfIRConstHolder::IsInt(constant->mTypeCode)) || (constant->mTypeCode == BfTypeCode_Boolean)) return constant->mInt64; return 0; @@ -482,12 +679,36 @@ void CeDebugger::DisableBreakpoint(Breakpoint* breakpoint) { } -void CeDebugger::SetBreakpointCondition(Breakpoint* breakpoint, const StringImpl& condition) +void CeDebugger::SetBreakpointCondition(Breakpoint* breakpoint, const StringImpl& conditionExpr) { + AutoCrit autoCrit(mDebugManager->mCritSect); + + CeBreakpoint* wdBreakpoint = (CeBreakpoint*)breakpoint; + BF_ASSERT(!wdBreakpoint->mIsLinkedSibling); + + if (conditionExpr.empty()) + { + delete wdBreakpoint->mCondition; + CeBreakpoint* curBreakpoint = wdBreakpoint; + wdBreakpoint->mCondition = NULL; + } + else + { + delete wdBreakpoint->mCondition; + auto condition = new CeBreakpointCondition(); + condition->mExpr = conditionExpr; + wdBreakpoint->mCondition = condition; + } } void CeDebugger::SetBreakpointLogging(Breakpoint* breakpoint, const StringImpl& logging, bool breakAfterLogging) { + AutoCrit autoCrit(mDebugManager->mCritSect); + + CeBreakpoint* wdBreakpoint = (CeBreakpoint*)breakpoint; + BF_ASSERT(!wdBreakpoint->mIsLinkedSibling); + wdBreakpoint->mLogging = logging; + wdBreakpoint->mBreakAfterLogging = breakAfterLogging; } Breakpoint* CeDebugger::FindBreakpointAt(intptr address) @@ -615,20 +836,61 @@ void CeDebugger::SetNextStatement(bool inAssembly, const StringImpl& fileName, i } CeFrame* CeDebugger::GetFrame(int callStackIdx) -{ +{ auto ceContext = mCeMachine->mCurContext; if (ceContext == NULL) return NULL; - if (callStackIdx < ceContext->mCallStack.mSize) + + if ((callStackIdx == -1) && (!ceContext->mCallStack.IsEmpty())) + return &ceContext->mCallStack.back(); + + if (callStackIdx < mDbgCallStack.mSize) { - int stackIdx = ceContext->mCallStack.mSize - callStackIdx - 1; - auto ceFrame = &ceContext->mCallStack[stackIdx]; + auto ceFrame = &ceContext->mCallStack[mDbgCallStack[callStackIdx].mFrameIdx]; return ceFrame; } return NULL; } -String CeDebugger::EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& bfPassInstance) +String CeDebugger::GetAutocompleteOutput(BfAutoComplete& autoComplete) +{ + String val = "\n:autocomplete\n"; + + if (autoComplete.mInsertStartIdx != -1) + { + val += StrFormat("insertRange\t%d %d\n", autoComplete.mInsertStartIdx, autoComplete.mInsertEndIdx); + } + + Array entries; + + for (auto& entry : autoComplete.mEntriesSet) + { + entries.Add(&entry); + } + std::sort(entries.begin(), entries.end(), [](AutoCompleteEntry* lhs, AutoCompleteEntry* rhs) + { + return stricmp(lhs->mDisplay, rhs->mDisplay) < 0; + }); + + for (auto entry : entries) + { + val += String(entry->mEntryType); + val += "\t"; + val += String(entry->mDisplay); + val += "\n"; + } + + /*if (autoComplete.mEntries.size() != 0) + { + for (auto& entry : autoComplete.mEntries) + { + val += String(entry.mEntryType) + "\t" + String(entry.mDisplay) + "\n"; + } + }*/ + return val; +} + +String CeDebugger::DoEvaluate(CePendingExpr* pendingExpr, bool inCompilerThread) { auto ceFrame = GetFrame(pendingExpr->mCallStackIdx); if (ceFrame == NULL) @@ -643,9 +905,14 @@ String CeDebugger::EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& auto module = mCeMachine->mCeModule; + if (!mCeMachine->mDbgPaused) + pendingExpr->mPassInstance->ClearErrors(); + + SetAndRestoreValue prevTypeState(module->mContext->mCurTypeState, NULL); + SetAndRestoreValue prevConstraintState(module->mContext->mCurConstraintState, NULL); SetAndRestoreValue prevTypeInstance(module->mCurTypeInstance, ceFrame->mFunction->mMethodInstance->GetOwner()); SetAndRestoreValue prevMethodInstance(module->mCurMethodInstance, ceFrame->mFunction->mMethodInstance); - SetAndRestoreValue prevPassInstance(mCompiler->mPassInstance, &bfPassInstance); + SetAndRestoreValue prevPassInstance(mCompiler->mPassInstance, pendingExpr->mPassInstance); SetAndRestoreValue prevIgnoreWrites(module->mBfIRBuilder->mIgnoreWrites, true); BfMethodState methodState; @@ -657,9 +924,31 @@ String CeDebugger::EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& dbgState.mCeContext = mCeMachine->mCurContext; dbgState.mExplicitThis = pendingExpr->mFormatInfo.mExplicitThis; dbgState.mDbgExpressionFlags = pendingExpr->mExpressionFlags; + if (!inCompilerThread) + dbgState.mDbgExpressionFlags = (DwEvalExpressionFlags)(dbgState.mDbgExpressionFlags & ~(DwEvalExpressionFlag_AllowCalls | DwEvalExpressionFlag_AllowPropertyEval)); + dbgState.mFormatInfo = &pendingExpr->mFormatInfo; SetAndRestoreValue prevDbgState(mCurDbgState, &dbgState); + BfAutoComplete autoComplete; + autoComplete.mModule = module; + autoComplete.mCompiler = module->mCompiler; + autoComplete.mSystem = module->mSystem; + + BfResolvePassData resolvePass; + resolvePass.mParser = pendingExpr->mParser; + resolvePass.mAutoComplete = &autoComplete; + + SetAndRestoreValue prevResolvePass; + if (pendingExpr->mCursorPos != -1) + { + pendingExpr->mParser->mParserFlags = (BfParserFlag)(pendingExpr->mParser->mParserFlags | ParserFlag_Autocomplete); + pendingExpr->mParser->mCursorIdx = pendingExpr->mCursorPos + 1; + pendingExpr->mParser->mCursorCheckIdx = pendingExpr->mCursorPos + 1; + prevResolvePass.Init(module->mCompiler->mResolvePassData, &resolvePass); + } + BfTypedValue exprResult; + BfTypedValue origExprResult; if (auto typeRef = BfNodeDynCast(pendingExpr->mExprNode)) { @@ -671,14 +960,24 @@ String CeDebugger::EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& { BfExprEvaluator exprEvaluator(mCeMachine->mCeModule); exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_Comptime); - exprEvaluator.VisitChildNoRef(pendingExpr->mExprNode); - exprResult = exprEvaluator.mResult; + exprEvaluator.VisitChildNoRef(pendingExpr->mExprNode); + exprResult = exprEvaluator.GetResult(); + origExprResult = exprResult; if ((exprResult) && (!exprResult.mType->IsComposite())) exprResult = module->LoadValue(exprResult); + module->FixIntUnknown(exprResult); } - + if (dbgState.mBlockedSideEffects) + { + if ((mCeMachine->mDbgPaused) && ((pendingExpr->mExpressionFlags & DwEvalExpressionFlag_AllowCalls) != 0)) + { + // Reprocess in compiler thread + return "!pending"; + } + return "!sideeffects"; + } if (!exprResult) { @@ -686,19 +985,46 @@ String CeDebugger::EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& if (resultType != NULL) { exprResult = BfTypedValue(resultType); - bfPassInstance.ClearErrors(); + pendingExpr->mPassInstance->ClearErrors(); } } - String val; - if (bfPassInstance.HasFailed()) + if ((exprResult.mType == NULL) && (dbgState.mReferencedIncompleteTypes)) { - BfLogDbgExpr("Evaluate Failed: %s\n", bfPassInstance.mErrors[0]->mError.c_str()); - val = StrFormat("!%d\t%d\t%s", bfPassInstance.mErrors[0]->GetSrcStart(), bfPassInstance.mErrors[0]->GetSrcLength(), bfPassInstance.mErrors[0]->mError.c_str()); + if ((mCeMachine->mDbgPaused) && ((pendingExpr->mExpressionFlags & DwEvalExpressionFlag_AllowCalls) != 0)) + { + // Reprocess in compiler thread + return "!pending"; + } + return "!incomplete"; } - else + + String val; + if (pendingExpr->mPassInstance->HasFailed()) { - val = TypedValueToString(exprResult, pendingExpr->mExprNode->ToString(), pendingExpr->mFormatInfo, (pendingExpr->mExpressionFlags & DwEvalExpressionFlag_FullPrecision) != 0); + BfLogDbgExpr("Evaluate Failed: %s\n", pendingExpr->mPassInstance->mErrors[0]->mError.c_str()); + String errorStr = pendingExpr->mPassInstance->mErrors[0]->mError; + for (auto moreInfo : pendingExpr->mPassInstance->mErrors[0]->mMoreInfo) + { + errorStr += " "; + errorStr += moreInfo->mInfo; + } + + errorStr.Replace('\n', ' '); + val = StrFormat("!%d\t%d\t%s", pendingExpr->mPassInstance->mErrors[0]->GetSrcStart(), pendingExpr->mPassInstance->mErrors[0]->GetSrcLength(), errorStr.c_str()); + } + else if ((!exprResult) && (!exprResult.IsNoValueType())) + { + return "!Debug evaluate failed"; + } + else + { + CeTypeModKind typeModKind = CeTypeModKind_Normal; + if ((origExprResult) && (!origExprResult.IsAddr()) && (origExprResult.mType->IsValueType())) + typeModKind = CeTypeModKind_Const; + else if (origExprResult.IsReadOnly()) + typeModKind = CeTypeModKind_ReadOnly; + val = TypedValueToString(exprResult, pendingExpr->mExprNode->ToString(), pendingExpr->mFormatInfo, (pendingExpr->mExpressionFlags & DwEvalExpressionFlag_FullPrecision) != 0, typeModKind); if ((!val.empty()) && (val[0] == '!')) return val; @@ -706,9 +1032,9 @@ String CeDebugger::EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& if (pendingExpr->mFormatInfo.mRawString) return val; - if (bfPassInstance.HasMessages()) + if (pendingExpr->mPassInstance->HasMessages()) { - for (auto error : bfPassInstance.mErrors) + for (auto error : pendingExpr->mPassInstance->mErrors) { if (error->mIsWarning) { @@ -738,14 +1064,23 @@ String CeDebugger::EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& if (dbgState.mHadSideEffects) val += "\n:sideeffects"; - auto resultConstant = module->mBfIRBuilder->GetConstant(exprResult.mValue); - if (resultConstant != NULL) +// auto resultConstant = module->mBfIRBuilder->GetConstant(exprResult.mValue); +// if (resultConstant != NULL) +// { +// auto ceResultTyped = GetAddr(resultConstant); +// if (ceResultTyped.mAddr != 0) +// val += "\n:canEdit"; +// } + + if ((origExprResult.mType != NULL) && (!origExprResult.mType->IsComposite()) && (!origExprResult.mType->IsRef()) && + (origExprResult.IsAddr()) && (!origExprResult.IsReadOnly())) { - auto ceResultTyped = GetAddr(resultConstant); - if (ceResultTyped.mAddr != 0) - val += "\n:canEdit"; + val += "\n:canEdit"; } + if (pendingExpr->mCursorPos != -1) + val += GetAutocompleteOutput(autoComplete); + return val; } @@ -760,11 +1095,12 @@ String CeDebugger::Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int formatInfo.mRawString = true; } + auto ceContext = mCeMachine->mCurContext; bool valIsAddr = false; BfParser* parser = new BfParser(mCompiler->mSystem); - BfPassInstance bfPassInstance(mCompiler->mSystem); + BfPassInstance* bfPassInstance = new BfPassInstance(mCompiler->mSystem); auto parseAsType = false; @@ -799,12 +1135,12 @@ String CeDebugger::Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int } parser->SetSource(terminatedExpr.c_str(), (int)terminatedExpr.length()); - parser->Parse(&bfPassInstance); + parser->Parse(bfPassInstance); BfReducer bfReducer; bfReducer.mAlloc = parser->mAlloc; bfReducer.mSystem = mCompiler->mSystem; - bfReducer.mPassInstance = &bfPassInstance; + bfReducer.mPassInstance = bfPassInstance; bfReducer.mVisitorPos = BfReducer::BfVisitorPos(parser->mRootNode); bfReducer.mVisitorPos.MoveNext(); bfReducer.mSource = parser; @@ -818,6 +1154,7 @@ String CeDebugger::Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int formatInfo.mCallStackIdx = callStackIdx; CePendingExpr* pendingExpr = new CePendingExpr(); + pendingExpr->mPassInstance = bfPassInstance; pendingExpr->mParser = parser; pendingExpr->mCallStackIdx = callStackIdx; pendingExpr->mCursorPos = cursorPos; @@ -854,11 +1191,11 @@ String CeDebugger::Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int if ((explicitType == NULL) && (formatFlags.length() > 0)) { String errorString = "Invalid expression"; - if (!ParseFormatInfo(formatFlags, &formatInfo, &bfPassInstance, &assignExprOffset, &assignExpr, &errorString)) + if (!ParseFormatInfo(formatFlags, &formatInfo, bfPassInstance, &assignExprOffset, &assignExpr, &errorString)) { if (formatInfo.mRawString) return ""; - bfPassInstance.FailAt(errorString, parser->mSourceData, exprNode->GetSrcEnd(), (int)expr.length() - exprNode->GetSrcEnd()); + bfPassInstance->FailAt(errorString, parser->mSourceData, exprNode->GetSrcEnd(), (int)expr.length() - exprNode->GetSrcEnd()); formatFlags = ""; } if (assignExprOffset != -1) @@ -889,7 +1226,8 @@ String CeDebugger::Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int pendingExpr->mExplitType = explicitType; pendingExpr->mFormatInfo = formatInfo; - String result = EvaluateContinue(pendingExpr, bfPassInstance); + + String result = DoEvaluate(pendingExpr, false); if (result == "!pending") { BF_ASSERT(mDebugPendingExpr == NULL); @@ -898,6 +1236,9 @@ String CeDebugger::Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int return "!retry"; // We already have a pending } mDebugPendingExpr = pendingExpr; + mCeMachine->mStepState.mKind = CeStepState::Kind_Evaluate; + mRunState = RunState_DebugEval; + ContinueDebugEvent(); } else delete pendingExpr; @@ -1099,7 +1440,7 @@ CeDbgTypeInfo* CeDebugger::GetDbgTypeInfo(int typeId) for (int fieldIdx = 0; fieldIdx < typeInst->mFieldInstances.mSize; fieldIdx++) { auto& fieldInst = typeInst->mFieldInstances[fieldIdx]; - if (fieldInst.mDataIdx > 0) + if (fieldInst.mDataIdx >= 0) { while (fieldInst.mDataIdx >= dbgTypeInfo->mFieldOffsets.mSize) dbgTypeInfo->mFieldOffsets.Add(CeDbgFieldEntry()); @@ -1257,15 +1598,13 @@ String CeDebugger::GetMemberList(BfType* type, addr_ce addr, addr_ce addrInst, b String retVal; int fieldCount = 0; - if ((typeInst->mBaseType != NULL) && - (!typeInst->mBaseType->IsInstanceOf(mCompiler->mBfObjectTypeDef)) && - (!typeInst->mBaseType->IsInstanceOf(mCompiler->mValueTypeTypeDef))) + if ((!isStatic) && (typeInst->mBaseType != NULL) && (!typeInst->mBaseType->IsInstanceOf(mCompiler->mValueTypeTypeDef))) { retVal += StrFormat("[base]\tthis,this=%d@0x%X, nd, na, nv", typeInst->mBaseType->mTypeId, addr); fieldCount++; } - auto ceContext = mCompiler->mCEMachine->mCurContext; + auto ceContext = mCompiler->mCeMachine->mCurContext; bool didStaticCtor = ceContext->mStaticCtorExecSet.Contains(type->mTypeId); bool hasStaticFields = false; @@ -1274,7 +1613,7 @@ String CeDebugger::GetMemberList(BfType* type, addr_ce addr, addr_ce addrInst, b auto fieldDef = fieldInst.GetFieldDef(); if (fieldDef == NULL) continue; - + if (fieldDef->mIsStatic != isStatic) { if (fieldDef->mIsStatic) @@ -1698,12 +2037,12 @@ String CeDebugger::GetArrayItems(DebugVisualizerEntry* debugVis, BfType* valueTy addrs += typeAddr; } - String addr = EncodeDataPtr(ceTypedVal.mAddr, false); + String addr = EncodeDataPtr((addr_ce)ceTypedVal.mAddr, false); addrs += addr; usedCount++; } auto elemType = curNode.mType->GetUnderlyingType(); - curNodeAddr = ceTypedVal.mAddr + elemType->GetStride(); + curNodeAddr = (addr_ce)ceTypedVal.mAddr + elemType->GetStride(); curNode.mValue = ceModule->mBfIRBuilder->CreateIntToPtr(curNodeAddr, ceModule->mBfIRBuilder->MapType(curNode.mType)); } count = usedCount; @@ -1721,43 +2060,52 @@ String CeDebugger::GetLinkedListItems(DebugVisualizerEntry* debugVis, addr_ce en { CeEvaluationContext nextEvaluationContext(this, debugVis->mNextPointer); CeEvaluationContext valueEvaluationContext(this, debugVis->mValuePointer); - + auto ceModule = mCeMachine->mCeModule; + String addrs; bool checkLeft = true; + + int mapIdx; + for (mapIdx = 0; mapIdx < count; mapIdx++) + { + CeTypedValue ceNodeVal = GetAddr(curNode); + if (!ceNodeVal) + break; - //TODO; -// int mapIdx; -// for (mapIdx = 0; mapIdx < count; mapIdx++) -// { -// if (curNode.mPtr == endNodePtr) -// break; -// BfTypedValue val = valueEvaluationContext.EvaluateInContext(curNode); -// if (!val) -// break; -// if (val.mPtr == 0) -// break; -// -// if (valueType == NULL) -// { -// String typeAddr = val.mType->ToStringRaw(); -// // RPad -// typeAddr.Append(' ', sizeof(addr_ce) * 2 - typeAddr.length()); -// addrs += typeAddr; -// } -// -// String addr = EncodeDataPtr(val.mPtr, false); -// addrs += addr; -// -// curNode = nextEvaluationContext.EvaluateInContext(curNode); -// } -// count = mapIdx; -// -// if (outContinuationData != NULL) -// { -// *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(endNodePtr, false) + EncodeDataPtr(valueType, false) + -// EncodeDataPtr(curNode.mType, false) + EncodeDataPtr(curNode.mPtr, false); -// } + if (ceNodeVal.mAddr == endNodePtr) + break; + BfTypedValue val = valueEvaluationContext.EvaluateInContext(curNode); + if (!val) + break; + + auto ceVal = GetAddr(val); + if (!ceVal) + break; + if (ceVal.mAddr == 0) + break; + + if (valueType == NULL) + { + String typeAddr = StrFormat("comptype(%d)", val.mType->mTypeId); + // RPad + typeAddr.Append(' ', sizeof(addr_ce) * 2 - (int)typeAddr.length()); + addrs += typeAddr; + } + + String addr = EncodeDataPtr((addr_ce)ceVal.mAddr, false); + addrs += addr; + + curNode = nextEvaluationContext.EvaluateInContext(curNode); + } + count = mapIdx; + + if (outContinuationData != NULL) + { + CeTypedValue ceNodeVal = GetAddr(curNode); + *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(endNodePtr, false) + EncodeDataPtr(valueType, false) + + EncodeDataPtr(curNode.mType, false) + EncodeDataPtr((addr_ce)ceNodeVal.mAddr, false); + } return addrs; } @@ -1765,6 +2113,7 @@ String CeDebugger::GetLinkedListItems(DebugVisualizerEntry* debugVis, addr_ce en String CeDebugger::GetDictionaryItems(DebugVisualizerEntry* debugVis, BfTypedValue dictValue, int bucketIdx, int nodeIdx, int& count, String* outContinuationData) { CeEvaluationContext nextEvaluationContext(this, debugVis->mNextPointer); + auto ceModule = mCeMachine->mCeModule; BfTypedValue bucketsPtr = EvaluateInContext(dictValue, debugVis->mBuckets); BfTypedValue entriesPtr = EvaluateInContext(dictValue, debugVis->mEntries); @@ -1773,52 +2122,68 @@ String CeDebugger::GetDictionaryItems(DebugVisualizerEntry* debugVis, BfTypedVal count = -1; return ""; } - + + auto ceDictTypedVal = GetAddr(dictValue); + if (!ceDictTypedVal) + return ""; + + auto ceBucketsTypedVal = GetAddr(bucketsPtr); + if (!ceBucketsTypedVal) + return ""; + String addrs; - //TODO: -// int entrySize = entriesPtr.mType->mTypeParam->GetStride(); -// int bucketIdxSize = bucketsPtr.mType->mTypeParam->GetStride(); -// -// bool checkLeft = true; -// -// int encodeCount = 0; -// while (encodeCount < count) -// { -// if (nodeIdx != -1) -// { -// BfTypedValue entryValue; -// entryValue.mSrcAddress = entriesPtr.mPtr + (nodeIdx * entrySize); -// entryValue.mType = entriesPtr.mType->mTypeParam; -// -// addrs += EncodeDataPtr(entryValue.mSrcAddress, false); -// -// BfTypedValue nextValue = nextEvaluationContext.EvaluateInContext(entryValue); -// if ((!nextValue) || (!nextValue.mType->IsInteger())) -// { -// break; -// } -// -// nodeIdx = (int)nextValue.GetInt64(); -// encodeCount++; -// } -// else -// { -// if (bucketIdxSize == 4) -// nodeIdx = ReadMemory(bucketsPtr.mPtr + bucketIdx * sizeof(int32)); -// else -// nodeIdx = (int)ReadMemory(bucketsPtr.mPtr + bucketIdx * sizeof(int64)); -// bucketIdx++; -// } -// } -// -// count = encodeCount; -// -// if (outContinuationData != NULL) -// { -// *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(dictValue.mType, false) + EncodeDataPtr(dictValue.mSrcAddress, false) + -// EncodeDataPtr((addr_ce)bucketIdx, false) + EncodeDataPtr((addr_ce)nodeIdx, false); -// } + if ((!entriesPtr) || (!entriesPtr.mType->IsPointer())) + return ""; + if ((!bucketsPtr) || (!bucketsPtr.mType->IsPointer())) + return ""; + + auto entryType = entriesPtr.mType->GetUnderlyingType(); + int entrySize = entryType->GetStride(); + int bucketIdxSize = bucketsPtr.mType->GetUnderlyingType()->GetStride(); + + auto ceElemTypedVal = GetAddr(entriesPtr); + if (!ceElemTypedVal) + return ""; + + bool checkLeft = true; + + int encodeCount = 0; + while (encodeCount < count) + { + if (nodeIdx != -1) + { + addr_ce entryAddr = (addr_ce)ceElemTypedVal.mAddr + (nodeIdx * entrySize); + + BfTypedValue entryValue = BfTypedValue(ceModule->mBfIRBuilder->CreateConstAggCE(ceModule->mBfIRBuilder->MapType(entryType), entryAddr), entryType); + addrs += EncodeDataPtr(entryAddr, false); + + BfTypedValue nextValue = nextEvaluationContext.EvaluateInContext(entryValue); + if ((!nextValue) || (!nextValue.mType->IsInteger())) + { + break; + } + + nodeIdx = (int)ValueToInt(nextValue); + encodeCount++; + } + else + { + if (bucketIdxSize == 4) + nodeIdx = ReadMemory(ceBucketsTypedVal.mAddr + bucketIdx * sizeof(int32)); + else + nodeIdx = (int)ReadMemory(ceBucketsTypedVal.mAddr + bucketIdx * sizeof(int64)); + bucketIdx++; + } + } + + count = encodeCount; + + if (outContinuationData != NULL) + { + *outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(dictValue.mType, false) + EncodeDataPtr((addr_ce)ceDictTypedVal.mAddr, false) + + EncodeDataPtr((addr_ce)bucketIdx, false) + EncodeDataPtr((addr_ce)nodeIdx, false); + } return addrs; } @@ -1964,22 +2329,23 @@ String CeDebugger::GetCollectionContinuation(const StringImpl& continuationData, // return retVal; } else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_LinkedList) - { - //TODO: -// addr_ce endNodePtr = DecodeTargetDataPtr(dataPtr); -// DbgType* valueType = (DbgType*)DecodeLocalDataPtr(dataPtr); -// BfTypedValue curNode; -// curNode.mType = (DbgType*)DecodeLocalDataPtr(dataPtr); -// curNode.mPtr = DecodeTargetDataPtr(dataPtr); -// -// String newContinuationData; -// -// if (count < 0) -// count = 3; -// -// String retVal = GetLinkedListItems(dbgCompileUnit, debugVis, endNodePtr, valueType, curNode, count, &newContinuationData); -// retVal += "\n" + newContinuationData; -// return retVal; + { + addr_ce endNodePtr = DecodeTargetDataPtr(dataPtr); + BfType* valueType = (BfType*)DecodeLocalDataPtr(dataPtr); + BfType* nodeType = (BfType*)DecodeLocalDataPtr(dataPtr); + + BfTypedValue curNode = BfTypedValue( + ceModule->mBfIRBuilder->CreateIntToPtr(DecodeTargetDataPtr(dataPtr), ceModule->mBfIRBuilder->MapType(nodeType)), + nodeType); + + String newContinuationData; + + if (count < 0) + count = 3; + + String retVal = GetLinkedListItems(debugVis, endNodePtr, valueType, curNode, count, &newContinuationData); + retVal += "\n" + newContinuationData; + return retVal; } else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Array) { @@ -2000,25 +2366,25 @@ String CeDebugger::GetCollectionContinuation(const StringImpl& continuationData, return retVal; } else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Dictionary) - { - //TODO: -// BfTypedValue dictValue; -// dictValue.mType = (DbgType*)DecodeLocalDataPtr(dataPtr); -// dictValue.mSrcAddress = DecodeTargetDataPtr(dataPtr); -// -// int bucketIdx = (int)DecodeTargetDataPtr(dataPtr); -// int nodeIdx = (int)DecodeTargetDataPtr(dataPtr); -// -// String newContinuationData; -// String retVal = GetDictionaryItems(dbgCompileUnit, debugVis, dictValue, bucketIdx, nodeIdx, count, &newContinuationData); -// retVal += "\n" + newContinuationData; -// return retVal; + { + auto dictValueType = (BfType*)DecodeLocalDataPtr(dataPtr); + BfTypedValue dictValue = BfTypedValue( + ceModule->mBfIRBuilder->CreateIntToPtr(DecodeTargetDataPtr(dataPtr), ceModule->mBfIRBuilder->MapType(dictValueType)), + dictValueType); + + int bucketIdx = (int)DecodeTargetDataPtr(dataPtr); + int nodeIdx = (int)DecodeTargetDataPtr(dataPtr); + + String newContinuationData; + String retVal = GetDictionaryItems(debugVis, dictValue, bucketIdx, nodeIdx, count, &newContinuationData); + retVal += "\n" + newContinuationData; + return retVal; } return ""; } -CeTypedValue CeDebugger::GetAddr(BfConstant* constant) +CeTypedValue CeDebugger::GetAddr(BfConstant* constant, BfType* type) { auto module = mCeMachine->mCeModule; auto ceContext = mCeMachine->mCurContext; @@ -2059,6 +2425,22 @@ CeTypedValue CeDebugger::GetAddr(BfConstant* constant) } return CeTypedValue(fieldInfo->mAddr, globalVar->mType); } + else if (constant->mTypeCode == BfTypeCode_StringId) + { + auto stringType = module->ResolveTypeDef(module->mCompiler->mStringTypeDef)->ToTypeInstance(); + if ((type != NULL) && (type->IsPointer())) + { + BfType* charType = module->GetPrimitiveType(BfTypeCode_Char8); + BfType* charPtrType = module->CreatePointerType(charType); + auto addr = ceContext->GetString(constant->mInt32) + stringType->mInstSize; + return CeTypedValue(addr, module->mBfIRBuilder->MapType(charPtrType)); + } + else + { + auto addr = ceContext->GetString(constant->mInt32); + return CeTypedValue(addr, module->mBfIRBuilder->MapType(stringType)); + } + } else if (constant->mConstType == BfConstType_AggCE) { auto aggCE = (BfConstantAggCE*)constant; @@ -2093,11 +2475,6 @@ CeTypedValue CeDebugger::GetAddr(BfConstant* constant) if (dbgTypeInfo == NULL) return CeTypedValue(); - if (!dbgTypeInfo->mType->IsPointer()) - { - NOP; - } - auto addr = typedVal.mAddr; if (gepConst->mIdx0 != 0) @@ -2128,14 +2505,31 @@ CeTypedValue CeDebugger::GetAddr(BfConstant* constant) addr += gepConst->mIdx0 * dbgTypeInfo->mType->GetStride(); if (gepConst->mIdx1 != 0) addr += dbgTypeInfo->mFieldOffsets[gepConst->mIdx1].mDataOffset; - auto ptrType = module->CreatePointerType(dbgTypeInfo->mFieldOffsets[gepConst->mIdx1].mType); + BfType* ptrType = NULL; + if (gepConst->mIdx1 == 0) + { + auto typeInst = dbgTypeInfo->mType->ToTypeInstance(); + if ((typeInst != NULL) && (typeInst->mBaseType != NULL)) + { + ptrType = typeInst->mBaseType; + if (!ptrType->IsValueType()) + ptrType = module->CreatePointerType(ptrType); + } + } + + if (ptrType == NULL) + { + if (gepConst->mIdx1 > dbgTypeInfo->mFieldOffsets.mSize) + return CeTypedValue(); + ptrType = module->CreatePointerType(dbgTypeInfo->mFieldOffsets[gepConst->mIdx1].mType); + } return CeTypedValue(addr, module->mBfIRBuilder->MapType(ptrType)); } else if ((constant->mTypeCode == BfTypeCode_Int32) || (constant->mTypeCode == BfTypeCode_Int64) || (constant->mTypeCode == BfTypeCode_IntPtr)) { - return CeTypedValue((addr_ce)constant->mInt64, module->mBfIRBuilder->GetPrimitiveType(constant->mTypeCode)); + return CeTypedValue(constant->mInt64, module->mBfIRBuilder->GetPrimitiveType(constant->mTypeCode)); } return CeTypedValue(); @@ -2146,7 +2540,7 @@ CeTypedValue CeDebugger::GetAddr(const BfTypedValue typedVal) auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(typedVal.mValue); if (constant == NULL) return CeTypedValue(); - return GetAddr(constant); + return GetAddr(constant, typedVal.mType); } #define GET_FROM(ptr, T) *((T*)(ptr += sizeof(T)) - 1) @@ -2415,15 +2809,20 @@ void CeDebugger::ProcessEvalString(BfTypedValue useTypedValue, String& evalStr, } } -String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const StringImpl& expr, CeFormatInfo& formatInfo, bool fullPrecision) +String CeDebugger::TypedValueToString(const BfTypedValue& origTypedValue, const StringImpl& expr, CeFormatInfo& formatInfo, bool fullPrecision, CeTypeModKind typeModKind) { + BfTypedValue typedValue = origTypedValue; + auto module = mCeMachine->mCeModule; String retVal; if (typedValue.IsNoValueType()) { + String typeName = TypeToString(typedValue); + + retVal += typeName; retVal += "\n"; - retVal += module->TypeToString(typedValue.mType); + retVal += typeName; retVal += "\n"; retVal += GetMemberList(typedValue.mType, 0, 0, true); return retVal; @@ -2453,8 +2852,8 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri } else if ((typedValue.IsAddr()) || (typedValue.mType->IsObjectOrInterface()) || (typedValue.mType->IsPointer())) { - CeTypedValue typedVal = GetAddr(constant); - addr = typedVal.mAddr; + CeTypedValue typedVal = GetAddr(constant, typedValue.mType); + addr = (addr_ce)typedVal.mAddr; if (!typedVal) { return "!Invalid addr type"; @@ -2490,7 +2889,12 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri uint8* data = ceContext->GetMemoryPtr(addr, checkMemSize); if ((addr != 0) && (data == NULL)) - return "!Invalid address"; + { + if (typedValue.mType->IsPointer()) + return EncodeDataPtr(addr, true) + "\n" + TypeToString(origTypedValue.mType, typeModKind); + else + return "!Invalid address"; + } addr_ce dataAddr = addr; if ((typedValue.IsAddr()) && (typedValue.mType->IsObjectOrInterface())) @@ -2570,7 +2974,7 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri String idxStr = "[{0}]"; - retVal += "\n" + module->TypeToString(typedValue.mType); + retVal += "\n" + TypeToString(typedValue); String evalStr = StrFormat("((comptype(%d))(void*)", typedValue.mType->mTypeId) + EncodeDataPtr(ptrVal, true) + ")[{0}]"; @@ -2592,130 +2996,21 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri } } - if (typedValue.mType->IsPrimitiveType()) + if (typedValue.mType->IsRef()) { - auto primType = (BfPrimitiveType*)typedValue.mType; - - BfTypeCode typeCode = primType->mTypeDef->mTypeCode; - if (typeCode == BfTypeCode_IntPtr) - typeCode = (primType->mSize == 8) ? BfTypeCode_Int64 : BfTypeCode_Int32; - if (typeCode == BfTypeCode_UIntPtr) - typeCode = (primType->mSize == 8) ? BfTypeCode_UInt64 : BfTypeCode_UInt32; + if (dataAddr == 0) + return "\n" + TypeToString(typedValue); - switch (typeCode) - { - case BfTypeCode_Boolean: - { - auto val = *(uint8*)(data); - if (val == 0) - return "false\nbool"; - else if (val == 1) - return "true\nbool"; - else - return StrFormat("true (%d)\nbool", val); - } - break; - case BfTypeCode_Char8: - { - auto val = *(uint8*)(data); - if (val != 0) - { - char str[2] = { (char)val }; - result = SlashString(str, formatInfo.mDisplayType == DwDisplayType_Utf8, true); + addr = *(addr_ce*)data; + dataAddr = addr; - if (!IsNormalChar(val)) - result = StrFormat("'%s' (0x%02X)\n", result.c_str(), val); - else - result = StrFormat("'%s'\n", result.c_str()); - } - else - result = "'\\0'\n"; - return result + "char"; - } - break; - case BfTypeCode_Char16: - { - auto val = *(uint16*)(data); - if (val != 0) - { - u8_toutf8(str, 8, val); - result = SlashString(str, true, true); - if (!IsNormalChar(val)) - result = StrFormat("'%s' (0x%02X)\n", result.c_str(), val); - else - result = StrFormat("'%s'\n", result.c_str()); - } - else - result = "'\\0'\n"; - return result + "char16"; - } - break; - case BfTypeCode_Char32: - { - auto val = *(uint32*)(data); - if (val != 0) - { - u8_toutf8(str, 8, val); - result = SlashString(str, true, true); - if (!IsNormalChar(val)) - result = StrFormat("'%s' (0x%02X)\n", result.c_str(), val); - else - result = StrFormat("'%s'\n", result.c_str()); - } - else - result = "'\\0'\n"; - return result + "char32"; - } - break; - case BfTypeCode_Int8: - return IntTypeToString(*(int8*)(data), "int8", displayInfo, formatInfo); - case BfTypeCode_UInt8: - return IntTypeToString(*(uint8*)(data), "uint8", displayInfo, formatInfo); - case BfTypeCode_Int16: - return IntTypeToString(*(int16*)(data), "int16", displayInfo, formatInfo); - case BfTypeCode_UInt16: - return IntTypeToString(*(uint16*)(data), "uint16", displayInfo, formatInfo); - case BfTypeCode_Int32: - return IntTypeToString(*(int32*)(data), "int32", displayInfo, formatInfo); - case BfTypeCode_UInt32: - return IntTypeToString(*(uint32*)(data), "uint32", displayInfo, formatInfo); - case BfTypeCode_Int64: - return IntTypeToString(*(int64*)(data), "int64", displayInfo, formatInfo); - case BfTypeCode_UInt64: - return IntTypeToString(*(uint64*)(data), "uint64", displayInfo, formatInfo); - case BfTypeCode_Float: - { - DwFloatDisplayType floatDisplayType = displayInfo->mFloatDisplayType; - if (floatDisplayType == DwFloatDisplayType_Default) - floatDisplayType = DwFloatDisplayType_Minimal; - if (floatDisplayType == DwFloatDisplayType_Minimal) - ExactMinimalFloatToStr(*(float*)data, str); - else if (floatDisplayType == DwFloatDisplayType_Full) - sprintf(str, "%1.9g", *(float*)data); - else if (floatDisplayType == DwFloatDisplayType_HexUpper) - sprintf(str, "0x%04X", *(uint32*)data); - else //if (floatDisplayType == DwFloatDisplayType_HexLower) - sprintf(str, "0x%04x", *(uint32*)data); - return StrFormat("%s\n%s", str, "float"); - } - case BfTypeCode_Double: - { - DwFloatDisplayType floatDisplayType = displayInfo->mFloatDisplayType; - if (floatDisplayType == DwFloatDisplayType_Default) - floatDisplayType = DwFloatDisplayType_Minimal; - if (floatDisplayType == DwFloatDisplayType_Minimal) - ExactMinimalDoubleToStr(*(double*)data, str); - else if (floatDisplayType == DwFloatDisplayType_Full) - sprintf(str, "%1.17g", *(double*)data); - else if (floatDisplayType == DwFloatDisplayType_HexUpper) - sprintf(str, "0x%08llX", *(uint64*)data); - else //if (floatDisplayType == DwFloatDisplayType_HexLower) - sprintf(str, "0x%08llx", *(uint64*)data); - return StrFormat("%s\n%s", str, "double"); - } - } + data = ceContext->GetMemoryPtr(addr, checkMemSize); + if ((addr != 0) && (data == NULL)) + return "!Invalid address"; + + typedValue = BfTypedValue(typedValue.mValue, typedValue.mType->GetUnderlyingType(), true); } - + if (typedValue.mType->IsPointer()) { //ceContext-> @@ -2739,16 +3034,16 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri if (!formatInfo.mHidePointers) retVal = EncodeDataPtr(ptrVal, true); - int strLen = (int)formatInfo.mOverrideCount; -// if (typedValue.mIsLiteral) -// { -// if (strLen == -1) -// strLen = 0x7FFFFFFF; -// if (typedValue.mDataLen > 0) -// strLen = BF_MIN(strLen, typedValue.mDataLen); -// else -// strLen = BF_MIN(strLen, strlen(typedValue.mCharPtr)); -// } + int strLen = (int)formatInfo.mOverrideCount; + // if (typedValue.mIsLiteral) + // { + // if (strLen == -1) + // strLen = 0x7FFFFFFF; + // if (typedValue.mDataLen > 0) + // strLen = BF_MIN(strLen, typedValue.mDataLen); + // else + // strLen = BF_MIN(strLen, strlen(typedValue.mCharPtr)); + // } SetAndRestoreValue prevOverrideLen(formatInfo.mOverrideCount, strLen); String strResult = ReadString(primType->mTypeDef->mTypeCode, ptrVal, strLen, formatInfo); @@ -2760,89 +3055,25 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri retVal += " "; retVal += strResult; } - retVal += "\n" + module->TypeToString(typedValue.mType); + retVal += "\n" + TypeToString(origTypedValue.mType, typeModKind); return retVal; } -// else if ((unmodInnerType != NULL) && -// ((unmodInnerType->mTypeCode == DbgType_Class) || (unmodInnerType->mTypeCode == DbgType_Struct) || (unmodInnerType->mTypeCode == DbgType_Union))) -// { -// isCompositeType = true; -// } -// else if ((unmodInnerType != NULL) && (unmodInnerType->mTypeCode == DbgType_SizedArray)) -// { -// isSizedArray = true; -// } -// else if (unmodInnerType->mTypeCode == DbgType_Subroutine) -// { -// if (formatInfo.mRawString) -// return ""; -// addr_ce funcPtr = (addr_ce)typedValue.mPtr; -// String retVal; -// if ((!typedValue.mIsLiteral) && (!formatInfo.mHidePointers)) -// retVal = EncodeDataPtr(funcPtr, true); + else if ((ptrVal != 0) && (innerType->IsComposite())) + { +// addr = *(addr_ce*)data; +// dataAddr = addr; // -// String symbolName; -// addr_ce offset; -// DbgModule* dwarf; -// static String demangledName; -// auto subProgram = mDebugTarget->FindSubProgram(funcPtr); -// if (subProgram != NULL) -// { -// demangledName = subProgram->ToString(); -// } -// else if (mDebugTarget->FindSymbolAt(funcPtr, &symbolName, &offset, &dwarf)) -// { -// demangledName = BfDemangler::Demangle(symbolName, language); -// -// if (offset != 0) -// demangledName += StrFormat("+%d", offset); -// } -// else -// { -// auto dbgModule = mDebugTarget->FindDbgModuleForAddress(funcPtr); -// if (dbgModule != NULL) -// demangledName += dbgModule->GetLinkedModule()->mDisplayName + "!"; -// demangledName += StrFormat("0x%@", funcPtr); -// } -// -// retVal += " {"; -// retVal += demangledName; -// retVal += "}"; -// retVal += "\n" + origValueType->ToString(language); -// -// return retVal; -// } -// else if (unmodInnerType->mTypeCode == DbgType_Void) -// { -// if (formatInfo.mRawString) -// return ""; -// addr_ce ptr = (addr_ce)typedValue.mPtr; -// String symbolName; -// addr_ce offset; -// DbgModule* dwarf; -// String demangledName; -// -// retVal += demangledName = StrFormat("0x%@", ptr); -// -// if (mDebugTarget->FindSymbolAt(ptr, &symbolName, &offset, &dwarf)) -// { -// if (offset == 0) -// { -// retVal += " {"; -// retVal += BfDemangler::Demangle(symbolName, language); -// retVal += "}"; -// } -// } -// -// retVal += "\n" + origValueType->ToString(language); -// -// return retVal; -// } -// else - { +// data = ceContext->GetMemoryPtr(addr, checkMemSize); +// if ((addr != 0) && (data == NULL)) +// return "!Invalid address"; + + typedValue = BfTypedValue(typedValue.mValue, typedValue.mType->GetUnderlyingType(), true); + } + else + { if (formatInfo.mRawString) - return ""; - + return ""; + String retVal; if (!formatInfo.mHidePointers) retVal = EncodeDataPtr((uint32)ptrVal, true); @@ -2855,7 +3086,7 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri if (innerTypedVal) { - CeFormatInfo defaultFormatInfo; + CeFormatInfo defaultFormatInfo; defaultFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + 2; // Take into accout the necessary {}'s defaultFormatInfo.mExpandItemDepth++; defaultFormatInfo.mCallStackIdx = formatInfo.mCallStackIdx; @@ -2878,10 +3109,10 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri } } - retVal += "\n" + module->TypeToString(typedValue.mType); + retVal += "\n" + TypeToString(origTypedValue.mType, typeModKind); module->PopulateType(innerType); - if (ptrVal != 0) + if ((ptrVal != 0) && (!innerType->IsValuelessType())) { //String ptrDataStr = StrFormat("(%s)", dwValueType->ToStringRaw(language).c_str()) + EncodeDataPtr(typedValue.mPtr, true); retVal += "\n*\t"; @@ -2895,14 +3126,141 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri retVal += ", refid=" + MaybeQuoteFormatInfoParam(formatInfo.mReferenceId); retVal += StrFormat(", this=%d@0x%X", innerType->mTypeId, ptrVal); + } - - retVal += "\n:editVal\t" + EncodeDataPtr((uint32)addr, true); + + retVal += "\n:canEdit\n:editVal\t" + EncodeDataPtr((uint32)addr, true); return retVal; } } + if (typedValue.mType->IsPrimitiveType()) + { + auto primType = (BfPrimitiveType*)typedValue.mType; + + BfTypeCode typeCode = primType->mTypeDef->mTypeCode; + if (typeCode == BfTypeCode_IntPtr) + typeCode = (primType->mSize == 8) ? BfTypeCode_Int64 : BfTypeCode_Int32; + if (typeCode == BfTypeCode_UIntPtr) + typeCode = (primType->mSize == 8) ? BfTypeCode_UInt64 : BfTypeCode_UInt32; + + switch (typeCode) + { + case BfTypeCode_None: + return "\nvoid"; + case BfTypeCode_Boolean: + { + auto val = *(uint8*)(data); + if (val == 0) + return "false\n" + TypeToString(origTypedValue.mType, typeModKind); + else if (val == 1) + return "true\n" + TypeToString(origTypedValue.mType, typeModKind); + else + return StrFormat("true (%d)\n%s", val, TypeToString(origTypedValue.mType, typeModKind).c_str()); + } + break; + case BfTypeCode_Char8: + { + auto val = *(uint8*)(data); + if (val != 0) + { + char str[2] = { (char)val }; + result = SlashString(str, formatInfo.mDisplayType == DwDisplayType_Utf8, true); + + if (!IsNormalChar(val)) + result = StrFormat("'%s' (0x%02X)\n", result.c_str(), val); + else + result = StrFormat("'%s'\n", result.c_str()); + } + else + result = "'\\0'\n"; + return result + TypeToString(origTypedValue.mType, typeModKind); + } + break; + case BfTypeCode_Char16: + { + auto val = *(uint16*)(data); + if (val != 0) + { + u8_toutf8(str, 8, val); + result = SlashString(str, true, true); + if (!IsNormalChar(val)) + result = StrFormat("'%s' (0x%02X)\n", result.c_str(), val); + else + result = StrFormat("'%s'\n", result.c_str()); + } + else + result = "'\\0'\n"; + return result + TypeToString(origTypedValue.mType, typeModKind); + } + break; + case BfTypeCode_Char32: + { + auto val = *(uint32*)(data); + if (val != 0) + { + u8_toutf8(str, 8, val); + result = SlashString(str, true, true); + if (!IsNormalChar(val)) + result = StrFormat("'%s' (0x%02X)\n", result.c_str(), val); + else + result = StrFormat("'%s'\n", result.c_str()); + } + else + result = "'\\0'\n"; + return result + TypeToString(origTypedValue.mType, typeModKind); + } + break; + case BfTypeCode_Int8: + return IntTypeToString(*(int8*)(data), TypeToString(origTypedValue.mType, typeModKind), displayInfo, formatInfo); + case BfTypeCode_UInt8: + return IntTypeToString(*(uint8*)(data), TypeToString(origTypedValue.mType, typeModKind), displayInfo, formatInfo); + case BfTypeCode_Int16: + return IntTypeToString(*(int16*)(data), TypeToString(origTypedValue.mType, typeModKind), displayInfo, formatInfo); + case BfTypeCode_UInt16: + return IntTypeToString(*(uint16*)(data), TypeToString(origTypedValue.mType, typeModKind), displayInfo, formatInfo); + case BfTypeCode_Int32: + return IntTypeToString(*(int32*)(data), TypeToString(origTypedValue.mType, typeModKind), displayInfo, formatInfo); + case BfTypeCode_UInt32: + return IntTypeToString(*(uint32*)(data), TypeToString(origTypedValue.mType, typeModKind), displayInfo, formatInfo); + case BfTypeCode_Int64: + return IntTypeToString(*(int64*)(data), TypeToString(origTypedValue.mType, typeModKind), displayInfo, formatInfo); + case BfTypeCode_UInt64: + return IntTypeToString(*(uint64*)(data), TypeToString(origTypedValue.mType, typeModKind), displayInfo, formatInfo); + case BfTypeCode_Float: + { + DwFloatDisplayType floatDisplayType = displayInfo->mFloatDisplayType; + if (floatDisplayType == DwFloatDisplayType_Default) + floatDisplayType = DwFloatDisplayType_Minimal; + if (floatDisplayType == DwFloatDisplayType_Minimal) + ExactMinimalFloatToStr(*(float*)data, str); + else if (floatDisplayType == DwFloatDisplayType_Full) + sprintf(str, "%1.9g", *(float*)data); + else if (floatDisplayType == DwFloatDisplayType_HexUpper) + sprintf(str, "0x%04X", *(uint32*)data); + else //if (floatDisplayType == DwFloatDisplayType_HexLower) + sprintf(str, "0x%04x", *(uint32*)data); + return StrFormat("%s\n%s", str, TypeToString(origTypedValue.mType, typeModKind).c_str()); + } + case BfTypeCode_Double: + { + DwFloatDisplayType floatDisplayType = displayInfo->mFloatDisplayType; + if (floatDisplayType == DwFloatDisplayType_Default) + floatDisplayType = DwFloatDisplayType_Minimal; + if (floatDisplayType == DwFloatDisplayType_Minimal) + ExactMinimalDoubleToStr(*(double*)data, str); + else if (floatDisplayType == DwFloatDisplayType_Full) + sprintf(str, "%1.17g", *(double*)data); + else if (floatDisplayType == DwFloatDisplayType_HexUpper) + sprintf(str, "0x%08llX", *(uint64*)data); + else //if (floatDisplayType == DwFloatDisplayType_HexLower) + sprintf(str, "0x%08llx", *(uint64*)data); + return StrFormat("%s\n%s", str, TypeToString(origTypedValue.mType, typeModKind).c_str()); + } + } + } + if (typedValue.mType->IsSizedArray()) { auto arrayType = (BfSizedArrayType*)typedValue.mType; @@ -2932,9 +3290,9 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri _ShowArraySummary(retVal, ptrVal, arraySize, innerType); } - retVal += "\n" + module->TypeToString(typedValue.mType); + retVal += "\n" + TypeToString(origTypedValue.mType, typeModKind); - String referenceId = module->TypeToString(typedValue.mType); + String referenceId = TypeToString(typedValue.mType); String evalStr; // Why did we have the "na"? Do we not want to show addresses for all members? @@ -3010,7 +3368,7 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri retVal += StrFormat("%lld", bitsLeft); } - retVal += "\n" + module->TypeToString(typedValue.mType); + retVal += "\n" + TypeToString(origTypedValue.mType, typeModKind); retVal += "\n:canEdit"; return retVal; @@ -3034,7 +3392,7 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri retVal += "{ "; retVal += innerReturn.Substring(0, crPos); retVal += " }"; - retVal += "\n" + module->TypeToString(typedValue.mType); + retVal += "\n" + TypeToString(origTypedValue.mType, typeModKind); return retVal; } @@ -3049,7 +3407,7 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri if ((dataAddr == 0) && (addr != 0)) dataAddr = *(addr_ce*)data; - if (((typedValue.mType->IsObjectOrInterface()) && + if ((((origTypedValue.mType->IsObjectOrInterface()) || (origTypedValue.mType->IsPointer())) && (!formatInfo.mHidePointers) || (dataAddr == 0))) { retVal = EncodeDataPtr((uint32)dataAddr, true); @@ -3086,13 +3444,20 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri } } } + + BfTypedValue summaryTypedValue = typedValue; + + if ((actualType != NULL) && (actualType != displayType)) + { + summaryTypedValue = BfTypedValue(module->mBfIRBuilder->CreateIntToPtr(addr, module->mBfIRBuilder->MapType(actualType)), actualType); + } DebugVisualizerEntry* debugVis = NULL; Array dbgVisWildcardCaptures; if ((!formatInfo.mNoVisualizers) && (!isNull) && (!isBadSrc)) { - debugVis = FindVisualizerForType(displayType, &dbgVisWildcardCaptures); + debugVis = FindVisualizerForType(summaryTypedValue.mType, &dbgVisWildcardCaptures); } bool wantsCustomExpandedItems = false; @@ -3105,7 +3470,7 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri { if (!displayEntry->mCondition.empty()) { - if (!EvalCondition(debugVis, typedValue, formatInfo, displayEntry->mCondition, dbgVisWildcardCaptures, displayString)) + if (!EvalCondition(debugVis, summaryTypedValue, formatInfo, displayEntry->mCondition, dbgVisWildcardCaptures, displayString)) continue; } @@ -3113,7 +3478,7 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri String displayStr = mDebugManager->mDebugVisualizers->DoStringReplace(displayEntry->mString, dbgVisWildcardCaptures); if (displayString.length() > 0) displayString += " "; - ProcessEvalString(typedValue, displayStr, displayString, formatInfo, debugVis, true); + ProcessEvalString(summaryTypedValue, displayStr, displayString, formatInfo, debugVis, true); if (formatInfo.mRawString) return displayString; @@ -3137,11 +3502,10 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri String bigRet = isTuple ? "(" : "{ "; int memberIdx = 0; - BfType* summaryType = typedValue.mType; + BfType* summaryType = summaryTypedValue.mType; bool summaryDone = false; bool truncatedMemberList = false; - - BfTypedValue summaryTypedValue = typedValue; + String summaryDataStr = ptrDataStr; String splatStr; if (dataAddr == -1) @@ -3210,6 +3574,11 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri for (auto& fieldInst : summaryTypeInst->mFieldInstances) { auto fieldDef = fieldInst.GetFieldDef(); + if (fieldDef == NULL) + continue; + if (fieldInst.mResolvedType == NULL) + continue; + if (!fieldDef->mIsStatic) { if (formatInfo.mTotalSummaryLength + retVal.length() + bigRet.length() > 255) @@ -3337,12 +3706,21 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri } retVal += displayString; - retVal += "\n" + module->TypeToString(displayType); + retVal += "\n" + TypeToString(origTypedValue.mType, typeModKind); + + BfType* memberListType = displayType; if ((actualType != NULL) && (actualType != displayType)) { - String actualTypeName = module->TypeToString(actualType); - retVal += StrFormat(" {%s}\n[%s]\tthis,this=%d@0x%X", actualTypeName.c_str(), actualTypeName.c_str(), actualType->mTypeId, addr); + if (displayType == module->mContext->mBfObjectType) + { + memberListType = actualType; + } + else + { + String actualTypeName = module->TypeToString(actualType); + retVal += StrFormat(" {%s}\n[%s]\tthis,this=%d@0x%X", actualTypeName.c_str(), actualTypeName.c_str(), actualType->mTypeId, addr); + } } if (formatInfo.mNoMembers) @@ -3351,21 +3729,21 @@ String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const Stri } else if (wantsCustomExpandedItems) { - HandleCustomExpandedItems(retVal, debugVis, typedValue, addr, dataAddr, dbgVisWildcardCaptures, formatInfo); + HandleCustomExpandedItems(retVal, debugVis, summaryTypedValue, addr, dataAddr, dbgVisWildcardCaptures, formatInfo); } else if ((!isNull) && (!isBadSrc)) { - retVal += "\n" + GetMemberList(displayType, addr, dataAddr, false); + retVal += "\n" + GetMemberList(memberListType, addr, dataAddr, false); } - if (typedValue.mType->IsObjectOrInterface()) + if ((origTypedValue.mType->IsObjectOrInterface()) || (origTypedValue.mType->IsPointer())) { retVal += "\n:editVal\t" + EncodeDataPtr((uint32)dataAddr, true); } return retVal; } - return "!unknown type"; + return "!Failed to display value"; } void CeDebugger::HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* debugVis, BfTypedValue typedValue, addr_ce addr, addr_ce addrInst, Array& dbgVisWildcardCaptures, CeFormatInfo& formatInfo) @@ -3592,12 +3970,14 @@ void CeDebugger::HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* size = (int)ValueToInt(sizeValue); } + auto ceEndPointerVal = GetAddr(endPointer); + BfTypedValue curNode = headPointer; Array parentList; String continuationData; int totalSize = 2; - String addrs; //TODO: = GetLinkedListItems(debugVis, endPointer.mPtr, valueType, curNode, totalSize, &continuationData); + String addrs = GetLinkedListItems(debugVis, (addr_ce)ceEndPointerVal.mAddr, valueType, curNode, totalSize, &continuationData); String firstAddr; String secondAddr; bool hasSecondAddr = valueType == NULL; @@ -3666,7 +4046,7 @@ void CeDebugger::HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* int getItemCount = (int)BF_MIN(ValueToInt(sizeValue), 32LL); - String addrs; //TODO: = GetTreeItems(dbgCompileUnit, debugVis, parentList, valueType, curNode, getItemCount, &continuationData); + String addrs = GetTreeItems(debugVis, parentList, valueType, curNode, getItemCount, &continuationData); addr_ce firstAddr = 0; addr_ce secondAddr = 0; bool hasSecondAddr = valueType == NULL; @@ -3730,7 +4110,7 @@ void CeDebugger::HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* BfType* useTypedValType = typedValue.mType; - String addrs; //TODO: = GetDictionaryItems(debugVis, useTypedValue, 0, -1, getItemCount, &continuationData); + String addrs = GetDictionaryItems(debugVis, typedValue, 0, -1, getItemCount, &continuationData); addr_ce firstAddr = 0; if (addrs.length() > 0) { @@ -3738,7 +4118,7 @@ void CeDebugger::HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* firstAddr = DecodeTargetDataPtr(addrsPtr); } - String evalStr = "((comptype(" + StrFormat("%d", valueType->mTypeId) + "))0x{1}), na"; + String evalStr = "((comptype(" + StrFormat("%d", valueType->mTypeId) + "))(void*)0x{1}), na"; evalStr += ", refid=\"" + referenceId + ".[]\""; if (isReadOnly) @@ -3769,7 +4149,18 @@ String CeDebugger::Evaluate(const StringImpl& expr, int callStackIdx, int cursor String CeDebugger::EvaluateContinue() { - return String(); + AutoCrit autoCrit(mDebugManager->mCritSect); + + if (mDebugPendingExpr == NULL) + return ""; + + if (!mDebugPendingExpr->mDone) + return "!pending"; + + String result = mDebugPendingExpr->mResult; + delete mDebugPendingExpr; + mDebugPendingExpr = NULL; + return result; } void CeDebugger::EvaluateContinueKeep() @@ -3793,17 +4184,32 @@ String CeDebugger::GetAutoExpressions(int callStackIdx, uint64 memoryRangeStart, String CeDebugger::GetAutoLocals(int callStackIdx, bool showRegs) { + AutoCrit autoCrit(mDebugManager->mCritSect); + + if (!mCeMachine->mDbgPaused) + return ""; + String result; auto ceFrame = GetFrame(callStackIdx); + + int scopeIdx = -1; + auto ceEntry = ceFrame->mFunction->FindEmitEntry(ceFrame->GetInstIdx()); + if (ceEntry != NULL) + scopeIdx = ceEntry->mScope; + if (ceFrame != NULL) { + int instIdx = ceFrame->GetInstIdx(); if (ceFrame->mFunction->mDbgInfo != NULL) { for (auto& dbgVar : ceFrame->mFunction->mDbgInfo->mVariables) - { - result += dbgVar.mName; - result += "\n"; + { + if ((dbgVar.mScope == scopeIdx) && (instIdx >= dbgVar.mStartCodePos) && (instIdx < dbgVar.mEndCodePos)) + { + result += dbgVar.mName; + result += "\n"; + } } } } @@ -3867,23 +4273,61 @@ bool CeDebugger::IsActiveThreadWaiting() void CeDebugger::ClearCallStack() { + AutoCrit autoCrit(mCeMachine->mCritSect); + mDbgCallStack.Clear(); } void CeDebugger::UpdateCallStack(bool slowEarlyOut) { + AutoCrit autoCrit(mCeMachine->mCritSect); + + if (!mDbgCallStack.IsEmpty()) + return; + + auto ceContext = mCeMachine->mCurContext; + for (int frameIdx = ceContext->mCallStack.mSize - 1; frameIdx >= 0; frameIdx--) + { + auto ceFrame = &ceContext->mCallStack[frameIdx]; + + auto instIdx = ceFrame->GetInstIdx(); + auto emitEntry = ceFrame->mFunction->FindEmitEntry(instIdx); + if (emitEntry == NULL) + continue; + + int scopeIdx = emitEntry->mScope; + int prevInlineIdx = -1; + while (scopeIdx != -1) + { + CeDbgStackInfo ceDbgStackInfo; + ceDbgStackInfo.mFrameIdx = frameIdx; + ceDbgStackInfo.mScopeIdx = scopeIdx; + ceDbgStackInfo.mInlinedFrom = prevInlineIdx; + mDbgCallStack.Add(ceDbgStackInfo); + + auto ceScope = &ceFrame->mFunction->mDbgScopes[scopeIdx]; + if (ceScope->mInlinedAt == -1) + break; + auto inlineInfo = &ceFrame->mFunction->mDbgInlineTable[ceScope->mInlinedAt]; + scopeIdx = inlineInfo->mScope; + prevInlineIdx = ceScope->mInlinedAt; + } + } } int CeDebugger::GetCallStackCount() { - auto ceContext = mCeMachine->mCurContext; - if (ceContext == NULL) + AutoCrit autoCrit(mCeMachine->mCritSect); + + if (!mCeMachine->mDbgPaused) return 0; - return ceContext->mCallStack.mSize; + + UpdateCallStack(); + return mDbgCallStack.mSize; } int CeDebugger::GetRequestedStackFrameIdx() { - return 0; + return mPendingActiveFrameOffset; } int CeDebugger::GetBreakStackFrameIdx() @@ -3934,10 +4378,15 @@ void CeDebugger::GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, i void CeDebugger::GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx) { + AutoCrit autoCrit(mDebugManager->mCritSect); + *outThreadId = 0; if (outStackIdx != NULL) *outStackIdx = -1; + if (!mCeMachine->mDbgPaused) + return; + auto ceContext = mCeMachine->mCurContext; for (int i = 0; i < (int)ceContext->mCallStack.mSize; i++) { @@ -3952,6 +4401,13 @@ void CeDebugger::GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackI String CeDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* outFile, int32* outHotIdx, int32* outDefLineStart, int32* outDefLineEnd, int32* outLine, int32* outColumn, int32* outLanguage, int32* outStackSize, int8* outFlags) { + AutoCrit autoCrit(mDebugManager->mCritSect); + + if (!mCeMachine->mDbgPaused) + return ""; + + UpdateCallStack(); + enum FrameFlags { FrameFlags_Optimized = 1, @@ -3961,7 +4417,7 @@ String CeDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* ou FrameFlags_HadError = 0x10 }; - auto ceContext = mCeMachine->mCurContext; + auto ceContext = mCeMachine->mCurContext; *addr = 0; *outFile = ""; @@ -3974,50 +4430,96 @@ String CeDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* ou *outStackSize = 0; *outFlags = 0; - if (stackFrameIdx < ceContext->mCallStack.mSize) - { - int stackIdx = ceContext->mCallStack.mSize - stackFrameIdx - 1; - auto ceFrame = &ceContext->mCallStack[stackIdx]; - auto ceFunction = ceFrame->mFunction; + if (ceContext == NULL) + return ""; - if (ceFunction->mFailed) - *outFlags |= FrameFlags_HadError; + auto& dbgCallstackInfo = mDbgCallStack[stackFrameIdx]; + + auto ceFrame = &ceContext->mCallStack[dbgCallstackInfo.mFrameIdx]; + auto ceFunction = ceFrame->mFunction; - int instIdx = (int)(ceFrame->mInstPtr - &ceFunction->mCode[0] - 2); + if (ceFunction->mFailed) + *outFlags |= FrameFlags_HadError; - BF_ASSERT(ceFunction->mId != -1); - *addr = ((intptr)ceFunction->mId << 32) | instIdx; + int instIdx = (int)(ceFrame->mInstPtr - &ceFunction->mCode[0] - 2); - CeEmitEntry* emitEntry = ceFunction->FindEmitEntry(instIdx); + BF_ASSERT(ceFunction->mId != -1); + *addr = ((intptr)ceFunction->mId << 32) | instIdx; + + CeEmitEntry* emitEntry = ceFunction->FindEmitEntry(instIdx); - if (stackIdx > 0) + if (stackFrameIdx < mDbgCallStack.mSize - 1) + { + auto& nextStackInfo = mDbgCallStack[stackFrameIdx + 1]; + auto prevFrame = &ceContext->mCallStack[nextStackInfo.mFrameIdx]; + *outStackSize = prevFrame->mStackAddr - ceFrame->mStackAddr; + } + else + { + *outStackSize = ceContext->mStackSize - ceFrame->mStackAddr; + } + + CeDbgScope* ceScope = NULL; + if (dbgCallstackInfo.mScopeIdx != -1) + ceScope = &ceFunction->mDbgScopes[dbgCallstackInfo.mScopeIdx]; + + if (emitEntry != NULL) + { + if (emitEntry->mScope != -1) + *outFile = ceFunction->mDbgScopes[emitEntry->mScope].mFilePath; + *outLine = emitEntry->mLine; + *outColumn = emitEntry->mColumn; + } + + if (dbgCallstackInfo.mInlinedFrom != -1) + { + auto dbgInlineInfo = &ceFunction->mDbgInlineTable[dbgCallstackInfo.mInlinedFrom]; + *outLine = dbgInlineInfo->mLine; + *outColumn = dbgInlineInfo->mColumn; + } + + if ((ceScope != NULL) && (ceScope->mMethodVal != -1)) + { + if ((ceScope->mMethodVal & CeDbgScope::MethodValFlag_MethodRef) != 0) { - auto prevFrame = &ceContext->mCallStack[stackIdx - 1]; - *outStackSize = prevFrame->mStackAddr - ceFrame->mStackAddr; + auto dbgMethodRef = &ceFunction->mDbgMethodRefTable[ceScope->mMethodVal & CeDbgScope::MethodValFlag_IdxMask]; + return dbgMethodRef->ToString(); } else { - *outStackSize = ceContext->mStackSize - ceFrame->mStackAddr; + auto callTableEntry = &ceFunction->mCallTable[ceScope->mMethodVal]; + return ceContext->mCurModule->MethodToString(callTableEntry->mFunctionInfo->mMethodInstance); } + } - if (emitEntry != NULL) - { - if (emitEntry->mScope != -1) - *outFile = ceFunction->mDbgScopes[emitEntry->mScope].mFilePath; - *outLine = emitEntry->mLine; - *outColumn = emitEntry->mColumn; - } - - return ceContext->mCurModule->MethodToString(ceFrame->mFunction->mMethodInstance); - } - - return "?"; + return ceContext->mCurModule->MethodToString(ceFrame->mFunction->mMethodInstance); } BfType* CeDebugger::FindType(const StringImpl& name) -{ - //TODO: - return NULL; +{ + if (name == "System.Object") + return mCeMachine->mCeModule->mContext->mBfObjectType; + + BfParser parser(mCompiler->mSystem); + BfPassInstance passInstance(mCompiler->mSystem); + parser.SetSource(name.c_str(), (int)name.length()); + parser.Parse(&passInstance); + + BfReducer reducer; + reducer.mAlloc = parser.mAlloc; + reducer.mSystem = mCompiler->mSystem; + reducer.mPassInstance = &passInstance; + reducer.mVisitorPos = BfReducer::BfVisitorPos(parser.mRootNode); + reducer.mVisitorPos.MoveNext(); + reducer.mSource = &parser; + auto typeRef = reducer.CreateTypeRef(parser.mRootNode->GetFirst()); + parser.Close(); + + auto ceModule = mCeMachine->mCeModule; + SetAndRestoreValue prevIgnoreErrors(ceModule->mIgnoreErrors, true); + SetAndRestoreValue prevIgnoreWarning(ceModule->mIgnoreWarnings, true); + + return ceModule->ResolveTypeRef(typeRef, {}, BfPopulateType_Declaration, BfResolveTypeRefFlag_IgnoreLookupError); } String CeDebugger::Callstack_GetStackFrameOldFileInfo(int stackFrameIdx) @@ -4029,6 +4531,11 @@ String CeDebugger::Callstack_GetStackFrameOldFileInfo(int stackFrameIdx) int CeDebugger::GetJmpState(int stackFrameIdx) { + AutoCrit autoCrit(mDebugManager->mCritSect); + + if (!mCeMachine->mDbgPaused) + return -1; + if (stackFrameIdx != 0) return -1; @@ -4091,6 +4598,11 @@ String CeDebugger::DisassembleAtRaw(intptr address) String CeDebugger::DisassembleAt(intptr address) { + AutoCrit autoCrit(mDebugManager->mCritSect); + + if (!mCeMachine->mDbgPaused) + return ""; + auto ceContext = mCeMachine->mCurContext; mCurDisasmFuncId = (int)(address >> 32); @@ -4115,6 +4627,8 @@ String CeDebugger::DisassembleAt(intptr address) CeEmitEntry* prevEmitEntry = NULL; CeEmitEntry* curEmitEntry = NULL; + String prevSourcePath; + while (dumpCtx.mPtr < dumpCtx.mEnd) { int ofs = (int)(dumpCtx.mPtr - start); @@ -4128,12 +4642,19 @@ String CeDebugger::DisassembleAt(intptr address) { if ((curEmitEntry != NULL) && (curEmitEntry->mLine != -1)) { + bool pathChanged = false; if ((prevEmitEntry == NULL) || (curEmitEntry->mScope != prevEmitEntry->mScope)) { - dumpCtx.mStr += StrFormat("S %s\n", ceFunction->mDbgScopes[curEmitEntry->mScope].mFilePath.c_str()); + auto ceDbgScope = &ceFunction->mDbgScopes[curEmitEntry->mScope]; + if (ceDbgScope->mFilePath != prevSourcePath) + { + pathChanged = true; + dumpCtx.mStr += StrFormat("S %s\n", ceDbgScope->mFilePath.c_str()); + prevSourcePath = ceDbgScope->mFilePath; + } } - if ((prevEmitEntry != NULL) && (curEmitEntry->mScope == prevEmitEntry->mScope)) + if ((prevEmitEntry != NULL) && (!pathChanged) && (curEmitEntry->mLine >= prevEmitEntry->mLine)) { dumpCtx.mStr += StrFormat("L %d %d\n", prevEmitEntry->mLine + 1, curEmitEntry->mLine - prevEmitEntry->mLine); } @@ -4217,6 +4738,7 @@ void CeDebugger::Terminate() void CeDebugger::Detach() { mRunState = RunState_Terminated; + mDbgCallStack.Clear(); } Profiler* CeDebugger::StartProfiling() diff --git a/IDEHelper/Compiler/CeDebugger.h b/IDEHelper/Compiler/CeDebugger.h index d57caee6..b0361c0c 100644 --- a/IDEHelper/Compiler/CeDebugger.h +++ b/IDEHelper/Compiler/CeDebugger.h @@ -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 mBreakpoints; - Dictionary mFileInfo; + Dictionary mFileInfo; Dictionary mDbgTypeInfoMap; + Array mDbgCallStack; CeEvaluationContext* mCurEvaluationContext; CeBreakpoint* mActiveBreakpoint; @@ -221,11 +255,23 @@ public: bool mBreakpointCacheDirty; bool mBreakpointFramesDirty; int mCurDisasmFuncId; + int mPendingActiveFrameOffset; public: + template 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& parentList, BfType*& valueType, BfTypedValue& curNode, int count, String* outContinuationData); bool EvalCondition(DebugVisualizerEntry* debugVis, BfTypedValue typedVal, CeFormatInfo& formatInfo, const StringImpl& condition, const Array& 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& 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); diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index a65f8787..f5d812b7 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -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 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(mdNode)) + mdNode = dbgLexicalBlock->mScope; + + if (dbgFunc = BeValueDynCast(mdNode)) + { + dbgFile = dbgFunc->mFile; + } + else if (auto dbgLoc = BeValueDynCast(mdNode)) + dbgFile = dbgLoc->GetDbgFile(); + else + dbgFile = BeValueDynCast(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 _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(castedInst->mDbgVar->mType)) + bool isConst = false; + + auto beType = castedInst->mDbgVar->mType; + if (auto dbgConstType = BeValueDynCast(beType)) { - CeDbgVariable dbgVariable; + isConst = true; + beType = dbgConstType->mElement; + } + + if (auto dbgTypeId = BeValueDynCast(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 prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, contextTypeInstance); - SetAndRestoreValue 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 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; } diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index f39a2e82..31e5de91 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -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 mCode; Array mDbgScopes; - Array mEmitTable; - Array mCallTable; + Array mDbgInlineTable; + Array mDbgMethodRefTable; + Array mEmitTable; + Array mCallTable; Array mStringTable; Array mConstStructTable; Array 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 mJumpTable; Dictionary mValueToOperand; int mFrameSize; - Dictionary mDbgFileMap; + Dictionary mDbgInlineMap; + Dictionary mDbgScopeMap; + Dictionary mDbgMethodRefMap; Dictionary mFunctionMap; Dictionary mStringMap; Dictionary mConstDataMap; Dictionary mInnerFunctionMap; Dictionary mStaticFieldMap; - Dictionary mStaticFieldInstanceMap; - + Dictionary mStaticFieldInstanceMap; + Dictionary mDbgVariableMap; + public: CeBuilder() { @@ -782,6 +847,9 @@ public: CeErrorKind EmitConst(Array& 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 mFunctionIdMap; // Only used for 32-bit and debugging Dictionary mTypeInfoMap; HashSet mMethodInstanceSet; - HashSet mFieldInstanceSet; - Array mFunctionList; + HashSet mFieldInstanceSet; Array 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()(key.mString) ^ (size_t)key.mKind; } }; + + template <> + struct hash + { + size_t operator()(const Beefy::CeDbgInlineLookup& key) const + { + return (intptr)key.mDbgFile ^ (intptr)key.mInlineAtIdx; + } + }; + + template <> + struct hash + { + size_t operator()(const Beefy::CeDbgMethodRef& key) const + { + return BeefHash()(key.mMethodRef) ^ BeefHash()(key.mNameMod); + } + }; } \ No newline at end of file diff --git a/IDEHelper/DbgExprEvaluator.cpp b/IDEHelper/DbgExprEvaluator.cpp index 3e58fca9..85a91787 100644 --- a/IDEHelper/DbgExprEvaluator.cpp +++ b/IDEHelper/DbgExprEvaluator.cpp @@ -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 { diff --git a/IDEHelper/DebugManager.cpp b/IDEHelper/DebugManager.cpp index 0ca03c8e..23f6ef27 100644 --- a/IDEHelper/DebugManager.cpp +++ b/IDEHelper/DebugManager.cpp @@ -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) diff --git a/IDEHelper/WinDebugger.h b/IDEHelper/WinDebugger.h index 29ef5767..e12f35a7 100644 --- a/IDEHelper/WinDebugger.h +++ b/IDEHelper/WinDebugger.h @@ -515,7 +515,7 @@ public: int SetProtection(intptr address, int size, int prot); void EnableMemCache(); void DisableMemCache(); - template T ReadMemory(intptr addr, bool local = false, bool* failed = NULL); + template T ReadMemory(intptr addr, bool local = false, bool* failed = NULL); bool WriteInstructions(intptr address, void* src, uint64 length); template bool WriteMemory(intptr addr, T val); virtual DbgMemoryFlags GetMemoryFlags(intptr address) override;