2
0
Brian Fiete 3 жил өмнө
parent
commit
ff2e40e3bf
40 өөрчлөгдсөн 6129 нэмэгдсэн , 435 устгасан
  1. 20 0
      BeefySysLib/util/Array.h
  2. 1 0
      IDE/src/Commands.bf
  3. 25 1
      IDE/src/Debugger/DebugManager.bf
  4. 50 3
      IDE/src/IDEApp.bf
  5. 1 0
      IDE/src/Settings.bf
  6. 105 53
      IDE/src/ui/DisassemblyPanel.bf
  7. 9 0
      IDE/src/ui/StatusBar.bf
  8. 16 11
      IDEHelper/Backend/BeCOFFObject.cpp
  9. 72 9
      IDEHelper/Backend/BeIRCodeGen.cpp
  10. 1 1
      IDEHelper/Backend/BeIRCodeGen.h
  11. 33 4
      IDEHelper/Backend/BeMCContext.cpp
  12. 34 4
      IDEHelper/Backend/BeModule.cpp
  13. 45 7
      IDEHelper/Backend/BeModule.h
  14. 5 0
      IDEHelper/Compiler/BfAst.h
  15. 8 0
      IDEHelper/Compiler/BfCompiler.cpp
  16. 163 19
      IDEHelper/Compiler/BfExprEvaluator.cpp
  17. 61 0
      IDEHelper/Compiler/BfIRBuilder.cpp
  18. 9 0
      IDEHelper/Compiler/BfIRBuilder.h
  19. 56 6
      IDEHelper/Compiler/BfModule.cpp
  20. 2 0
      IDEHelper/Compiler/BfModule.h
  21. 1 1
      IDEHelper/Compiler/BfModuleTypeUtils.cpp
  22. 9 3
      IDEHelper/Compiler/BfParser.cpp
  23. 1 1
      IDEHelper/Compiler/BfParser.h
  24. 4 0
      IDEHelper/Compiler/BfResolvedTypeUtils.cpp
  25. 1 1
      IDEHelper/Compiler/BfStmtEvaluator.cpp
  26. 8 0
      IDEHelper/Compiler/BfUtil.cpp
  27. 1 0
      IDEHelper/Compiler/BfUtil.h
  28. 4239 0
      IDEHelper/Compiler/CeDebugger.cpp
  29. 357 0
      IDEHelper/Compiler/CeDebugger.h
  30. 546 199
      IDEHelper/Compiler/CeMachine.cpp
  31. 160 52
      IDEHelper/Compiler/CeMachine.h
  32. 1 1
      IDEHelper/DbgExprEvaluator.cpp
  33. 43 0
      IDEHelper/DbgExprEvaluator.h
  34. 17 4
      IDEHelper/DebugManager.cpp
  35. 1 1
      IDEHelper/DebugManager.h
  36. 9 1
      IDEHelper/Debugger.h
  37. 2 0
      IDEHelper/IDEHelper.vcxproj
  38. 6 0
      IDEHelper/IDEHelper.vcxproj.filters
  39. 4 3
      IDEHelper/WinDebugger.cpp
  40. 3 50
      IDEHelper/WinDebugger.h

+ 20 - 0
BeefySysLib/util/Array.h

@@ -1080,6 +1080,26 @@ public:
 			return NULL;
 			return NULL;
 		return &this->mVals[this->mSize - addSize];
 		return &this->mVals[this->mSize - addSize];
 	}
 	}
+
+	template <typename TAlt>
+	int BinarySearchAlt(const TAlt& val, const std::function<int(const T& lhs, const TAlt& rhs)>& func)
+	{
+		int lo = 0;
+		int hi = this->mSize - 1;
+
+		while (lo <= hi)
+		{
+			int i = (lo + hi) / 2;
+			const T& midVal = this->mVals[i];
+			int c = func(midVal, val);
+			if (c == 0) return i;
+			if (c < 0)
+				lo = i + 1;
+			else
+				hi = i - 1;
+		}
+		return ~lo;
+	}
 };
 };
 
 
 template <typename T, typename TAlloc = AllocatorCLib<T> >
 template <typename T, typename TAlloc = AllocatorCLib<T> >

+ 1 - 0
IDE/src/Commands.bf

@@ -225,6 +225,7 @@ namespace IDE
 			Add("Comment Toggle", new => gApp.[Friend]CommentToggle, .Editor);
 			Add("Comment Toggle", new => gApp.[Friend]CommentToggle, .Editor);
 			Add("Compile File", new => gApp.Cmd_CompileFile);
 			Add("Compile File", new => gApp.Cmd_CompileFile);
 			Add("Debug All Tests", new () => { gApp.[Friend]RunTests(true, true); });
 			Add("Debug All Tests", new () => { gApp.[Friend]RunTests(true, true); });
+			Add("Debug Comptime", new => gApp.DebugComptime);
 			Add("Debug Normal Tests", new () => { gApp.[Friend]RunTests(false, true); });
 			Add("Debug Normal Tests", new () => { gApp.[Friend]RunTests(false, true); });
 			Add("Delete All Right", new => gApp.[Friend]DeleteAllRight);
 			Add("Delete All Right", new => gApp.[Friend]DeleteAllRight);
 			Add("Duplicate Line", new () => { gApp.[Friend]DuplicateLine(); });
 			Add("Duplicate Line", new () => { gApp.[Friend]DuplicateLine(); });

+ 25 - 1
IDE/src/Debugger/DebugManager.bf

@@ -5,6 +5,7 @@ using System.Threading.Tasks;
 using System.Diagnostics;
 using System.Diagnostics;
 using Beefy.utils;
 using Beefy.utils;
 using IDE.util;
 using IDE.util;
+using IDE.Compiler;
 
 
 namespace IDE.Debugger
 namespace IDE.Debugger
 {
 {
@@ -80,7 +81,8 @@ namespace IDE.Debugger
 			Optimized = 1,
 			Optimized = 1,
 			HasPendingDebugInfo = 2,
 			HasPendingDebugInfo = 2,
 			CanLoadOldVersion = 4,
 			CanLoadOldVersion = 4,
-			WasHotReplaced = 8
+			WasHotReplaced = 8,
+			HadError = 0x10
 		}
 		}
 
 
 		//[Flags]
 		//[Flags]
@@ -142,6 +144,9 @@ namespace IDE.Debugger
 		[CallingConvention(.Stdcall),CLink]
 		[CallingConvention(.Stdcall),CLink]
 		static extern bool Debugger_OpenFile(char8* launchPath, char8* targetPath, char8* args, char8* workingDir, void* envBlockPtr, int32 envBlockLen, bool hotSwapEnabled);
 		static extern bool Debugger_OpenFile(char8* launchPath, char8* targetPath, char8* args, char8* workingDir, void* envBlockPtr, int32 envBlockLen, bool hotSwapEnabled);
 
 
+		[CallingConvention(.Stdcall),CLink]
+		static extern bool Debugger_ComptimeAttach(void* bfCompiler);
+
 		[CallingConvention(.Stdcall),CLink]
 		[CallingConvention(.Stdcall),CLink]
 		static extern bool Debugger_Attach(int32 processId, AttachFlags attachFlags);
 		static extern bool Debugger_Attach(int32 processId, AttachFlags attachFlags);
 
 
@@ -371,6 +376,7 @@ namespace IDE.Debugger
 		public bool mIsRunning;
 		public bool mIsRunning;
 		public bool mIsRunningCompiled;
 		public bool mIsRunningCompiled;
 		public bool mIsRunningWithHotSwap;
 		public bool mIsRunningWithHotSwap;
+		public bool mIsComptimeDebug;
 		//public RunState mLastUpdatedRunState;
 		//public RunState mLastUpdatedRunState;
 		public bool mCallStackDirty;
 		public bool mCallStackDirty;
 		public int32 mActiveCallStackIdx;
 		public int32 mActiveCallStackIdx;
@@ -427,11 +433,21 @@ namespace IDE.Debugger
 			DeleteAndNullify!(mRunningPath);
 			DeleteAndNullify!(mRunningPath);
 			mRunningPath = new String(launchPath);
 			mRunningPath = new String(launchPath);
 
 
+			mIsComptimeDebug = false;
 			mIsRunningCompiled = isCompiled;
 			mIsRunningCompiled = isCompiled;
 			mIsRunningWithHotSwap = hotSwapEnabled;
 			mIsRunningWithHotSwap = hotSwapEnabled;
 			return Debugger_OpenFile(launchPath, targetPath, args, workingDir, envBlock.Ptr, (int32)envBlock.Length, hotSwapEnabled);
 			return Debugger_OpenFile(launchPath, targetPath, args, workingDir, envBlock.Ptr, (int32)envBlock.Length, hotSwapEnabled);
 		}
 		}
 
 
+		public bool ComptimeAttach(BfCompiler compiler)
+		{
+			mIsComptimeDebug = true;
+			mIsRunningCompiled = false;
+			mIsRunningWithHotSwap = false;
+			mIsRunning = true;
+			return Debugger_ComptimeAttach(compiler.mNativeBfCompiler);
+		}
+
 		public void SetSymSrvOptions(String symCacheDir, String symSrvStr, SymSrvFlags symSrvFlags)
 		public void SetSymSrvOptions(String symCacheDir, String symSrvStr, SymSrvFlags symSrvFlags)
 		{
 		{
 			Debugger_SetSymSrvOptions(symCacheDir, symSrvStr, (int32)symSrvFlags);
 			Debugger_SetSymSrvOptions(symCacheDir, symSrvStr, (int32)symSrvFlags);
@@ -439,7 +455,9 @@ namespace IDE.Debugger
 
 
 		public bool OpenMiniDump(String file)
 		public bool OpenMiniDump(String file)
 		{
 		{
+			mIsComptimeDebug = false;
 			mIsRunningCompiled = false;
 			mIsRunningCompiled = false;
+			mIsRunningWithHotSwap = false;
 			return Debugger_OpenMiniDump(file);
 			return Debugger_OpenMiniDump(file);
 		}
 		}
 
 
@@ -482,6 +500,9 @@ namespace IDE.Debugger
 				if (breakpoint.mThreadId != -1)
 				if (breakpoint.mThreadId != -1)
 					breakpoint.mThreadId = 0;
 					breakpoint.mThreadId = 0;
 			}
 			}
+
+			mIsComptimeDebug = false;
+			mIsRunning = false;
 		}
 		}
 
 
 		public RunState GetRunState()
 		public RunState GetRunState()
@@ -1083,6 +1104,9 @@ namespace IDE.Debugger
 
 
 		public bool Attach(Process process, AttachFlags attachFlags)
 		public bool Attach(Process process, AttachFlags attachFlags)
 		{
 		{
+			mIsRunningCompiled = false;
+			mIsComptimeDebug = false;
+			mIsRunningWithHotSwap = false;
 			return Debugger_Attach(process.Id, attachFlags);
 			return Debugger_Attach(process.Id, attachFlags);
 		}
 		}
 
 

+ 50 - 3
IDE/src/IDEApp.bf

@@ -862,7 +862,8 @@ namespace IDE
 			let sourceViewPanel = GetActiveSourceViewPanel();
 			let sourceViewPanel = GetActiveSourceViewPanel();
 			if (sourceViewPanel != null)
 			if (sourceViewPanel != null)
 			{
 			{
-				Path.GetDirectoryPath(sourceViewPanel.mFilePath, fullDir);
+				if (sourceViewPanel.mFilePath != null)
+					Path.GetDirectoryPath(sourceViewPanel.mFilePath, fullDir);
 			}
 			}
 			else if ((gApp.mDebugger.mRunningPath != null) && (!mWorkspace.IsInitialized))
 			else if ((gApp.mDebugger.mRunningPath != null) && (!mWorkspace.IsInitialized))
 			{
 			{
@@ -4342,7 +4343,10 @@ namespace IDE
 			    if (mExecutionQueue.Count == 0)
 			    if (mExecutionQueue.Count == 0)
 			    {
 			    {
 			        mOutputPanel.Clear();
 			        mOutputPanel.Clear();
-			        OutputLine("Compiling...");
+					if (mDebugger?.mIsComptimeDebug == true)
+			        	OutputLine("Compiling with comptime debugging...");
+					else
+						OutputLine("Compiling...");
 			        Compile(.Normal, null);
 			        Compile(.Normal, null);
 			    }
 			    }
 			}
 			}
@@ -4447,6 +4451,24 @@ namespace IDE
 			}
 			}
 		}
 		}
 
 
+		[IDECommand]
+		public void DebugComptime()
+		{
+			if (mDebugger.mIsRunning)
+				return;
+
+			if (IsCompiling)
+				return;
+
+			CheckDebugVisualizers();
+			mTargetDidInitBreak = true;
+			mTargetStartWithStep = false;
+			mDebugger.ComptimeAttach(mBfBuildCompiler);
+			mDebugger.RehupBreakpoints(true);
+			mBfBuildCompiler.ForceRebuild();
+			Compile();
+		}
+
 		[IDECommand]
 		[IDECommand]
 		void RunWithoutCompiling()
 		void RunWithoutCompiling()
 		{
 		{
@@ -5622,6 +5644,7 @@ namespace IDE
 
 
             subMenu = root.AddMenuItem("&Build");
             subMenu = root.AddMenuItem("&Build");
 			AddMenuItem(subMenu, "&Build Workspace", "Build Workspace", new => UpdateMenuItem_HasWorkspace);
 			AddMenuItem(subMenu, "&Build Workspace", "Build Workspace", new => UpdateMenuItem_HasWorkspace);
+			AddMenuItem(subMenu, "&Debug Comptime", "Debug Comptime", new => UpdateMenuItem_HasWorkspace);
             AddMenuItem(subMenu, "&Clean", "Clean", new => UpdateMenuItem_DebugStopped_HasWorkspace);
             AddMenuItem(subMenu, "&Clean", "Clean", new => UpdateMenuItem_DebugStopped_HasWorkspace);
             AddMenuItem(subMenu, "Clean Beef", "Clean Beef", new => UpdateMenuItem_DebugStopped_HasWorkspace);
             AddMenuItem(subMenu, "Clean Beef", "Clean Beef", new => UpdateMenuItem_DebugStopped_HasWorkspace);
 			//subMenu.AddMenuItem("Compile Current File", null, new (menu) => { CompileCurrentFile(); });
 			//subMenu.AddMenuItem("Compile Current File", null, new (menu) => { CompileCurrentFile(); });
@@ -7211,7 +7234,7 @@ namespace IDE
 						// No 'wrong hash' warnings
 						// No 'wrong hash' warnings
 					}
 					}
 					else if (((hash != .None) && (sourceViewPanel.mEditData != null) && (!sourceViewPanel.mEditData.CheckHash(hash))) ||
 					else if (((hash != .None) && (sourceViewPanel.mEditData != null) && (!sourceViewPanel.mEditData.CheckHash(hash))) ||
-						(sourceViewPanel.mHasChangedSinceLastCompile))
+						(sourceViewPanel.mHasChangedSinceLastCompile) && (mDebugger?.mIsComptimeDebug != true))
 					{
 					{
 						sourceViewPanel.ShowWrongHash();
 						sourceViewPanel.ShowWrongHash();
 					}
 					}
@@ -7695,6 +7718,11 @@ namespace IDE
 
 
         void SysKeyDown(KeyDownEvent evt)
         void SysKeyDown(KeyDownEvent evt)
         {
         {
+			if (evt.mKeyCode != .Alt)
+			{
+				NOP!();
+			}
+
 			if (evt.mHandled)
 			if (evt.mHandled)
 				return;
 				return;
 
 
@@ -8723,6 +8751,9 @@ namespace IDE
 					if ((mVerbosity >= .Detailed) && (buildCompletedCmd.mStopwatch != null))
 					if ((mVerbosity >= .Detailed) && (buildCompletedCmd.mStopwatch != null))
                     	OutputLine("Total build time: {0:0.00}s", buildCompletedCmd.mStopwatch.ElapsedMilliseconds / 1000.0f);
                     	OutputLine("Total build time: {0:0.00}s", buildCompletedCmd.mStopwatch.ElapsedMilliseconds / 1000.0f);
 
 
+					if (mDebugger?.mIsComptimeDebug == true)
+						DebuggerComptimeStop();
+
 					CompileDone(!buildCompletedCmd.mFailed);
 					CompileDone(!buildCompletedCmd.mFailed);
 
 
 					if (mTestManager != null)
 					if (mTestManager != null)
@@ -9427,6 +9458,9 @@ namespace IDE
 
 
 			bool needsComptime = bfCompiler.GetLastHadComptimeRebuilds();
 			bool needsComptime = bfCompiler.GetLastHadComptimeRebuilds();
 
 
+			if (mDebugger?.mIsComptimeDebug == true)
+				needsComptime = true;
+
 			if ((!workspaceOptions.mIncrementalBuild) && (!lastCompileHadMessages))
 			if ((!workspaceOptions.mIncrementalBuild) && (!lastCompileHadMessages))
 			{
 			{
 				tryQueueFiles = false;
 				tryQueueFiles = false;
@@ -10376,6 +10410,9 @@ namespace IDE
 			{
 			{
 				Beep(MessageBeepType.Error);
 				Beep(MessageBeepType.Error);
 			}
 			}
+
+			if (mDebugger?.mIsComptimeDebug == true)
+				DebuggerComptimeStop();
         }
         }
 
 
 		void DbgCopyChangedFiles(DateTime cmpTime, StringView srcDir, StringView destDir)
 		void DbgCopyChangedFiles(DateTime cmpTime, StringView srcDir, StringView destDir)
@@ -10767,6 +10804,9 @@ namespace IDE
 
 
 			if (mDebugger.mIsRunning)
 			if (mDebugger.mIsRunning)
 			{
 			{
+				if (mDebugger.mIsComptimeDebug)
+					CancelBuild();
+
 				mDebugger.StopDebugging();
 				mDebugger.StopDebugging();
 			}
 			}
 		}
 		}
@@ -12104,6 +12144,12 @@ namespace IDE
 			return .Normal;
 			return .Normal;
 		}
 		}
 
 
+		void DebuggerComptimeStop()
+		{
+			mDebugger.DisposeNativeBreakpoints();
+			mDebugger.Detach();
+		}
+
         void DebuggerPaused()
         void DebuggerPaused()
         {
         {
             mDebugger.mActiveCallStackIdx = 0;
             mDebugger.mActiveCallStackIdx = 0;
@@ -14027,6 +14073,7 @@ namespace IDE
         [Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
         [Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
         public static extern bool MessageBeep(MessageBeepType type);
         public static extern bool MessageBeep(MessageBeepType type);
 #endif
 #endif
+		
     }
     }
 
 
 	static
 	static

+ 1 - 0
IDE/src/Settings.bf

@@ -787,6 +787,7 @@ namespace IDE
 				Add("Comment Block", "Ctrl+K, Ctrl+C");
 				Add("Comment Block", "Ctrl+K, Ctrl+C");
 				Add("Comment Lines", "Ctrl+K, Ctrl+/");
 				Add("Comment Lines", "Ctrl+K, Ctrl+/");
 				Add("Comment Toggle", "Ctrl+K, Ctrl+T");
 				Add("Comment Toggle", "Ctrl+K, Ctrl+T");
+				Add("Debug Comptime", "Alt+F7");
 				Add("Duplicate Line", "Ctrl+D");
 				Add("Duplicate Line", "Ctrl+D");
 				Add("Find Class", "Alt+Shift+L");
 				Add("Find Class", "Alt+Shift+L");
 				Add("Find in Document", "Ctrl+F");
 				Add("Find in Document", "Ctrl+F");

+ 105 - 53
IDE/src/ui/DisassemblyPanel.bf

@@ -539,6 +539,7 @@ namespace IDE.ui
 			String sourceLineText = scope .(1024);
 			String sourceLineText = scope .(1024);
 
 
 			int32 maxLine = 0;
 			int32 maxLine = 0;
+			int addrOffset = 0;
 
 
 			for (var lineStrView in codeData.Split('\n'))
 			for (var lineStrView in codeData.Split('\n'))
 		    {
 		    {
@@ -557,6 +558,9 @@ namespace IDE.ui
 
 
 		        switch (line[0])
 		        switch (line[0])
 		        {
 		        {
+				case 'A':
+					addrOffset = (int)int64.Parse(StringView(line, 2), System.Globalization.NumberStyles.HexNumber);
+					continue;
 				case 'O':
 				case 'O':
 					isOptimized = true;
 					isOptimized = true;
 					addLineData = false;
 					addLineData = false;
@@ -612,7 +616,7 @@ namespace IDE.ui
 	                    //int ptrSize = 8;
 	                    //int ptrSize = 8;
 	                    var addrString = scope String(disasmLine, 0, parenPos);
 	                    var addrString = scope String(disasmLine, 0, parenPos);
 	                    addrString.Replace("'", "");
 	                    addrString.Replace("'", "");
-	                    lineData.mAddr = (int)int64.Parse(addrString, System.Globalization.NumberStyles.HexNumber);
+	                    lineData.mAddr = (int)int64.Parse(addrString, System.Globalization.NumberStyles.HexNumber) + addrOffset;
 	                    lineData.mAddrEnd = lineData.mAddr + 1;
 	                    lineData.mAddrEnd = lineData.mAddr + 1;
 
 
 	                    if (prevDisasmLineData != -1)
 	                    if (prevDisasmLineData != -1)
@@ -709,7 +713,7 @@ namespace IDE.ui
 	                    addLineData = false;
 	                    addLineData = false;
 	                    JumpEntry jumpEntry = new JumpEntry();
 	                    JumpEntry jumpEntry = new JumpEntry();
 	                    int64 addrFrom = (int64)mLineDatas[mLineDatas.Count - 1].mAddr;
 	                    int64 addrFrom = (int64)mLineDatas[mLineDatas.Count - 1].mAddr;
-	                    int64 addrTo = int64.Parse(scope String(line, 2), System.Globalization.NumberStyles.HexNumber);
+	                    int64 addrTo = int64.Parse(scope String(line, 2), System.Globalization.NumberStyles.HexNumber) + addrOffset;
 	                    jumpEntry.mAddrMin = (int)Math.Min(addrFrom, addrTo);
 	                    jumpEntry.mAddrMin = (int)Math.Min(addrFrom, addrTo);
 	                    jumpEntry.mAddrMax = (int)Math.Max(addrFrom, addrTo);
 	                    jumpEntry.mAddrMax = (int)Math.Max(addrFrom, addrTo);
 	                    jumpEntry.mIsReverse = jumpEntry.mAddrMin == (int)addrTo;
 	                    jumpEntry.mIsReverse = jumpEntry.mAddrMin == (int)addrTo;
@@ -1193,6 +1197,7 @@ namespace IDE.ui
 
 
                 int leftIdx = -1;
                 int leftIdx = -1;
                 int rightIdx = -1;
                 int rightIdx = -1;
+				int commaIdx = -1;
                 String debugExpr = null;
                 String debugExpr = null;
 
 
                 if ((cursorPos < content.mData.mTextLength) && (!((char8)content.mData.mText[cursorPos].mChar).IsWhiteSpace))
                 if ((cursorPos < content.mData.mTextLength) && (!((char8)content.mData.mText[cursorPos].mChar).IsWhiteSpace))
@@ -1208,59 +1213,94 @@ namespace IDE.ui
                         content.ExtractString(lineStart, lineEnd - lineStart, lineStr);
                         content.ExtractString(lineStart, lineEnd - lineStart, lineStr);
                         int strIdx = 0;
                         int strIdx = 0;
 
 
-                        int colonPos = -1;
-                        int instrStartIdx = -1;
-                        int instrEndIdx = -1;
-                        int firstParamIdx = -1;
-                        int commaIdx = -1;                        
+						bool isComptime = false;
+						for (int i in 0..<lineStr.Length-1)
+						{
+							if ((lineStr[i] == '[') && (lineStr[i+1] == 'F'))
+								isComptime = true;
+						}
 
 
-                        for (; strIdx < lineStr.Length; strIdx++)
-                        {
-                            char8 c = lineStr[strIdx];
-                            if (colonPos == -1)
-                            {
-                                if (c == ':')
-                                    colonPos = strIdx;
-                            }
-                            else if (instrStartIdx == -1)
-                            {
-                                if (c.IsLower)
-                                    instrStartIdx = strIdx;
-                            }
-                            else if (instrEndIdx == -1)
-                            {
-                                if (c.IsWhiteSpace)
-                                    instrEndIdx = strIdx;
-                            }
-                            else if (firstParamIdx == -1)
-                            {
-                                if (!c.IsWhiteSpace)
-                                    firstParamIdx = strIdx;
-                            }
-                            else if (commaIdx == -1)
-                            {
-                                if (c == ',')
-                                    commaIdx = strIdx;
-                            }
-                        }
+						if (isComptime)
+						{
+							int cursorStrIdx = cursorPos - lineStart;
+							if ((cursorStrIdx >= 0) && (cursorStrIdx < lineStr.Length))
+							{
+								leftIdx = cursorStrIdx;
+								rightIdx = cursorStrIdx;
 
 
-                        int cursorStrIdx = cursorPos - lineStart;
-                        if (cursorStrIdx > commaIdx)
-                        {
-                            if (commaIdx != -1)
-                                leftIdx = lineStart + commaIdx + 1;
-                            else
-                                leftIdx = lineStart + firstParamIdx;
-                            rightIdx = lineEnd - 1;
-                        }
-                        else if (cursorStrIdx >= firstParamIdx)
-                        {
-                            leftIdx = lineStart + firstParamIdx;
-                            if (commaIdx != -1)
-                                rightIdx = lineStart + commaIdx - 1;
-                            else
-                                rightIdx = lineEnd - 1;
-                        }
+								while (leftIdx > 0)
+								{
+									if (lineStr[leftIdx - 1].IsWhiteSpace)
+										break;
+									leftIdx--;
+								}
+
+								while (rightIdx < lineStr.Length - 1)
+								{
+									if (lineStr[rightIdx + 1].IsWhiteSpace)
+										break;
+									rightIdx++;
+								}
+
+								leftIdx += lineStart;
+								rightIdx += lineStart;
+							}
+						}
+						else
+						{
+	                        int colonPos = -1;
+	                        int instrStartIdx = -1;
+	                        int instrEndIdx = -1;
+	                        int firstParamIdx = -1;
+
+	                        for (; strIdx < lineStr.Length; strIdx++)
+	                        {
+	                            char8 c = lineStr[strIdx];
+	                            if (colonPos == -1)
+	                            {
+	                                if (c == ':')
+	                                    colonPos = strIdx;
+	                            }
+	                            else if (instrStartIdx == -1)
+	                            {
+	                                if (c.IsLower)
+	                                    instrStartIdx = strIdx;
+	                            }
+	                            else if (instrEndIdx == -1)
+	                            {
+	                                if (c.IsWhiteSpace)
+	                                    instrEndIdx = strIdx;
+	                            }
+	                            else if (firstParamIdx == -1)
+	                            {
+	                                if (!c.IsWhiteSpace)
+	                                    firstParamIdx = strIdx;
+	                            }
+	                            else if (commaIdx == -1)
+	                            {
+	                                if (c == ',')
+	                                    commaIdx = strIdx;
+	                            }
+	                        }
+
+	                        int cursorStrIdx = cursorPos - lineStart;
+	                        if (cursorStrIdx > commaIdx)
+	                        {
+	                            if (commaIdx != -1)
+	                                leftIdx = lineStart + commaIdx + 1;
+	                            else
+	                                leftIdx = lineStart + firstParamIdx;
+	                            rightIdx = lineEnd - 1;
+	                        }
+	                        else if (cursorStrIdx >= firstParamIdx)
+	                        {
+	                            leftIdx = lineStart + firstParamIdx;
+	                            if (commaIdx != -1)
+	                                rightIdx = lineStart + commaIdx - 1;
+	                            else
+	                                rightIdx = lineEnd - 1;
+	                        }
+						}
 
 
                         if (leftIdx != -1)
                         if (leftIdx != -1)
                         {
                         {
@@ -1273,6 +1313,11 @@ namespace IDE.ui
                             int32 semiPos = (int32)debugExpr.IndexOf(';');
                             int32 semiPos = (int32)debugExpr.IndexOf(';');
                             if (semiPos != -1)
                             if (semiPos != -1)
                                 debugExpr.RemoveToEnd(semiPos);
                                 debugExpr.RemoveToEnd(semiPos);
+							debugExpr.Trim();
+
+							int atPos = debugExpr.IndexOf('@');
+							if (atPos != -1)
+								debugExpr.RemoveToEnd(atPos);
 
 
                             debugExpr.Replace('[', '(');
                             debugExpr.Replace('[', '(');
                             debugExpr.Replace(']', ')');
                             debugExpr.Replace(']', ')');
@@ -1282,6 +1327,13 @@ namespace IDE.ui
                             debugExpr.Replace("word ptr", "(int16*)");
                             debugExpr.Replace("word ptr", "(int16*)");
                             debugExpr.Replace("byte ptr", "(int8*)");
                             debugExpr.Replace("byte ptr", "(int8*)");
 
 
+							if ((debugExpr.Contains('(')) && (debugExpr[0].IsLetter))
+							{
+							   int parenPos = debugExpr.IndexOf('(');
+								debugExpr.Insert(parenPos, "*)");
+								debugExpr.Insert(0, "*(");
+							}
+
                             if (line < mLineDatas.Count - 1)
                             if (line < mLineDatas.Count - 1)
                             {
                             {
                                 if (mLineDatas[line].mAddrEnd != (int)0)
                                 if (mLineDatas[line].mAddrEnd != (int)0)

+ 9 - 0
IDE/src/ui/StatusBar.bf

@@ -321,6 +321,11 @@ namespace IDE.ui
 
 
 			float statusLabelPos = (int)GS!(-1.3f);
 			float statusLabelPos = (int)GS!(-1.3f);
 
 
+			if ((gApp.mDebugger?.mIsComptimeDebug == true) && (gApp.mDebugger.IsPaused()))
+			{
+			   completionPct = null;
+			}
+
 			//completionPct = 0.4f;
 			//completionPct = 0.4f;
             if (completionPct.HasValue)
             if (completionPct.HasValue)
             {                
             {                
@@ -331,6 +336,10 @@ namespace IDE.ui
                 using (g.PushColor(0xFF00FF00))
                 using (g.PushColor(0xFF00FF00))
                     g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth * completionPct.Value, completionRect.mHeight);
                     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()))
             else if ((gApp.mDebugger.mIsRunning) && (gApp.HaveSourcesChanged()))
             {
             {
                 Rect completionRect = Rect(GS!(200), GS!(1), GS!(120), GS!(17));
                 Rect completionRect = Rect(GS!(200), GS!(1), GS!(120), GS!(17));

+ 16 - 11
IDEHelper/Backend/BeCOFFObject.cpp

@@ -475,9 +475,9 @@ void BeCOFFObject::DbgMakeFuncType(BeDbgFunction* dbgFunc)
 		if (hasThis)
 		if (hasThis)
 		{
 		{
 			if ((dbgFunc->mVariables.size() > 0) && (dbgFunc->mVariables[0] == NULL))
 			if ((dbgFunc->mVariables.size() > 0) && (dbgFunc->mVariables[0] == NULL))
-				outT.Write(DbgGetTypeId(dbgFunc->GetParamType(1))); // 0 is sret, 1 = this
+				outT.Write(DbgGetTypeId(BeValueDynCast<BeDbgType>(dbgFunc->GetParamType(1)))); // 0 is sret, 1 = this
 			else
 			else
-				outT.Write(DbgGetTypeId(dbgFunc->GetParamType(0))); // 0 = this
+				outT.Write(DbgGetTypeId(BeValueDynCast<BeDbgType>(dbgFunc->GetParamType(0)))); // 0 = this
 		}
 		}
 		else
 		else
 			outT.Write((int32)T_VOID);
 			outT.Write((int32)T_VOID);
@@ -941,7 +941,7 @@ int BeCOFFObject::DbgGetTypeId(BeDbgType* dbgType, bool doDefine)
 	{	
 	{	
 		CV_modifier_t attr = { 0 };		
 		CV_modifier_t attr = { 0 };		
 		attr.MOD_const = 1;
 		attr.MOD_const = 1;
-		int32 elementId = DbgGetTypeId(constType->mElement);
+		int32 elementId = DbgGetTypeId(BeValueDynCast<BeDbgType>(constType->mElement));
 
 
 		DbgTStartTag();
 		DbgTStartTag();
 		outT.Write((int16)LF_MODIFIER);		
 		outT.Write((int16)LF_MODIFIER);		
@@ -985,10 +985,10 @@ void BeCOFFObject::DbgGenerateTypeInfo()
 	auto& outT = mDebugTSect.mData;
 	auto& outT = mDebugTSect.mData;
 	outT.Write((int)CV_SIGNATURE_C13);
 	outT.Write((int)CV_SIGNATURE_C13);
 
 
-	for (auto dbgType : mBeModule->mDbgModule->mTypes)
+	for (auto mdNode : mBeModule->mDbgModule->mTypes)
 	{		
 	{		
 		bool defineType = true;
 		bool defineType = true;
-		if (auto dbgStructType = BeValueDynCast<BeDbgStructType>(dbgType))
+		if (auto dbgStructType = BeValueDynCast<BeDbgStructType>(mdNode))
 		{
 		{
 			if (!dbgStructType->mIsFullyDefined)
 			if (!dbgStructType->mIsFullyDefined)
 				defineType = false;			
 				defineType = false;			
@@ -996,7 +996,8 @@ void BeCOFFObject::DbgGenerateTypeInfo()
 
 
 		if (defineType)
 		if (defineType)
 		{
 		{
-			DbgGetTypeId(dbgType, true);
+			if (auto dbgType = BeValueDynCast<BeDbgType>(mdNode))
+				DbgGetTypeId(dbgType, true);
 		}
 		}
 	}
 	}
 
 
@@ -1032,6 +1033,8 @@ void BeCOFFObject::DbgStartVarDefRange(BeDbgFunction* dbgFunc, BeDbgVariable* db
 	
 	
 	auto funcSym = GetSymbol(dbgFunc->mValue);
 	auto funcSym = GetSymbol(dbgFunc->mValue);
 
 
+	auto varType = BeValueDynCast<BeDbgType>(dbgVar->mType);
+
 	auto& outS = mDebugSSect.mData;	
 	auto& outS = mDebugSSect.mData;	
 	if (varLoc.mKind == BeDbgVariableLoc::Kind_SymbolAddr)
 	if (varLoc.mKind == BeDbgVariableLoc::Kind_SymbolAddr)
 	{
 	{
@@ -1042,14 +1045,14 @@ void BeCOFFObject::DbgStartVarDefRange(BeDbgFunction* dbgFunc, BeDbgVariable* db
 		if (varLoc.mOfs == 0)
 		if (varLoc.mOfs == 0)
 		{
 		{
 			outS.Write((int16)S_DEFRANGE_REGISTER);
 			outS.Write((int16)S_DEFRANGE_REGISTER);
-			outS.Write((int16)GetCVRegNum(varLoc.mReg, dbgVar->mType->mSize * 8));
+			outS.Write((int16)GetCVRegNum(varLoc.mReg, varType->mSize * 8));
 			CV_RANGEATTR rangeAttr = { 0 };
 			CV_RANGEATTR rangeAttr = { 0 };
 			outS.Write(*(int16*)&rangeAttr); // offset to register
 			outS.Write(*(int16*)&rangeAttr); // offset to register
 		}
 		}
 		else
 		else
 		{
 		{
 			outS.Write((int16)S_DEFRANGE_REGISTER_REL);
 			outS.Write((int16)S_DEFRANGE_REGISTER_REL);
-			outS.Write((int16)GetCVRegNum(varLoc.mReg, dbgVar->mType->mSize * 8));
+			outS.Write((int16)GetCVRegNum(varLoc.mReg, varType->mSize * 8));
 			outS.Write((int16)0);
 			outS.Write((int16)0);
 			outS.Write((int32)varLoc.mOfs);
 			outS.Write((int32)varLoc.mOfs);
 // 			CV_RANGEATTR rangeAttr = { 0 };
 // 			CV_RANGEATTR rangeAttr = { 0 };
@@ -1135,6 +1138,8 @@ void BeCOFFObject::DbgSEndTag()
 
 
 void BeCOFFObject::DbgOutputLocalVar(BeDbgFunction* dbgFunc, BeDbgVariable* dbgVar)
 void BeCOFFObject::DbgOutputLocalVar(BeDbgFunction* dbgFunc, BeDbgVariable* dbgVar)
 {	
 {	
+	auto varType = BeValueDynCast<BeDbgType>(dbgVar->mType);
+
 	// CodeView only allows 16-bit lengths, so we need to split ranges for very long spans
 	// CodeView only allows 16-bit lengths, so we need to split ranges for very long spans
 	if (dbgVar->mDeclEnd - dbgVar->mDeclStart > 0xFFFF)
 	if (dbgVar->mDeclEnd - dbgVar->mDeclStart > 0xFFFF)
 	{		
 	{		
@@ -1215,7 +1220,7 @@ void BeCOFFObject::DbgOutputLocalVar(BeDbgFunction* dbgFunc, BeDbgVariable* dbgV
 
 
 	DbgSStartTag();
 	DbgSStartTag();
 	outS.Write((int16)S_LOCAL);
 	outS.Write((int16)S_LOCAL);
-	outS.Write(DbgGetTypeId(dbgVar->mType));
+	outS.Write(DbgGetTypeId(varType));
 	CV_LVARFLAGS flags = { 0 };
 	CV_LVARFLAGS flags = { 0 };
 
 
 	if (dbgVar->mParamNum != -1)
 	if (dbgVar->mParamNum != -1)
@@ -1732,7 +1737,7 @@ void BeCOFFObject::DbgGenerateModuleInfo()
 			else
 			else
 				outS.Write(dbgGlobalVar->mIsLocalToUnit ? (int16)S_LDATA32 : (int16)S_GDATA32);
 				outS.Write(dbgGlobalVar->mIsLocalToUnit ? (int16)S_LDATA32 : (int16)S_GDATA32);
 			
 			
-			outS.Write(DbgGetTypeId(dbgGlobalVar->mType));
+			outS.Write(DbgGetTypeId(BeValueDynCast<BeDbgType>(dbgGlobalVar->mType)));
 
 
 			BF_ASSERT(dbgGlobalVar->mValue != NULL);			
 			BF_ASSERT(dbgGlobalVar->mValue != NULL);			
 
 
@@ -1896,7 +1901,7 @@ void BeCOFFObject::WriteConst(BeCOFFSection& sect, BeConstant* constVal)
 	{
 	{
 		WriteConst(sect, constCast->mTarget);
 		WriteConst(sect, constCast->mTarget);
 	}
 	}
-	else if (auto constGep = BeValueDynCast<BeGEPConstant>(constVal))
+	else if (auto constGep = BeValueDynCast<BeGEP2Constant>(constVal))
 	{
 	{
 		if (auto globalVar = BeValueDynCast<BeGlobalVariable>(constGep->mTarget))
 		if (auto globalVar = BeValueDynCast<BeGlobalVariable>(constGep->mTarget))
 		{
 		{

+ 72 - 9
IDEHelper/Backend/BeIRCodeGen.cpp

@@ -5,6 +5,9 @@
 
 
 #include "BeefySysLib/util/AllocDebug.h"
 #include "BeefySysLib/util/AllocDebug.h"
 #include "BeefySysLib/util/Hash.h"
 #include "BeefySysLib/util/Hash.h"
+#include "BeModule.h"
+#include "BeContext.h"
+#include "..\Compiler\CeMachine.h"
 
 
 #ifdef _DEBUG
 #ifdef _DEBUG
 #define BE_EXTRA_CHECKS
 #define BE_EXTRA_CHECKS
@@ -228,7 +231,7 @@ BeIRCodeGen::BeIRCodeGen()
 	mBeContext = NULL;
 	mBeContext = NULL;
 	mBeModule = NULL;
 	mBeModule = NULL;
 	mHasDebugLoc = false;
 	mHasDebugLoc = false;
-	mDebugging = false;
+	mDebugging = false;	
 	mCmdCount = 0;
 	mCmdCount = 0;
 }
 }
 
 
@@ -736,6 +739,20 @@ void BeIRCodeGen::Read(BeValue*& beValue)
 			BE_MEM_END("ParamType_Const_BitCast");
 			BE_MEM_END("ParamType_Const_BitCast");
 			return;
 			return;
 		}
 		}
+		else if (constType == BfConstType_GEP32_1)
+		{
+			CMD_PARAM(BeConstant*, target);
+			CMD_PARAM(int, idx0);			
+
+			BF_ASSERT(target->GetType()->IsPointer());
+			auto gepConstant = mBeModule->mAlloc.Alloc<BeGEP1Constant>();
+			gepConstant->mTarget = target;
+			gepConstant->mIdx0 = idx0;			
+
+			beValue = gepConstant;
+			BE_MEM_END("ParamType_Const_GEP32_1");
+			return;
+		}
 		else if (constType == BfConstType_GEP32_2)
 		else if (constType == BfConstType_GEP32_2)
 		{
 		{
 			CMD_PARAM(BeConstant*, target);
 			CMD_PARAM(BeConstant*, target);
@@ -743,7 +760,7 @@ void BeIRCodeGen::Read(BeValue*& beValue)
 			CMD_PARAM(int, idx1);
 			CMD_PARAM(int, idx1);
 			
 			
 			BF_ASSERT(target->GetType()->IsPointer());
 			BF_ASSERT(target->GetType()->IsPointer());
-			auto gepConstant = mBeModule->mAlloc.Alloc<BeGEPConstant>();
+			auto gepConstant = mBeModule->mAlloc.Alloc<BeGEP2Constant>();
 			gepConstant->mTarget = target;
 			gepConstant->mTarget = target;
 			gepConstant->mIdx0 = idx0;
 			gepConstant->mIdx0 = idx0;
 			gepConstant->mIdx1 = idx1;
 			gepConstant->mIdx1 = idx1;
@@ -2852,7 +2869,15 @@ void BeIRCodeGen::HandleNextCmd()
 	case BfIRCmd_DbgGetType:
 	case BfIRCmd_DbgGetType:
 		{
 		{
 			CMD_PARAM(int, typeId);
 			CMD_PARAM(int, typeId);
-			SetResult(curId, GetTypeEntry(typeId).mDIType);
+
+			if (mBeModule->mCeMachine != NULL)
+			{
+				auto dbgType = mBeModule->mDbgModule->mTypes.Alloc<BeDbgTypeId>();
+				dbgType->mTypeId = typeId;
+				SetResult(curId, dbgType);
+			}
+			else
+				SetResult(curId, GetTypeEntry(typeId).mDIType);
 		}
 		}
 		break;
 		break;
 	case BfIRCmd_DbgGetTypeInst:
 	case BfIRCmd_DbgGetTypeInst:
@@ -2974,7 +2999,21 @@ void BeIRCodeGen::HandleNextCmd()
 		{			
 		{			
 			CMD_PARAM(BeMDNode*, elementTypeNode);
 			CMD_PARAM(BeMDNode*, elementTypeNode);
 			
 			
-			BeDbgType* elementType = (BeDbgType*)elementTypeNode;
+			BeDbgType* elementType = BeValueDynCast<BeDbgType>(elementTypeNode);
+			if (elementType == NULL)
+			{
+				if (auto dbgTypeId = BeValueDynCast<BeDbgTypeId>(elementTypeNode))
+				{
+					auto bfElementType = mBeModule->mCeMachine->mCeModule->mContext->mTypes[dbgTypeId->mTypeId];
+					auto bfPtrType = mBeModule->mCeMachine->mCeModule->CreatePointerType(bfElementType);
+
+					auto dbgType = mBeModule->mDbgModule->mTypes.Alloc<BeDbgTypeId>();
+					dbgType->mTypeId = bfPtrType->mTypeId;
+					SetResult(curId, dbgType);
+					break;
+				}				
+			}
+
 			BeDbgType* useType = elementType->FindDerivedType(BeDbgPointerType::TypeId);
 			BeDbgType* useType = elementType->FindDerivedType(BeDbgPointerType::TypeId);
 			if (useType == NULL)
 			if (useType == NULL)
 			{
 			{
@@ -2992,7 +3031,23 @@ void BeIRCodeGen::HandleNextCmd()
 	case BfIRCmd_DbgCreateReferenceType:
 	case BfIRCmd_DbgCreateReferenceType:
 		{
 		{
 			CMD_PARAM(BeMDNode*, elementTypeNode);
 			CMD_PARAM(BeMDNode*, elementTypeNode);
-			auto useType = mBeModule->mDbgModule->CreateReferenceType((BeDbgType*)elementTypeNode);
+			
+			BeDbgType* elementType = BeValueDynCast<BeDbgType>(elementTypeNode);
+			if (elementType == NULL)
+			{
+				if (auto dbgTypeId = BeValueDynCast<BeDbgTypeId>(elementTypeNode))
+				{
+					auto bfElementType = mBeModule->mCeMachine->mCeModule->mContext->mTypes[dbgTypeId->mTypeId];
+					auto bfPtrType = mBeModule->mCeMachine->mCeModule->CreateRefType(bfElementType);
+
+					auto dbgType = mBeModule->mDbgModule->mTypes.Alloc<BeDbgTypeId>();
+					dbgType->mTypeId = bfPtrType->mTypeId;
+					SetResult(curId, dbgType);
+					break;
+				}
+			}
+			
+			auto useType = mBeModule->mDbgModule->CreateReferenceType(elementType);
 			SetResult(curId, useType);
 			SetResult(curId, useType);
 		}
 		}
 		break;
 		break;
@@ -3000,7 +3055,15 @@ void BeIRCodeGen::HandleNextCmd()
 		{
 		{
 			CMD_PARAM(BeMDNode*, elementTypeNode);
 			CMD_PARAM(BeMDNode*, elementTypeNode);
 
 
-			BeDbgType* elementType = (BeDbgType*)elementTypeNode;
+			BeDbgType* elementType = BeValueDynCast<BeDbgType>(elementTypeNode);			
+			if (elementType == NULL)
+			{
+				auto dbgType = mBeModule->mDbgModule->mTypes.Alloc<BeDbgConstType>();
+				dbgType->mElement = elementTypeNode;
+				SetResult(curId, dbgType);
+				break;
+			}
+
 			BeDbgType* useType = elementType->FindDerivedType(BeDbgConstType::TypeId);
 			BeDbgType* useType = elementType->FindDerivedType(BeDbgConstType::TypeId);
 			if (useType == NULL)
 			if (useType == NULL)
 			{
 			{
@@ -3363,7 +3426,7 @@ void BeIRCodeGen::HandleNextCmd()
 
 
 			auto dbgVar = mBeModule->mOwnedValues.Alloc<BeDbgVariable>();
 			auto dbgVar = mBeModule->mOwnedValues.Alloc<BeDbgVariable>();
 			dbgVar->mName = name;
 			dbgVar->mName = name;
-			dbgVar->mType = (BeDbgType*)type;
+			dbgVar->mType = type;
 			dbgVar->mParamNum = argNo - 1;
 			dbgVar->mParamNum = argNo - 1;
 
 
 			int argIdx = argNo - 1;
 			int argIdx = argNo - 1;
@@ -3411,7 +3474,7 @@ void BeIRCodeGen::HandleNextCmd()
 
 
 			auto dbgVar = mBeModule->mOwnedValues.Alloc<BeDbgVariable>();
 			auto dbgVar = mBeModule->mOwnedValues.Alloc<BeDbgVariable>();
 			dbgVar->mName = name;
 			dbgVar->mName = name;
-			dbgVar->mType = (BeDbgType*)type;
+			dbgVar->mType = type;
 			dbgVar->mScope = scope;
 			dbgVar->mScope = scope;
 			dbgVar->mInitType = (BfIRInitType)initType;
 			dbgVar->mInitType = (BfIRInitType)initType;
 			mActiveFunction->mDbgFunction->mVariables.push_back(dbgVar);
 			mActiveFunction->mDbgFunction->mVariables.push_back(dbgVar);
@@ -3490,7 +3553,7 @@ void BeIRCodeGen::HandleNextCmd()
 			dbgGlobalVariable->mLinkageName = linkageName;
 			dbgGlobalVariable->mLinkageName = linkageName;
 			dbgGlobalVariable->mFile = (BeDbgFile*)file;
 			dbgGlobalVariable->mFile = (BeDbgFile*)file;
 			dbgGlobalVariable->mLineNum = lineNum;
 			dbgGlobalVariable->mLineNum = lineNum;
-			dbgGlobalVariable->mType = (BeDbgType*)type;
+			dbgGlobalVariable->mType = type;
 			dbgGlobalVariable->mIsLocalToUnit = isLocalToUnit;
 			dbgGlobalVariable->mIsLocalToUnit = isLocalToUnit;
 			dbgGlobalVariable->mValue = val;
 			dbgGlobalVariable->mValue = val;
 			dbgGlobalVariable->mDecl = decl;
 			dbgGlobalVariable->mDecl = decl;

+ 1 - 1
IDEHelper/Backend/BeIRCodeGen.h

@@ -82,7 +82,7 @@ public:
 	BeContext* mBeContext;
 	BeContext* mBeContext;
 	BeModule* mBeModule;	
 	BeModule* mBeModule;	
 	Array<BeDbgLoc*> mSavedDebugLocs;	
 	Array<BeDbgLoc*> mSavedDebugLocs;	
-	bool mHasDebugLoc;	
+	bool mHasDebugLoc;		
 
 
 	int mCmdCount;
 	int mCmdCount;
 	Dictionary<int, BeIRCodeGenEntry> mResults;
 	Dictionary<int, BeIRCodeGenEntry> mResults;

+ 33 - 4
IDEHelper/Backend/BeMCContext.cpp

@@ -2279,9 +2279,34 @@ BeMCOperand BeMCContext::GetOperand(BeValue* value, bool allowMetaResult, bool a
 
 
 		return mcOperand;
 		return mcOperand;
 	}
 	}
-	case BeGEPConstant::TypeId:
+	case BeGEP1Constant::TypeId:
 	{
 	{
-		auto gepConstant = (BeGEPConstant*)value;
+		auto gepConstant = (BeGEP1Constant*)value;
+
+		auto mcVal = GetOperand(gepConstant->mTarget);
+
+		BePointerType* ptrType = (BePointerType*)GetType(mcVal);
+		BEMC_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer);
+
+		auto result = mcVal;
+
+		// We assume we never do both an idx0 and idx1 at once.  Fix if we change that.				
+		int byteOffset = 0;
+		BeType* elementType = ptrType->mElementType;
+		byteOffset += gepConstant->mIdx0 * ptrType->mElementType->GetStride();
+				
+		result = AllocRelativeVirtualReg(ptrType, result, GetImmediate(byteOffset), 1);
+		// The def is primary to create a single 'master location' for the GEP vreg to become legalized before use			
+		auto vregInfo = GetVRegInfo(result);
+		vregInfo->mDefOnFirstUse = true;
+		result.mKind = BeMCOperandKind_VReg;
+
+		return result;
+	}
+	break;
+	case BeGEP2Constant::TypeId:
+	{
+		auto gepConstant = (BeGEP2Constant*)value;
 
 
 		auto mcVal = GetOperand(gepConstant->mTarget);
 		auto mcVal = GetOperand(gepConstant->mTarget);
 
 
@@ -2887,10 +2912,14 @@ static bool NeedsDecompose(BeConstant* constant)
 		if (auto targetConstant = BeValueDynCast<BeConstant>(castConst->mValue))
 		if (auto targetConstant = BeValueDynCast<BeConstant>(castConst->mValue))
 			return NeedsDecompose(targetConstant);
 			return NeedsDecompose(targetConstant);
 	}
 	}
-	else if (auto castConst = BeValueDynCast<BeGEPConstant>(constant))
+	else if (auto castConst = BeValueDynCast<BeGEP1Constant>(constant))
 	{		
 	{		
 		return NeedsDecompose(castConst->mTarget);
 		return NeedsDecompose(castConst->mTarget);
 	}
 	}
+	else if (auto castConst = BeValueDynCast<BeGEP2Constant>(constant))
+	{
+		return NeedsDecompose(castConst->mTarget);
+	}
 
 
 	return false;
 	return false;
 }
 }
@@ -8681,7 +8710,7 @@ void BeMCContext::DoActualization()
 							else
 							else
 							{
 							{
 								inst->mArg0.mKind = BeMCOperandKind_VRegAddr;
 								inst->mArg0.mKind = BeMCOperandKind_VRegAddr;
-								vregInfo->mDbgVariable->mType = mModule->mDbgModule->CreateReferenceType(vregInfo->mDbgVariable->mType);
+								vregInfo->mDbgVariable->mType = mModule->mDbgModule->CreateReferenceType(BeValueDynCast<BeDbgType>(vregInfo->mDbgVariable->mType));
 							}
 							}
 						}
 						}
 						vregInfo->mWantsExprActualize = false;
 						vregInfo->mWantsExprActualize = false;

+ 34 - 4
IDEHelper/Backend/BeModule.cpp

@@ -497,7 +497,13 @@ void BeStructConstant::GetData(BeConstData& data)
 		val->GetData(data);
 		val->GetData(data);
 }
 }
 
 
-BeType* BeGEPConstant::GetType()
+BeType* BeGEP1Constant::GetType()
+{
+	BePointerType* ptrType = (BePointerType*)mTarget->GetType();
+	return ptrType;
+}
+
+BeType* BeGEP2Constant::GetType()
 {	
 {	
 	BePointerType* ptrType = (BePointerType*)mTarget->GetType();
 	BePointerType* ptrType = (BePointerType*)mTarget->GetType();
 	BF_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer);
 	BF_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer);
@@ -1040,6 +1046,12 @@ void BeDumpContext::ToString(StringImpl& str, BeValue* value, bool showType, boo
 			return;
 			return;
 		}
 		}
 
 
+		if (auto dbgType = BeValueDynCast<BeDbgTypeId>(mdNode))
+		{			
+			str += StrFormat("DbgTypeId: %d", dbgType->mTypeId);
+			return;
+		}
+
 		if (auto dbgVar = BeValueDynCast<BeDbgVariable>(mdNode))
 		if (auto dbgVar = BeValueDynCast<BeDbgVariable>(mdNode))
 		{
 		{
 			ToString(str, dbgVar->mType);
 			ToString(str, dbgVar->mType);
@@ -1281,9 +1293,17 @@ void BeDumpContext::ToString(StringImpl& str, BeValue* value, bool showType, boo
 		return;
 		return;
 	}
 	}
 
 
-	if (auto constantGEP = BeValueDynCast<BeGEPConstant>(value))
+	if (auto constantGEP = BeValueDynCast<BeGEP1Constant>(value))
+	{
+		str += "ConstGEP1 ";
+		ToString(str, constantGEP->mTarget);
+		str += StrFormat(" %d %d", constantGEP->mIdx0);
+		return;
+	}
+
+	if (auto constantGEP = BeValueDynCast<BeGEP2Constant>(value))
 	{	
 	{	
-		str += "ConstGep ";
+		str += "ConstGEP2 ";
 		ToString(str, constantGEP->mTarget);
 		ToString(str, constantGEP->mTarget);
 		str += StrFormat(" %d %d", constantGEP->mIdx0, constantGEP->mIdx1);
 		str += StrFormat(" %d %d", constantGEP->mIdx0, constantGEP->mIdx1);
 		return;
 		return;
@@ -1373,7 +1393,16 @@ void BeDumpContext::ToString(StringImpl& str, BeValue* value, bool showType, boo
 		return;
 		return;
 	}
 	}
 
 
-	if (auto constant = BeValueDynCast<BeGEPConstant>(value))
+	if (auto constant = BeValueDynCast<BeGEP1Constant>(value))
+	{
+		ToString(str, constant->GetType());
+		str += " gep (";
+		ToString(str, constant->mTarget);
+		str += StrFormat(", %d)", constant->mIdx0);
+		return;
+	}
+
+	if (auto constant = BeValueDynCast<BeGEP2Constant>(value))
 	{		
 	{		
 		ToString(str, constant->GetType());
 		ToString(str, constant->GetType());
 		str += " gep (";
 		str += " gep (";
@@ -1762,6 +1791,7 @@ BeModule::BeModule(const StringImpl& moduleName, BeContext* context)
 	mLastDbgLoc = NULL;
 	mLastDbgLoc = NULL;
 	mActiveFunction = NULL;
 	mActiveFunction = NULL;
 	mDbgModule = NULL;
 	mDbgModule = NULL;
+	mCeMachine = NULL;
 	mPrevDbgLocInline = NULL;
 	mPrevDbgLocInline = NULL;
 	mCurDbgLocIdx = 0;
 	mCurDbgLocIdx = 0;
 	mCurLexBlockId = 0;	
 	mCurLexBlockId = 0;	

+ 45 - 7
IDEHelper/Backend/BeModule.h

@@ -55,6 +55,7 @@ class BePhiInst;
 class BeSwitchInst;
 class BeSwitchInst;
 class BeRetInst;
 class BeRetInst;
 class BeCallInst;
 class BeCallInst;
+class CeMachine;
 
 
 class BeDbgVariable;
 class BeDbgVariable;
 class BeDbgDeclareInst;
 class BeDbgDeclareInst;
@@ -357,10 +358,26 @@ public:
 	}
 	}
 };
 };
 
 
-class BeGEPConstant : public BeConstant
+class BeGEP1Constant : public BeConstant
 {
 {
 public:
 public:
-	BE_VALUE_TYPE(BeGEPConstant, BeConstant);	
+	BE_VALUE_TYPE(BeGEP1Constant, BeConstant);
+	int mIdx0;	
+
+	virtual BeType* GetType();
+
+	virtual void HashContent(BeHashContext& hashCtx) override
+	{
+		hashCtx.Mixin(TypeId);
+		mTarget->HashReference(hashCtx);
+		hashCtx.Mixin(mIdx0);		
+	}
+};
+
+class BeGEP2Constant : public BeConstant
+{
+public:
+	BE_VALUE_TYPE(BeGEP2Constant, BeConstant);	
 	int mIdx0;
 	int mIdx0;
 	int mIdx1;
 	int mIdx1;
 
 
@@ -1646,6 +1663,26 @@ public:
 	}
 	}
 };
 };
 
 
+class BeDbgTypeId : public BeMDNode
+{
+public:
+	BE_VALUE_TYPE(BeDbgTypeId, BeMDNode);
+
+public:
+	int mTypeId;
+	
+	BeDbgTypeId()
+	{
+		mTypeId = -1;
+	}
+	
+	virtual void HashContent(BeHashContext& hashCtx) override
+	{
+		hashCtx.Mixin(TypeId);
+		hashCtx.Mixin(mTypeId);		
+	}
+};
+
 class BeDbgType : public BeMDNode
 class BeDbgType : public BeMDNode
 {
 {
 public:
 public:
@@ -1743,7 +1780,7 @@ public:
 	BE_VALUE_TYPE(BeDbgConstType, BeDbgType);
 	BE_VALUE_TYPE(BeDbgConstType, BeDbgType);
 
 
 public:
 public:
-	BeDbgType* mElement;
+	BeMDNode* mElement;
 
 
 	virtual void HashContent(BeHashContext& hashCtx) override
 	virtual void HashContent(BeHashContext& hashCtx) override
 	{
 	{
@@ -1920,7 +1957,7 @@ public:
 
 
 public:
 public:
 	String mName;
 	String mName;
-	BeDbgType* mType;	
+	BeMDNode* mType;	
 	BeValue* mValue;
 	BeValue* mValue;
 	int mParamNum;
 	int mParamNum;
 	BfIRInitType mInitType;
 	BfIRInitType mInitType;
@@ -2044,7 +2081,7 @@ public:
 		mCvArgListId = -1;
 		mCvArgListId = -1;
 	}
 	}
 
 
-	BeDbgType* GetParamType(int paramIdx)
+	BeMDNode* GetParamType(int paramIdx)
 	{
 	{
 		/*if (!mParams.empty())
 		/*if (!mParams.empty())
 			return mParams[paramIdx]->mType;*/
 			return mParams[paramIdx]->mType;*/
@@ -2209,7 +2246,7 @@ public:
 	String mLinkageName;
 	String mLinkageName;
 	BeDbgFile* mFile;
 	BeDbgFile* mFile;
 	int mLineNum;
 	int mLineNum;
-	BeDbgType* mType;
+	BeMDNode* mType;
 	bool mIsLocalToUnit;
 	bool mIsLocalToUnit;
 	BeConstant* mValue;
 	BeConstant* mValue;
 	BeMDNode* mDecl;
 	BeMDNode* mDecl;
@@ -2246,7 +2283,7 @@ public:
 	OwnedVector<BeDbgNamespace> mNamespaces;
 	OwnedVector<BeDbgNamespace> mNamespaces;
 	OwnedVector<BeDbgGlobalVariable> mGlobalVariables;
 	OwnedVector<BeDbgGlobalVariable> mGlobalVariables;
 
 
-	OwnedVector<BeDbgType> mTypes;
+	OwnedVector<BeMDNode> mTypes;
 	Array<BeDbgFunction*> mFuncs; // Does not include methods in structs
 	Array<BeDbgFunction*> mFuncs; // Does not include methods in structs
 
 
 	virtual void HashContent(BeHashContext& hashCtx) override;	
 	virtual void HashContent(BeHashContext& hashCtx) override;	
@@ -2284,6 +2321,7 @@ public:
 	int mCurLexBlockId;	
 	int mCurLexBlockId;	
 
 
 	BeDbgModule* mDbgModule;
 	BeDbgModule* mDbgModule;
+	CeMachine* mCeMachine;
 
 
 public:	
 public:	
 	void AddInst(BeInst* inst);	
 	void AddInst(BeInst* inst);	

+ 5 - 0
IDEHelper/Compiler/BfAst.h

@@ -750,6 +750,11 @@ public:
 		return (mKind == BfTypedValueKind_UntypedValue);
 		return (mKind == BfTypedValueKind_UntypedValue);
 	}
 	}
 
 
+	bool IsNoValueType() const
+	{
+		return (mKind == BfTypedValueKind_NoValue);
+	}
+
 	bool IsParams()
 	bool IsParams()
 	{
 	{
 		return (mKind == BfTypedValueKind_ParamsSplat) || (mKind == BfTypedValueKind_Params);
 		return (mKind == BfTypedValueKind_ParamsSplat) || (mKind == BfTypedValueKind_Params);

+ 8 - 0
IDEHelper/Compiler/BfCompiler.cpp

@@ -7658,6 +7658,12 @@ void BfCompiler::Cancel()
 	mCanceling = true;
 	mCanceling = true;
 	mFastFinish = true;
 	mFastFinish = true;
 	mHadCancel = true;
 	mHadCancel = true;
+	if (mCEMachine != NULL)
+	{
+		AutoCrit autoCrit(mCEMachine->mCritSect);		
+		mCEMachine->mSpecialCheck = true;
+		mFastFinish = true;
+	}
 	BfLogSysM("BfCompiler::Cancel\n");
 	BfLogSysM("BfCompiler::Cancel\n");
 	BpEvent("BfCompiler::Cancel", "");
 	BpEvent("BfCompiler::Cancel", "");
 }
 }
@@ -7665,6 +7671,8 @@ void BfCompiler::Cancel()
 void BfCompiler::RequestFastFinish()
 void BfCompiler::RequestFastFinish()
 {
 {
 	mFastFinish = true;
 	mFastFinish = true;
+	if (mCEMachine != NULL)
+		mCEMachine->mSpecialCheck = true;
 	BfLogSysM("BfCompiler::RequestFastFinish\n");
 	BfLogSysM("BfCompiler::RequestFastFinish\n");
 	BpEvent("BfCompiler::RequestFastFinish", "");
 	BpEvent("BfCompiler::RequestFastFinish", "");
 }
 }

+ 163 - 19
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -21,6 +21,8 @@
 #include "BfFixits.h"
 #include "BfFixits.h"
 #include "CeMachine.h"
 #include "CeMachine.h"
 #include "BfDefBuilder.h"
 #include "BfDefBuilder.h"
+#include "CeMachine.h"
+#include "CeDebugger.h"
 
 
 #pragma warning(pop)
 #pragma warning(pop)
 #pragma warning(disable:4996)
 #pragma warning(disable:4996)
@@ -4018,6 +4020,35 @@ BfTypedValue BfExprEvaluator::LoadLocal(BfLocalVariable* varDecl, bool allowRef)
 
 
 BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringImpl& findName, bool ignoreInitialError, bool* hadError)
 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))
+	{
+		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 (dbgVar.mName == findName)
+				{
+					if (dbgVar.mValue.mKind == CeOperandKind_AllocaAddr)
+					{
+						return BfTypedValue(mModule->mBfIRBuilder->CreateConstAggCE(mModule->mBfIRBuilder->MapType(dbgVar.mType), activeFrame->mFrameAddr + dbgVar.mValue.mFrameOfs), dbgVar.mType, true);
+					}
+				}
+			}
+		}
+
+		if (findName == "FR")
+		{
+			auto ptrType = mModule->CreatePointerType(mModule->GetPrimitiveType(BfTypeCode_UInt8));
+			auto intVal = mModule->mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, activeFrame->mFrameAddr);
+			auto ptrVal = mModule->mBfIRBuilder->CreateIntToPtr(intVal, mModule->mBfIRBuilder->MapType(ptrType));
+			return BfTypedValue(ptrVal, ptrType);
+		}
+	}
+
 	auto identifierNode = BfNodeDynCast<BfIdentifierNode>(refNode);
 	auto identifierNode = BfNodeDynCast<BfIdentifierNode>(refNode);
 	if (mModule->mCurMethodState != NULL)
 	if (mModule->mCurMethodState != NULL)
 	{
 	{
@@ -4649,7 +4680,8 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe
 
 
 	if (isFailurePass)
 	if (isFailurePass)
 	{
 	{
-		mModule->Fail(StrFormat("'%s.%s' is inaccessible due to its protection level", mModule->TypeToString(typeInstance).c_str(), fieldDef->mName.c_str()), targetSrc);
+		if (mModule->GetCeDbgState() == NULL)
+			mModule->Fail(StrFormat("'%s.%s' is inaccessible due to its protection level", mModule->TypeToString(typeInstance).c_str(), fieldDef->mName.c_str()), targetSrc);
 	}
 	}
 
 
 	auto resolvePassData = mModule->mCompiler->mResolvePassData;
 	auto resolvePassData = mModule->mCompiler->mResolvePassData;
@@ -6039,23 +6071,46 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 				CeEvalFlags evalFlags = CeEvalFlags_None;
 				CeEvalFlags evalFlags = CeEvalFlags_None;
 				if ((mBfEvalExprFlags & BfEvalExprFlags_NoCeRebuildFlags) != 0)
 				if ((mBfEvalExprFlags & BfEvalExprFlags_NoCeRebuildFlags) != 0)
 					evalFlags = (CeEvalFlags)(evalFlags | CeEvalFlags_NoRebuild);
 					evalFlags = (CeEvalFlags)(evalFlags | CeEvalFlags_NoRebuild);
-				auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
-				if (constRet)
+				
+				if ((mModule->mIsComptimeModule) && (mModule->mCompiler->mCEMachine->mDebugger != NULL) && (mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
 				{
 				{
-					auto constant = mModule->mBfIRBuilder->GetConstant(constRet.mValue);
-					BF_ASSERT(!constRet.mType->IsVar());
-					return constRet;
-				}
+					auto ceDbgState = mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState;
+					if ((ceDbgState->mDbgExpressionFlags & DwEvalExpressionFlag_AllowCalls) != 0)
+					{	
+						ceDbgState->mHadSideEffects = true;
 
 
-				if (mModule->mCompiler->mFastFinish)
-				{
-					if ((mModule->mCurMethodInstance == NULL) || (!mModule->mCurMethodInstance->mIsAutocompleteMethod))
+						SetAndRestoreValue<CeDebugger*> prevDebugger(mModule->mCompiler->mCEMachine->mDebugger, NULL);
+
+						evalFlags = (CeEvalFlags)(evalFlags | CeEvalFlags_DbgCall);
+						auto result = ceDbgState->mCeContext->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
+						if (result)
+							return result;
+					}
+					else
 					{
 					{
-						// We didn't properly resolve this so queue for a rebuild later
-						mModule->DeferRebuildType(mModule->mCurTypeInstance);
+						ceDbgState->mBlockedSideEffects = true;						
 					}
 					}
+				}				
+				else
+				{					
+					auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
+					if (constRet)
+					{
+						auto constant = mModule->mBfIRBuilder->GetConstant(constRet.mValue);
+						BF_ASSERT(!constRet.mType->IsVar());
+						return constRet;
+					}
+
+					if (mModule->mCompiler->mFastFinish)
+					{
+						if ((mModule->mCurMethodInstance == NULL) || (!mModule->mCurMethodInstance->mIsAutocompleteMethod))
+						{
+							// We didn't properly resolve this so queue for a rebuild later
+							mModule->DeferRebuildType(mModule->mCurTypeInstance);
+						}
+					}
+					doConstReturn = true;
 				}
 				}
-				doConstReturn = true;
 			}			
 			}			
 		}
 		}
 		else if (mModule->mIsComptimeModule)
 		else if (mModule->mIsComptimeModule)
@@ -17499,6 +17554,51 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
 			}
 			}
 			return;
 			return;
 		}
 		}
+
+		if (auto ceDbgState = mModule->GetCeDbgState())
+		{
+			if (targetFunctionName.StartsWith("__"))
+			{
+				auto ceDebugger = mModule->mCompiler->mCEMachine->mDebugger;
+
+				auto _ResolveArg = [&](int argIdx, BfType* type = NULL)
+				{
+					if (argIdx >= args.mSize)
+						return BfTypedValue();
+					return mModule->CreateValueFromExpression(args[argIdx], type);
+				};
+
+				if (targetFunctionName == "__getHighBits")
+				{
+					auto typedVal = _ResolveArg(0);
+					if ((typedVal) && (typedVal.mType->IsPrimitiveType()))
+					{
+						auto primType = (BfPrimitiveType*)typedVal.mType;
+
+						int64 val = ceDebugger->ValueToInt(typedVal);
+						int64 bitCount = ceDebugger->ValueToInt(_ResolveArg(1));
+						int64 resultVal = val >> (typedVal.mType->mSize * 8 - bitCount);
+						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, (uint64)resultVal), typedVal.mType);
+						return;
+					}
+				}
+				else if (targetFunctionName == "__clearHighBits")
+				{
+					auto typedVal = _ResolveArg(0);
+					if ((typedVal) && (typedVal.mType->IsPrimitiveType()))
+					{
+						auto primType = (BfPrimitiveType*)typedVal.mType;
+
+						int64 val = ceDebugger->ValueToInt(typedVal);
+						int64 bitCount = ceDebugger->ValueToInt(_ResolveArg(1));						
+						int64 andBits = (0x8000000000000000LL) >> ((typedVal.mType->mSize - 8) * 8 + bitCount - 1);
+						int64 resultVal = val & ~andBits;
+						mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, (uint64)resultVal), typedVal.mType);
+						return;
+					}
+				}
+			}
+		}
 	}
 	}
 	else if (auto expr = BfNodeDynCast<BfExpression>(target))
 	else if (auto expr = BfNodeDynCast<BfExpression>(target))
 	{		
 	{		
@@ -18968,7 +19068,7 @@ BfTypedValue BfExprEvaluator::PerformAssignment_CheckOp(BfAssignmentExpression*
 }
 }
 
 
 void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue)
 void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue)
-{	
+{
 	auto binaryOp = BfAssignOpToBinaryOp(assignExpr->mOp);	
 	auto binaryOp = BfAssignOpToBinaryOp(assignExpr->mOp);	
 
 
 	BfExpression* targetNode = assignExpr->mLeft;
 	BfExpression* targetNode = assignExpr->mLeft;
@@ -19375,10 +19475,54 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
 				}
 				}
 				else if (!alreadyWritten)
 				else if (!alreadyWritten)
 				{
 				{
-					//ptr = mModule->LoadValue(ptr);
-					BF_ASSERT(ptr.IsAddr());
-					convVal = mModule->LoadValue(convVal);
-					auto storeInst = mModule->mBfIRBuilder->CreateAlignedStore(convVal.mValue, ptr.mValue, ptr.mType->mAlign, mIsVolatileReference);
+					if ((mModule->mIsComptimeModule) && (mModule->mCompiler->mCEMachine->mDebugger != NULL) && (mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
+					{
+						auto ceDbgState = mModule->mCompiler->mCEMachine->mDebugger->mCurDbgState;
+						bool success = false;
+
+						if ((convVal.mValue.IsConst()) && (ptr.mValue.IsConst()))
+						{
+							auto constant = mModule->mBfIRBuilder->GetConstant(ptr.mValue);
+							auto valConstant = mModule->mBfIRBuilder->GetConstant(convVal.mValue);
+
+							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))
+							{
+								if ((ceDbgState->mDbgExpressionFlags & DwEvalExpressionFlag_AllowSideEffects) != 0)
+								{
+									ceDbgState->mHadSideEffects = true;
+									if (ceContext->WriteConstant(mModule, ceTypedVal.mAddr, valConstant, convVal.mType))
+										success = true;
+								}
+								else
+								{
+									ceDbgState->mBlockedSideEffects = true;
+									success = true;
+								}
+							}
+						}
+						
+						if (!success)
+						{
+							mModule->Fail("Assignment failed", assignExpr);
+							return;
+						}
+					}
+
+					if (!alreadyWritten)
+					{
+						//ptr = mModule->LoadValue(ptr);
+						BF_ASSERT(ptr.IsAddr());
+						convVal = mModule->LoadValue(convVal);
+						auto storeInst = mModule->mBfIRBuilder->CreateAlignedStore(convVal.mValue, ptr.mValue, ptr.mType->mAlign, mIsVolatileReference);
+					}
 				}
 				}
 			}
 			}
 		}
 		}
@@ -21570,7 +21714,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp
 		leftValue.mType = leftValue.mType->GetUnderlyingType();
 		leftValue.mType = leftValue.mType->GetUnderlyingType();
 	
 	
 	if ((binaryOp == BfBinaryOp_ConditionalAnd) || (binaryOp == BfBinaryOp_ConditionalOr))
 	if ((binaryOp == BfBinaryOp_ConditionalAnd) || (binaryOp == BfBinaryOp_ConditionalOr))
-	{
+	{		
  		if (mModule->mCurMethodState->mDeferredLocalAssignData != NULL)
  		if (mModule->mCurMethodState->mDeferredLocalAssignData != NULL)
  			mModule->mCurMethodState->mDeferredLocalAssignData->BreakExtendChain();
  			mModule->mCurMethodState->mDeferredLocalAssignData->BreakExtendChain();
 		if (mModule->mCurMethodState->mCurScope->mScopeKind == BfScopeKind_StatementTarget)
 		if (mModule->mCurMethodState->mCurScope->mScopeKind == BfScopeKind_StatementTarget)

+ 61 - 0
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -1684,6 +1684,12 @@ String BfIRBuilder::ToString(BfIRValue irValue)
 			BfIRValue targetConst(BfIRValueFlags_Const, box->mTarget);
 			BfIRValue targetConst(BfIRValueFlags_Const, box->mTarget);
 			return ToString(targetConst) + " box to " + ToString(box->mToType);
 			return ToString(targetConst) + " box to " + ToString(box->mToType);
 		}
 		}
+		else if (constant->mConstType == BfConstType_GEP32_1)
+		{
+			auto gepConst = (BfConstantGEP32_1*)constant;
+			BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget);
+			return ToString(targetConst) + StrFormat(" Gep32 %d", gepConst->mIdx0);
+		}
 		else if (constant->mConstType == BfConstType_GEP32_2)
 		else if (constant->mConstType == BfConstType_GEP32_2)
 		{
 		{
 			auto gepConst = (BfConstantGEP32_2*)constant;
 			auto gepConst = (BfConstantGEP32_2*)constant;
@@ -4616,8 +4622,30 @@ BfIRValue BfIRBuilder::CreateIntToPtr(BfIRValue val, BfIRType type)
 	return retVal;
 	return retVal;
 }
 }
 
 
+BfIRValue BfIRBuilder::CreateIntToPtr(uint64 val, BfIRType type)
+{
+	return CreateIntToPtr(CreateConst(BfTypeCode_IntPtr, val), type);
+}
+
 BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, int idx0)
 BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, int idx0)
 {
 {
+	if (val.IsConst())
+	{
+		auto constGEP = mTempAlloc.Alloc<BfConstantGEP32_1>();
+		constGEP->mConstType = BfConstType_GEP32_1;
+		constGEP->mTarget = val.mId;
+		constGEP->mIdx0 = idx0;		
+
+		BfIRValue retVal;
+		retVal.mFlags = BfIRValueFlags_Const;
+		retVal.mId = mTempAlloc.GetChunkedId(constGEP);
+
+#ifdef CHECK_CONSTHOLDER
+		retVal.mHolder = this;
+#endif
+		return retVal;
+	}
+
 	BfIRValue retVal = WriteCmd(BfIRCmd_InboundsGEP1_32, val, idx0);
 	BfIRValue retVal = WriteCmd(BfIRCmd_InboundsGEP1_32, val, idx0);
 	NEW_CMD_INSERTED_IRVALUE;
 	NEW_CMD_INSERTED_IRVALUE;
 	return retVal;
 	return retVal;
@@ -4650,6 +4678,39 @@ BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, int idx0, int idx1)
 
 
 BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, BfIRValue idx0)
 BfIRValue BfIRBuilder::CreateInBoundsGEP(BfIRValue val, BfIRValue idx0)
 {
 {
+	auto constant = GetConstant(val);
+	if (constant != NULL)
+	{
+		if (constant->mConstType == BfConstType_IntToPtr)
+		{
+			auto fromPtrToInt = (BfConstantIntToPtr*)constant;
+			auto fromTarget = GetConstantById(fromPtrToInt->mTarget);
+			if (IsInt(fromTarget->mTypeCode))
+			{
+				if (fromPtrToInt->mToType.mKind == BfIRTypeData::TypeKind_TypeId)
+				{
+					auto type = mModule->mContext->mTypes[fromPtrToInt->mToType.mId];
+					if (type->IsPointer())
+					{
+						auto elementType = type->GetUnderlyingType();
+						auto addConstant = GetConstant(idx0);
+						if ((addConstant != NULL) && (IsInt(addConstant->mTypeCode)))
+						{
+							return CreateIntToPtr(CreateConst(fromTarget->mTypeCode, (uint64)(fromTarget->mInt64 + addConstant->mInt64 * elementType->GetStride())),
+								fromPtrToInt->mToType);
+						}
+					}
+				}
+			}
+		}
+
+		if (auto idxConstant = GetConstant(idx0))
+		{
+			if (IsInt(idxConstant->mTypeCode))
+				return CreateInBoundsGEP(val, idxConstant->mInt32);
+		}
+	}
+
 	BfIRValue retVal = WriteCmd(BfIRCmd_InBoundsGEP1, val, idx0);
 	BfIRValue retVal = WriteCmd(BfIRCmd_InBoundsGEP1, val, idx0);
 	NEW_CMD_INSERTED_IRVALUE;
 	NEW_CMD_INSERTED_IRVALUE;
 	return retVal;
 	return retVal;

+ 9 - 0
IDEHelper/Compiler/BfIRBuilder.h

@@ -126,6 +126,7 @@ enum BfConstType
 	BfConstType_GlobalVar = BfTypeCode_Length,	
 	BfConstType_GlobalVar = BfTypeCode_Length,	
 	BfConstType_BitCast,
 	BfConstType_BitCast,
 	BfConstType_BitCastNull,
 	BfConstType_BitCastNull,
+	BfConstType_GEP32_1,
 	BfConstType_GEP32_2,
 	BfConstType_GEP32_2,
 	BfConstType_ExtractValue,
 	BfConstType_ExtractValue,
 	BfConstType_PtrToInt,
 	BfConstType_PtrToInt,
@@ -878,6 +879,13 @@ struct BfConstantIntToPtr
 	BfIRType mToType;
 	BfIRType mToType;
 };
 };
 
 
+struct BfConstantGEP32_1
+{
+	BfConstType mConstType;
+	int mTarget;
+	int mIdx0;	
+};
+
 struct BfConstantGEP32_2
 struct BfConstantGEP32_2
 {
 {
 	BfConstType mConstType;
 	BfConstType mConstType;
@@ -1223,6 +1231,7 @@ public:
 	BfIRValue CreateBitCast(BfIRValue val, BfIRType type);
 	BfIRValue CreateBitCast(BfIRValue val, BfIRType type);
 	BfIRValue CreatePtrToInt(BfIRValue val, BfTypeCode typeCode);
 	BfIRValue CreatePtrToInt(BfIRValue val, BfTypeCode typeCode);
 	BfIRValue CreateIntToPtr(BfIRValue val, BfIRType type);
 	BfIRValue CreateIntToPtr(BfIRValue val, BfIRType type);
+	BfIRValue CreateIntToPtr(uint64 val, BfIRType type);
 	BfIRValue CreateInBoundsGEP(BfIRValue val, int idx0);
 	BfIRValue CreateInBoundsGEP(BfIRValue val, int idx0);
 	BfIRValue CreateInBoundsGEP(BfIRValue val, int idx0, int idx1);
 	BfIRValue CreateInBoundsGEP(BfIRValue val, int idx0, int idx1);
 	BfIRValue CreateInBoundsGEP(BfIRValue val, BfIRValue idx0);
 	BfIRValue CreateInBoundsGEP(BfIRValue val, BfIRValue idx0);

+ 56 - 6
IDEHelper/Compiler/BfModule.cpp

@@ -25,6 +25,7 @@
 #include "BfDefBuilder.h"
 #include "BfDefBuilder.h"
 #include "BfDeferEvalChecker.h"
 #include "BfDeferEvalChecker.h"
 #include "CeMachine.h"
 #include "CeMachine.h"
+#include "CeDebugger.h"
 #include <fcntl.h>
 #include <fcntl.h>
 #include <time.h>
 #include <time.h>
 
 
@@ -1045,7 +1046,7 @@ void BfModule::FinishInit()
 	mHasFullDebugInfo = moduleOptions.mEmitDebugInfo == 1;
 	mHasFullDebugInfo = moduleOptions.mEmitDebugInfo == 1;
 
 
 	if (mIsComptimeModule)
 	if (mIsComptimeModule)
-		mHasFullDebugInfo = false;
+		mHasFullDebugInfo = true;
 	
 	
 	if (((!mCompiler->mIsResolveOnly) && (!mIsScratchModule) && (moduleOptions.mEmitDebugInfo != 0) && (mIsReified)) ||
 	if (((!mCompiler->mIsResolveOnly) && (!mIsScratchModule) && (moduleOptions.mEmitDebugInfo != 0) && (mIsReified)) ||
 		(mIsComptimeModule))
 		(mIsComptimeModule))
@@ -1732,6 +1733,15 @@ String* BfModule::GetStringPoolString(BfIRValue constantStr, BfIRConstHolder * c
 	return NULL;
 	return NULL;
 }
 }
 
 
+CeDbgState* BfModule::GetCeDbgState()
+{
+	if (!mIsComptimeModule)
+		return NULL;
+	if ((mCompiler->mCEMachine != NULL) && (mCompiler->mCEMachine->mDebugger != NULL))
+		return mCompiler->mCEMachine->mDebugger->mCurDbgState;
+	return NULL;
+}
+
 BfIRValue BfModule::GetStringCharPtr(int stringId, bool force)
 BfIRValue BfModule::GetStringCharPtr(int stringId, bool force)
 {
 {
 	if ((mBfIRBuilder->mIgnoreWrites) && (!force))
 	if ((mBfIRBuilder->mIgnoreWrites) && (!force))
@@ -3066,8 +3076,10 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
 
 
 	//BF_ASSERT(refNode != NULL);
 	//BF_ASSERT(refNode != NULL);
 
 
-	if (mIsComptimeModule)
+	if ((mIsComptimeModule) && (!mCompiler->mCEMachine->mDbgPaused))
 	{
 	{
+		mHadBuildError = true;
+
 		if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurTargetSrc != NULL))
 		if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurTargetSrc != NULL))
 		{
 		{
 			BfError* bfError = mCompiler->mPassInstance->Fail("Comptime method generation had errors", mCompiler->mCEMachine->mCurContext->mCurTargetSrc);
 			BfError* bfError = mCompiler->mPassInstance->Fail("Comptime method generation had errors", mCompiler->mCEMachine->mCurContext->mCurTargetSrc);
@@ -3075,8 +3087,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
 				mCompiler->mPassInstance->MoreInfo(error, refNode);
 				mCompiler->mPassInstance->MoreInfo(error, refNode);
 			return bfError;
 			return bfError;
 		}
 		}
-
-		mHadBuildError = true;
+		
 		return NULL;
 		return NULL;
 	}
 	}
 
 
@@ -4139,7 +4150,7 @@ void BfModule::ResolveConstField(BfTypeInstance* typeInstance, BfFieldInstance*
 		}
 		}
 	}
 	}
 	else if (mBfIRBuilder != NULL)
 	else if (mBfIRBuilder != NULL)
-	{			
+	{		
 		SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
 		SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
 
 
 		SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
 		SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
@@ -12452,6 +12463,39 @@ BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bo
 					return GetDefaultTypedValue(typedValue.mType);
 					return GetDefaultTypedValue(typedValue.mType);
 				}
 				}
 			}
 			}
+
+			if ((mIsComptimeModule) && (mCompiler->mCEMachine->mDebugger != NULL) && (mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
+			{
+				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()))
+					{
+						void* data = ceContext->GetMemoryPtr(ceTypedValue.mAddr, sizeof(addr_ce));
+						if (data == NULL)
+						{
+							Fail("Invalid address", refNode);
+							return GetDefaultTypedValue(typedValue.mType);
+						}
+
+						addr_ce dataAddr = *(addr_ce*)data;
+						return BfTypedValue(mBfIRBuilder->CreateIntToPtr(
+							mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)dataAddr), mBfIRBuilder->MapType(typedValue.mType)), typedValue.mType);
+					}
+
+					auto constVal = ceContext->CreateConstant(this, ceContext->mMemory.mVals + ceTypedValue.mAddr, typedValue.mType);
+					if (!constVal)
+					{
+						Fail("Failed to create const", refNode);
+						return GetDefaultTypedValue(typedValue.mType);
+					}
+					return BfTypedValue(constVal, typedValue.mType);
+				}
+			}
 		}
 		}
 	}
 	}
 
 
@@ -14605,6 +14649,11 @@ void BfModule::MarkUsingThis()
 
 
 BfTypedValue BfModule::GetThis(bool markUsing)
 BfTypedValue BfModule::GetThis(bool markUsing)
 {	
 {	
+	if ((mIsComptimeModule) && (mCompiler->mCEMachine->mDebugger != NULL) && (mCompiler->mCEMachine->mDebugger->mCurDbgState != NULL))
+	{
+		return mCompiler->mCEMachine->mDebugger->mCurDbgState->mExplicitThis;
+	}
+
 	auto useMethodState = mCurMethodState;
 	auto useMethodState = mCurMethodState;
 	while ((useMethodState != NULL) && (useMethodState->mClosureState != NULL) && (useMethodState->mClosureState->mCapturing))		
 	while ((useMethodState != NULL) && (useMethodState->mClosureState != NULL) && (useMethodState->mClosureState->mCapturing))		
 	{
 	{
@@ -14628,7 +14677,7 @@ BfTypedValue BfModule::GetThis(bool markUsing)
 		}
 		}
 	}
 	}
 	else
 	else
-	{
+	{		
 		//TODO: Do we allow useMethodState to be NULL anymore?
 		//TODO: Do we allow useMethodState to be NULL anymore?
 		return BfTypedValue();
 		return BfTypedValue();
 	}
 	}
@@ -16616,6 +16665,7 @@ void BfModule::EmitDtorBody()
 				}
 				}
 				else
 				else
 				{
 				{
+					PopulateType(fieldInst->mResolvedType);
 					if (fieldInst->mResolvedType->IsValuelessType())
 					if (fieldInst->mResolvedType->IsValuelessType())
 					{
 					{
 						value = mBfIRBuilder->GetFakeVal();
 						value = mBfIRBuilder->GetFakeVal();

+ 2 - 0
IDEHelper/Compiler/BfModule.h

@@ -33,6 +33,7 @@ class BfType;
 class BfResolvedType;
 class BfResolvedType;
 class BfExprEvaluator;
 class BfExprEvaluator;
 class CeEmitContext;
 class CeEmitContext;
+class CeDbgState;
 
 
 enum BfPopulateType
 enum BfPopulateType
 {	
 {	
@@ -1543,6 +1544,7 @@ public:
 	void VerifyOnDemandMethods();
 	void VerifyOnDemandMethods();
 	bool IsSkippingExtraResolveChecks();
 	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* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false, bool deferError = false);
 	BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL);
 	BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL);
 	BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);	
 	BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);	

+ 1 - 1
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -12086,7 +12086,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 		if ((typedVal.mType->IsPointer()) && (toType->IsIntPtr()))
 		if ((typedVal.mType->IsPointer()) && (toType->IsIntPtr()))
 		{				
 		{				
 			if ((!typedVal.mType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
 			if ((!typedVal.mType->GetUnderlyingType()->IsVoid()) && ((castFlags & BfCastFlags_FromCompiler) == 0))
-			{				
+			{
 				if (!ignoreErrors)
 				if (!ignoreErrors)
 					Fail(StrFormat("Unable to cast directly from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
 					Fail(StrFormat("Unable to cast directly from '%s' to '%s', consider casting to void* first", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
 				else if (!silentFail)
 				else if (!silentFail)

+ 9 - 3
IDEHelper/Compiler/BfParser.cpp

@@ -720,7 +720,7 @@ BfBlock* BfParser::ParseInlineBlock(int spaceIdx, int endIdx)
 
 
 	while (true)
 	while (true)
 	{
 	{
-		NextToken(endIdx + 1);
+		NextToken(endIdx + 1, false, true);
 		if (mSyntaxToken == BfSyntaxToken_HIT_END_IDX)
 		if (mSyntaxToken == BfSyntaxToken_HIT_END_IDX)
 		{
 		{
 			mSrcIdx = usedEndIdx;
 			mSrcIdx = usedEndIdx;
@@ -1384,7 +1384,7 @@ double BfParser::ParseLiteralDouble()
 	return strtod(buf, NULL);
 	return strtod(buf, NULL);
 }
 }
 
 
-void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
+void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePreprocessor)
 {
 {
 	auto prevToken = mToken;
 	auto prevToken = mToken;
 
 
@@ -2337,7 +2337,13 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
 			}
 			}
 			break;
 			break;
 		case '#':
 		case '#':
-			HandlePreprocessor();
+			if (disablePreprocessor)
+			{
+				TokenFail("Unexpected character");
+				continue;
+			}
+			else
+				HandlePreprocessor();
 			if (mSyntaxToken == BfSyntaxToken_EOF)
 			if (mSyntaxToken == BfSyntaxToken_EOF)
 				return;
 				return;
 			break;
 			break;

+ 1 - 1
IDEHelper/Compiler/BfParser.h

@@ -227,7 +227,7 @@ public:
 	void MoveSource(const char* data, int length); // Takes ownership of data ptr
 	void MoveSource(const char* data, int length); // Takes ownership of data ptr
 	void RefSource(const char* data, int length);
 	void RefSource(const char* data, int length);
 	void MakeNegative(uint64& val, bool& hadOverflow);
 	void MakeNegative(uint64& val, bool& hadOverflow);
-	void NextToken(int endIdx = -1, bool outerIsInterpolate = false);
+	void NextToken(int endIdx = -1, bool outerIsInterpolate = false, bool disablePreprocessor = false);
 	BfAstNode* CreateNode();	
 	BfAstNode* CreateNode();	
 		
 		
 	void Parse(BfPassInstance* passInstance);		
 	void Parse(BfPassInstance* passInstance);		

+ 4 - 0
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -3503,6 +3503,10 @@ int BfResolvedTypeSet::DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHa
 			BF_ASSERT(sizeExpr != NULL);
 			BF_ASSERT(sizeExpr != NULL);
 			if (sizeExpr != NULL)
 			if (sizeExpr != NULL)
 			{
 			{
+				BfMethodState methodState;
+				SetAndRestoreValue<BfMethodState*> prevMethodState(ctx->mModule->mCurMethodState, &methodState);
+				methodState.mTempKind = BfMethodState::TempKind_Static;
+
 				BfConstResolver constResolver(ctx->mModule);
 				BfConstResolver constResolver(ctx->mModule);
 				BfType* intType = ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr);
 				BfType* intType = ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr);
 				constResolver.mAllowGenericConstValue = true;
 				constResolver.mAllowGenericConstValue = true;

+ 1 - 1
IDEHelper/Compiler/BfStmtEvaluator.cpp

@@ -3523,7 +3523,7 @@ void BfModule::VisitCodeBlock(BfBlock* block)
 							mCurMethodState->mMixinState->mResultExpr = expr;
 							mCurMethodState->mMixinState->mResultExpr = expr;
 							break;
 							break;
 						}
 						}
-						else if ((mCurMethodInstance->IsMixin()) && (mCurMethodState->mCurScope == &mCurMethodState->mHeadScope))
+						else if ((mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin()) && (mCurMethodState->mCurScope == &mCurMethodState->mHeadScope))
 						{
 						{
 							// Only in mixin definition - result ignored
 							// Only in mixin definition - result ignored
 							CreateValueFromExpression(expr);
 							CreateValueFromExpression(expr);

+ 8 - 0
IDEHelper/Compiler/BfUtil.cpp

@@ -27,6 +27,14 @@ String Beefy::EncodeDataPtr(uint32 addr, bool doPrefix)
 		return StrFormat("%08X", addr);
 		return StrFormat("%08X", addr);
 }
 }
 
 
+String Beefy::EncodeDataPtr(int addr, bool doPrefix)
+{
+	if (doPrefix)
+		return StrFormat("0x%08X", addr);
+	else
+		return StrFormat("%08X", addr);
+}
+
 String Beefy::EncodeDataPtr(uint64 addr, bool doPrefix)
 String Beefy::EncodeDataPtr(uint64 addr, bool doPrefix)
 {
 {
 	if (doPrefix)
 	if (doPrefix)

+ 1 - 0
IDEHelper/Compiler/BfUtil.h

@@ -269,6 +269,7 @@ void* DecodeLocalDataPtr(const char*& strRef);
 String EncodeDataPtr(void* addr, bool doPrefix);
 String EncodeDataPtr(void* addr, bool doPrefix);
 String EncodeDataPtr(uint32 addr, bool doPrefix);
 String EncodeDataPtr(uint32 addr, bool doPrefix);
 String EncodeDataPtr(uint64 addr, bool doPrefix);
 String EncodeDataPtr(uint64 addr, bool doPrefix);
+String EncodeDataPtr(int addr, bool doPrefix);
 void* ZeroedAlloc(int size);
 void* ZeroedAlloc(int size);
 /*template <typename T>
 /*template <typename T>
 T* ZeroedAlloc()
 T* ZeroedAlloc()

+ 4239 - 0
IDEHelper/Compiler/CeDebugger.cpp

@@ -0,0 +1,4239 @@
+#include "CeDebugger.h"
+#include "CeMachine.h"
+#include "BfCompiler.h"
+#include "../DebugManager.h"
+#include "BeefySysLib/util/BeefPerf.h"
+#include "BfParser.h"
+#include "BfReducer.h"
+#include "BeefySysLib/util/UTF8.h"
+#include "BfUtil.h"
+#include "BfExprEvaluator.h"
+#include "BeefySysLib/util/BitSet.h"
+#include "../DebugVisualizers.h"
+
+USING_NS_BF;
+
+static addr_ce DecodeTargetDataPtr(const char*& strRef)
+{
+	addr_ce val = (addr_ce)stouln(strRef, sizeof(addr_ce) * 2);
+	strRef += sizeof(addr_ce) * 2;
+	return val;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+CePendingExpr::CePendingExpr()
+{
+	mThreadId = -1;
+	mCallStackIdx = -1;
+	mParser = NULL;
+	mCursorPos = -1;
+	mExprNode = NULL;
+	mIdleTicks = 0;
+	mExplitType = NULL;
+	mExpressionFlags = DwEvalExpressionFlag_None;
+}
+
+CePendingExpr::~CePendingExpr()
+{
+	delete mParser;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+
+CeEvaluationContext::CeEvaluationContext(CeDebugger* winDebugger, const StringImpl& expr, CeFormatInfo* formatInfo, BfTypedValue contextValue)
+{
+	Init(winDebugger, expr, formatInfo, contextValue);
+}
+
+void CeEvaluationContext::Init(CeDebugger* ceDebugger, const StringImpl& expr, CeFormatInfo* formatInfo, BfTypedValue contextValue)
+{
+	mDebugger = ceDebugger;
+		
+	mCallStackIdx = 0;
+	mParser = NULL;
+	mReducer = NULL;
+	mPassInstance = NULL;
+	mExprEvaluator = NULL;
+	mExprNode = NULL;
+	
+	if (expr.empty())
+		return;	
+
+	int atPos = (int)expr.IndexOf('@');
+	if ((atPos != -1) && (atPos < expr.mLength - 2) && (expr[atPos + 1] == '0') && (expr[atPos + 2] == 'x'))
+	{
+		bool isValid = true;
+		for (int i = 0; i < atPos; i++)
+		{
+			char c = expr[i];
+			if ((c < '0') || (c > '9'))
+			{
+				isValid = false;
+				break;
+			}
+		}
+
+		if (isValid)
+		{
+			int parseLength = expr.mLength;
+			for (int i = 0; i < expr.mLength; i++)
+			{
+				if ((expr[i] == ',') || (::isspace((uint8)expr[i])))
+				{
+					parseLength = i;
+					break;
+				}
+			}
+			mExprString = expr.Substring(0, parseLength);
+
+			String typeIdStr = expr.Substring(0, atPos);
+			String addrStr = expr.Substring(atPos + 3, parseLength - atPos - 3);
+
+			int typeId = strtol(typeIdStr.c_str(), NULL, 10);
+			int64 addrVal = strtoll(addrStr.c_str(), NULL, 16);
+
+			if ((typeId != 0) && (addrVal != 0))
+			{
+				auto type = ceDebugger->mCompiler->mContext->FindTypeById(typeId);
+				if (type != NULL)
+				{
+					auto module = ceDebugger->mCeMachine->mCeModule;
+
+					if (type->IsObjectOrInterface())
+					{
+						mResultOverride = BfTypedValue(module->mBfIRBuilder->CreateIntToPtr(
+							module->mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)addrVal), module->mBfIRBuilder->MapType(type)), type);
+					}
+					else
+					{
+						mResultOverride = BfTypedValue(module->mBfIRBuilder->CreateConstAggCE(module->mBfIRBuilder->MapType(type), (addr_ce)addrVal), type, true);
+					}
+				}
+			}
+			return;
+		}
+	}
+
+	mParser = new BfParser(ceDebugger->mCompiler->mSystem);	
+	mPassInstance = new BfPassInstance(ceDebugger->mCompiler->mSystem);
+	auto terminatedExpr = expr + ";";
+	mParser->SetSource(terminatedExpr.c_str(), (int)terminatedExpr.length());
+	mParser->Parse(mPassInstance);
+
+	mReducer = new BfReducer();
+	mReducer->mAlloc = mParser->mAlloc;
+	mReducer->mSystem = ceDebugger->mCompiler->mSystem;
+	mReducer->mPassInstance = mPassInstance;
+	mReducer->mVisitorPos = BfReducer::BfVisitorPos(mParser->mRootNode);
+	mReducer->mVisitorPos.MoveNext();
+	mReducer->mSource = mParser;
+	mExprNode = mReducer->CreateExpression(mParser->mRootNode->GetFirst());
+	mParser->Close();
+	mExprEvaluator = new BfExprEvaluator(ceDebugger->mCeMachine->mCeModule);
+
+	if ((formatInfo != NULL) && (mExprNode != NULL) && (mExprNode->GetSrcEnd() < (int)expr.length()))
+	{
+		String formatFlags = expr.Substring(mExprNode->GetSrcEnd());
+		String errorString = "Invalid expression";
+		if (!ceDebugger->ParseFormatInfo(formatFlags, formatInfo, mPassInstance, NULL, NULL, &errorString, contextValue))
+		{
+			mPassInstance->FailAt(errorString, mParser->mSourceData, mExprNode->GetSrcEnd(), (int)expr.length() - mExprNode->GetSrcEnd());
+			formatFlags = "";
+		}
+	}
+
+	if (formatInfo != NULL)
+	{
+		mExplicitThis = formatInfo->mExplicitThis;
+		mCallStackIdx = formatInfo->mCallStackIdx;
+	}
+
+	mExprNode->ToString(mExprString);
+}
+
+bool CeEvaluationContext::HasExpression()
+{
+	return !mExprString.IsEmpty();
+}
+
+CeEvaluationContext::~CeEvaluationContext()
+{
+	delete mParser;
+	delete mReducer;
+	delete mExprEvaluator;
+	delete mPassInstance;
+}
+
+BfTypedValue CeEvaluationContext::EvaluateInContext(BfTypedValue contextTypedValue)
+{
+	if (mResultOverride)
+		return mResultOverride;
+
+	if (mExprNode == NULL)
+		return BfTypedValue();
+	mPassInstance->ClearErrors();
+
+	auto ceFrame = mDebugger->GetFrame(mCallStackIdx);
+
+	auto module = mDebugger->mCeMachine->mCeModule;
+	
+	SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(module->mCurTypeInstance, ceFrame->mFunction->mMethodInstance->GetOwner());
+	SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(module->mCurMethodInstance, ceFrame->mFunction->mMethodInstance);
+	SetAndRestoreValue<BfPassInstance*> prevPassInstance(mDebugger->mCompiler->mPassInstance, mPassInstance);
+	SetAndRestoreValue<bool> prevIgnoreWrites(module->mBfIRBuilder->mIgnoreWrites, true);
+
+	BfMethodState methodState;
+	SetAndRestoreValue<BfMethodState*> 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;
+	if (contextTypedValue)
+		dbgState.mExplicitThis = contextTypedValue;
+	else
+		dbgState.mExplicitThis = mExplicitThis;
+	SetAndRestoreValue<CeDbgState*> prevDbgState(mDebugger->mCurDbgState, &dbgState);
+
+	BfTypedValue exprResult;
+	mExprEvaluator->VisitChildNoRef(mExprNode);
+
+	auto result = mExprEvaluator->mResult;
+	if ((result) && (!result.mType->IsComposite()))
+		result = module->LoadValue(result);
+
+	return result;
+}
+
+bool CeEvaluationContext::HadError()
+{
+	return (mPassInstance != NULL) && (mPassInstance->mFailedIdx != 0);
+}
+
+String CeEvaluationContext::GetErrorStr()
+{
+	if (mPassInstance == NULL)
+		return "";
+	String errorStr = mPassInstance->mErrors[0]->mError;
+	if (mExprNode != NULL)
+	{
+		errorStr += ": ";
+		errorStr += mExprNode->ToString();
+	}
+	return errorStr;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+CeDebugger::CeDebugger(DebugManager* debugManager, BfCompiler* bfCompiler)
+{
+	mDebugManager = debugManager;
+	mCompiler = bfCompiler;
+	mCeMachine = bfCompiler->mCEMachine;
+	mRunState = RunState_Running;
+	mCeMachine->mDebugger = this;
+	mCeMachine->mDebugEvent.Reset();
+	mDebugPendingExpr = NULL;
+	mCurDbgState = NULL;
+	mBreakpointVersion = 0;
+	mBreakpointCacheDirty = false;	
+	mBreakpointFramesDirty = false;
+	mCurDisasmFuncId = 0;
+	mActiveBreakpoint = NULL;
+	mCurEvaluationContext = NULL;
+}
+
+CeDebugger::~CeDebugger()
+{
+	mCeMachine->mDebugEvent.Set(true);
+	mCeMachine->mDebugger = NULL;
+	delete mDebugPendingExpr;
+
+	for (auto breakpoint : mBreakpoints)
+		delete breakpoint;
+
+	for (auto kv : mFileInfo)
+		delete kv.mValue;
+}
+
+void CeDebugger::OutputMessage(const StringImpl& msg)
+{
+	if (this == NULL)
+		return;
+	AutoCrit autoCrit(mDebugManager->mCritSect);
+	mDebugManager->mOutMessages.push_back("msg " + msg);
+}
+
+void CeDebugger::OutputRawMessage(const StringImpl& msg)
+{
+	if (this == NULL)
+		return;
+	AutoCrit autoCrit(mDebugManager->mCritSect);
+	mDebugManager->mOutMessages.push_back(msg);
+}
+
+int CeDebugger::GetAddrSize()
+{
+	return sizeof(addr_ce);
+}
+
+bool CeDebugger::CanOpen(const StringImpl& fileName, DebuggerResult* outResult)
+{
+	return false;
+}
+
+void CeDebugger::OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled)
+{
+}
+
+bool CeDebugger::Attach(int processId, BfDbgAttachFlags attachFlags)
+{
+	return false;
+}
+
+void CeDebugger::Run()
+{
+}
+
+void CeDebugger::HotLoad(const Array<String>& objectFiles, int hotIdx)
+{
+}
+
+void CeDebugger::InitiateHotResolve(DbgHotResolveFlags flags)
+{
+}
+
+intptr CeDebugger::GetDbgAllocHeapSize()
+{
+	return intptr();
+}
+
+String CeDebugger::GetDbgAllocInfo()
+{
+	return String();
+}
+
+void CeDebugger::Update()
+{
+	if ((mRunState == RunState_Terminated) || (mRunState == RunState_Terminating))
+		return;
+
+	AutoCrit autoCrit(mCeMachine->mCritSect);
+	if (mCeMachine->mDbgPaused)
+	{
+		mRunState = RunState_Paused;
+	}
+	else
+	{
+		mRunState = RunState_Running;
+	}
+}
+
+void CeDebugger::UpdateBreakpointFrames()
+{
+	if (mBreakpointCacheDirty)
+		UpdateBreakpointCache();
+	for (auto& callStack : mCeMachine->mCurContext->mCallStack)
+	{
+		if (callStack.mFunction->mBreakpointVersion != mBreakpointVersion)
+			UpdateBreakpoints(callStack.mFunction);
+	}
+}
+
+void CeDebugger::ContinueDebugEvent()
+{	
+	mRunState = RunState_Running;
+	mActiveBreakpoint = NULL;
+
+	if (mBreakpointFramesDirty)
+		UpdateBreakpointFrames();
+
+	mCeMachine->mDebugEvent.Set();
+}
+
+void CeDebugger::ForegroundTarget()
+{
+}
+
+Breakpoint* CeDebugger::CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset)
+{
+	ClearBreakpointCache();
+
+	auto breakpoint = new CeBreakpoint();
+	breakpoint->mFilePath = fileName;
+	breakpoint->mRequestedLineNum = lineNum;
+	breakpoint->mLineNum = lineNum;
+	breakpoint->mColumn = wantColumn;
+	breakpoint->mInstrOffset = instrOffset;	
+	mBreakpoints.Add(breakpoint);
+
+	mBreakpointVersion++;
+
+	return breakpoint;
+}
+
+Breakpoint* CeDebugger::CreateMemoryBreakpoint(intptr addr, int byteCount)
+{
+	return nullptr;
+}
+
+Breakpoint* CeDebugger::CreateSymbolBreakpoint(const StringImpl& symbolName)
+{
+	return nullptr;
+}
+
+Breakpoint* CeDebugger::CreateAddressBreakpoint(intptr address)
+{
+	return nullptr;
+}
+
+uintptr CeDebugger::GetBreakpointAddr(Breakpoint* breakpoint)
+{
+	if (mBreakpointCacheDirty)
+	{
+		UpdateBreakpointCache();
+		UpdateBreakpointAddrs();
+	}
+	return breakpoint->GetAddr();
+}
+
+void CeDebugger::CheckBreakpoint(Breakpoint* breakpoint)
+{
+}
+
+void CeDebugger::HotBindBreakpoint(Breakpoint* breakpoint, int lineNum, int hotIdx)
+{
+}
+
+int64 CeDebugger::ValueToInt(const BfTypedValue& typedVal)
+{	
+	auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(typedVal.mValue);
+	if (constant == NULL)
+		return 0;
+
+	if (typedVal.IsAddr())
+	{	
+		BfType* type = typedVal.mType;
+		if (type->IsTypedPrimitive())
+			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 0;
+	}	
+	if ((BfIRConstHolder::IsInt(constant->mTypeCode)) || (constant->mTypeCode == BfTypeCode_Boolean))
+		return constant->mInt64;
+	return 0;
+}
+
+void CeDebugger::DeleteBreakpoint(Breakpoint* breakpoint)
+{
+	if (mActiveBreakpoint == breakpoint)
+		mActiveBreakpoint = NULL;
+	mBreakpoints.Remove((CeBreakpoint*)breakpoint);
+	delete breakpoint;
+	ClearBreakpointCache();
+}
+
+void CeDebugger::DetachBreakpoint(Breakpoint* breakpoint)
+{
+}
+
+void CeDebugger::MoveBreakpoint(Breakpoint* breakpoint, int lineNum, int wantColumn, bool rebindNow)
+{
+	breakpoint->mLineNum = lineNum;
+	breakpoint->mColumn = wantColumn;
+	ClearBreakpointCache();
+}
+
+void CeDebugger::MoveMemoryBreakpoint(Breakpoint* breakpoint, intptr addr, int byteCount)
+{
+}
+
+void CeDebugger::DisableBreakpoint(Breakpoint* breakpoint)
+{	
+}
+
+void CeDebugger::SetBreakpointCondition(Breakpoint* breakpoint, const StringImpl& condition)
+{
+}
+
+void CeDebugger::SetBreakpointLogging(Breakpoint* breakpoint, const StringImpl& logging, bool breakAfterLogging)
+{
+}
+
+Breakpoint* CeDebugger::FindBreakpointAt(intptr address)
+{
+	return nullptr;
+}
+
+Breakpoint* CeDebugger::GetActiveBreakpoint()
+{
+	return mActiveBreakpoint;
+}
+
+void CeDebugger::BreakAll()
+{
+	mCeMachine->mSpecialCheck = true;
+	mCeMachine->mDbgWantBreak = true;
+
+}
+
+bool CeDebugger::TryRunContinue()
+{
+	return false;
+}
+
+bool CeDebugger::SetupStep(int frameIdx)
+{
+	auto ceFrame = GetFrame(frameIdx);
+	if (ceFrame == NULL)
+	{
+		ContinueDebugEvent();
+		return false;
+	}
+
+	int entryIdx = 0;
+	auto curEntry = ceFrame->mFunction->FindEmitEntry(ceFrame->GetInstIdx(), &entryIdx);
+	if (curEntry == NULL)
+	{
+		ContinueDebugEvent();
+		return false;
+	}
+
+	auto ceMachine = mCeMachine;	
+	auto ceContext = mCeMachine->mCurContext;
+
+	if (entryIdx < ceFrame->mFunction->mEmitTable.mSize - 1)
+	{
+		int checkIdx = entryIdx + 1;
+		while (checkIdx < ceFrame->mFunction->mEmitTable.mSize)
+		{
+			auto checkEntry = &ceFrame->mFunction->mEmitTable[checkIdx];
+			ceMachine->mStepState.mNextInstIdx = checkEntry->mCodePos;
+			if ((checkEntry->mScope != curEntry->mScope) || (checkEntry->mLine != curEntry->mLine))
+				break;
+			++checkIdx;
+		}
+	}
+	else
+		ceMachine->mStepState.mNextInstIdx = ceFrame->mFunction->mCode.mSize;	
+	ceMachine->mStepState.mStartDepth = ceContext->mCallStack.mSize - frameIdx;
+	ceMachine->mSpecialCheck = true;
+
+	ContinueDebugEvent();
+	return true;
+}
+
+void CeDebugger::StepInto(bool inAssembly)
+{
+	if (!SetupStep())
+		return;
+	mCeMachine->mStepState.mKind = inAssembly ? CeStepState::Kind_StepInfo_Asm : CeStepState::Kind_StepInfo;
+}
+
+void CeDebugger::StepIntoSpecific(intptr addr)
+{
+}
+
+void CeDebugger::StepOver(bool inAssembly)
+{
+	if (!SetupStep())
+		return;
+	mCeMachine->mStepState.mKind = inAssembly ? CeStepState::Kind_StepOver_Asm : CeStepState::Kind_StepOver;
+}
+
+void CeDebugger::StepOut(bool inAssembly)
+{
+	if (!SetupStep(1))
+		return;
+	mCeMachine->mStepState.mKind = inAssembly ? CeStepState::Kind_StepOut_Asm : CeStepState::Kind_StepOut;
+}
+
+void CeDebugger::SetNextStatement(bool inAssembly, const StringImpl& fileName, int64 lineNumOrAsmAddr, int wantColumn)
+{
+	auto ceFrame = GetFrame(0);
+	if (ceFrame == NULL)
+		return;
+
+	if (inAssembly)
+	{		
+		int32 instIdx = (int32)lineNumOrAsmAddr;
+		if (instIdx < ceFrame->mFunction->mCode.mSize)
+		{
+			mCeMachine->mSpecialCheck = true;
+			mCeMachine->mStepState.mKind = CeStepState::Kind_Jmp;
+			mCeMachine->mStepState.mNextInstIdx = instIdx;
+			ContinueDebugEvent();
+		}
+	}
+	else
+	{
+		for (auto& emitEntry : ceFrame->mFunction->mEmitTable)
+		{
+			if (emitEntry.mScope == -1)
+				continue;
+			auto& scope = ceFrame->mFunction->mDbgScopes[emitEntry.mScope];
+			if ((FileNameEquals(fileName, scope.mFilePath) && (emitEntry.mLine == lineNumOrAsmAddr)))
+			{
+				mCeMachine->mSpecialCheck = true;
+				mCeMachine->mStepState.mKind = CeStepState::Kind_Jmp;
+				mCeMachine->mStepState.mNextInstIdx = emitEntry.mCodePos;
+				ContinueDebugEvent();
+				return;
+			}
+		}
+	}
+}
+
+CeFrame* CeDebugger::GetFrame(int callStackIdx)
+{
+	auto ceContext = mCeMachine->mCurContext;
+	if (ceContext == NULL)
+		return NULL;
+	if (callStackIdx < ceContext->mCallStack.mSize)
+	{
+		int stackIdx = ceContext->mCallStack.mSize - callStackIdx - 1;
+		auto ceFrame = &ceContext->mCallStack[stackIdx];
+		return ceFrame;
+	}
+	return NULL;
+}
+
+String CeDebugger::EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& bfPassInstance)
+{
+	auto ceFrame = GetFrame(pendingExpr->mCallStackIdx);
+	if (ceFrame == NULL)
+	{
+		return "!failed";
+	}
+
+	if (pendingExpr->mExprNode == NULL)
+	{
+		return "!failed";
+	}
+
+	auto module = mCeMachine->mCeModule;
+
+	SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(module->mCurTypeInstance, ceFrame->mFunction->mMethodInstance->GetOwner());
+	SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(module->mCurMethodInstance, ceFrame->mFunction->mMethodInstance);
+	SetAndRestoreValue<BfPassInstance*> prevPassInstance(mCompiler->mPassInstance, &bfPassInstance);
+	SetAndRestoreValue<bool> prevIgnoreWrites(module->mBfIRBuilder->mIgnoreWrites, true);
+
+	BfMethodState methodState;
+	SetAndRestoreValue<BfMethodState*> prevMethodState(module->mCurMethodState, &methodState);
+	methodState.mTempKind = module->mCurMethodInstance->mMethodDef->mIsStatic ? BfMethodState::TempKind_Static : BfMethodState::TempKind_NonStatic;
+
+	CeDbgState dbgState;
+	dbgState.mActiveFrame = ceFrame;
+	dbgState.mCeContext = mCeMachine->mCurContext;
+	dbgState.mExplicitThis = pendingExpr->mFormatInfo.mExplicitThis;
+	dbgState.mDbgExpressionFlags = pendingExpr->mExpressionFlags;
+	SetAndRestoreValue<CeDbgState*> prevDbgState(mCurDbgState, &dbgState);
+
+	BfTypedValue exprResult;
+
+	if (auto typeRef = BfNodeDynCast<BfTypeReference>(pendingExpr->mExprNode))
+	{
+		auto resultType = mCeMachine->mCeModule->ResolveTypeRef(typeRef);
+		if (resultType != NULL)
+			exprResult = BfTypedValue(resultType);
+	}
+	else
+	{
+		BfExprEvaluator exprEvaluator(mCeMachine->mCeModule);
+		exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_Comptime);
+		exprEvaluator.VisitChildNoRef(pendingExpr->mExprNode);
+		exprResult = exprEvaluator.mResult;
+		if ((exprResult) && (!exprResult.mType->IsComposite()))
+			exprResult = module->LoadValue(exprResult);
+	}
+	
+	if (dbgState.mBlockedSideEffects)
+		return "!sideeffects";
+	
+	if (!exprResult)
+	{
+		auto resultType = mCeMachine->mCeModule->ResolveTypeRef(pendingExpr->mExprNode, {}, BfPopulateType_Data, BfResolveTypeRefFlag_IgnoreLookupError);
+		if (resultType != NULL)
+		{
+			exprResult = BfTypedValue(resultType);
+			bfPassInstance.ClearErrors();
+		}
+	}
+
+	String val;
+	if (bfPassInstance.HasFailed())
+	{
+		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());
+	}
+	else	
+	{
+		val = TypedValueToString(exprResult, pendingExpr->mExprNode->ToString(), pendingExpr->mFormatInfo, (pendingExpr->mExpressionFlags & DwEvalExpressionFlag_FullPrecision) != 0);
+
+		if ((!val.empty()) && (val[0] == '!'))
+			return val;
+
+		if (pendingExpr->mFormatInfo.mRawString)
+			return val;
+
+		if (bfPassInstance.HasMessages())
+		{
+			for (auto error : bfPassInstance.mErrors)
+			{
+				if (error->mIsWarning)
+				{
+					val += "\n:warn\t";
+					val += error->mError;
+				}
+			}
+		}
+
+		if (!pendingExpr->mFormatInfo.mReferenceId.empty())
+			val += "\n:referenceId\t" + pendingExpr->mFormatInfo.mReferenceId;
+
+		// 	if ((exprResult.mSrcAddress != 0) && (HasMemoryBreakpoint(exprResult.mSrcAddress, exprResult.mType->GetByteCount())))
+		// 		val += StrFormat("\n:break\t%@", exprResult.mSrcAddress);
+
+		auto checkType = exprResult.mType;
+		if (checkType->IsObject())
+			val += "\n:type\tobject";
+		else if (checkType->IsPointer())
+			val += "\n:type\tpointer";
+		else if (checkType->IsInteger())
+			val += "\n:type\tint";
+		else if (checkType->IsFloat())
+			val += "\n:type\tfloat";
+	}
+
+	if (dbgState.mHadSideEffects)
+		val += "\n:sideeffects";
+
+	auto resultConstant = module->mBfIRBuilder->GetConstant(exprResult.mValue);
+	if (resultConstant != NULL)
+	{
+		auto ceResultTyped = GetAddr(resultConstant);
+		if (ceResultTyped.mAddr != 0)
+			val += "\n:canEdit";
+	}
+
+	return val;
+}
+
+String CeDebugger::Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags)
+{
+	BP_ZONE_F("WinDebugger::Evaluate %s", BP_DYN_STR(expr.c_str()));
+
+	AutoCrit autoCrit(mCeMachine->mCritSect);
+
+	if ((expressionFlags & DwEvalExpressionFlag_RawStr) != 0)
+	{
+		formatInfo.mRawString = true;
+	}
+
+	bool valIsAddr = false;
+
+	BfParser* parser = new BfParser(mCompiler->mSystem);	
+
+	BfPassInstance bfPassInstance(mCompiler->mSystem);
+
+	auto parseAsType = false;
+
+	auto terminatedExpr = expr;
+	terminatedExpr.Trim();
+
+	if (terminatedExpr.EndsWith(">"))
+		parseAsType = true;
+	else if ((terminatedExpr.StartsWith("comptype(")) && (!terminatedExpr.Contains('.')))
+		parseAsType = true;
+
+	if (!parseAsType)
+		terminatedExpr += ";";
+	if ((terminatedExpr.length() > 2) && (terminatedExpr[0] == '@'))
+	{
+		if (terminatedExpr[1] == '!') // Return string as error
+		{
+			int errorEnd = (int)terminatedExpr.IndexOf("@!", 2);
+			if (errorEnd != -1)
+				return terminatedExpr.Substring(1, errorEnd - 1);
+			else
+				return terminatedExpr.Substring(1);
+		}
+		else if (terminatedExpr[1] == '>') // Return string as text
+		{
+			int errorEnd = (int)terminatedExpr.IndexOf("@>", 2);
+			if (errorEnd != -1)
+				return terminatedExpr.Substring(2, errorEnd - 1);
+			else
+				return terminatedExpr.Substring(2);
+		}
+	}
+
+	parser->SetSource(terminatedExpr.c_str(), (int)terminatedExpr.length());
+	parser->Parse(&bfPassInstance);
+
+	BfReducer bfReducer;
+	bfReducer.mAlloc = parser->mAlloc;
+	bfReducer.mSystem = mCompiler->mSystem;
+	bfReducer.mPassInstance = &bfPassInstance;
+	bfReducer.mVisitorPos = BfReducer::BfVisitorPos(parser->mRootNode);
+	bfReducer.mVisitorPos.MoveNext();	
+	bfReducer.mSource = parser;
+	BfAstNode* exprNode = NULL;
+	if (parseAsType)
+		exprNode = bfReducer.CreateTypeRef(parser->mRootNode->mChildArr.GetAs<BfAstNode*>(0));
+	else
+		exprNode = bfReducer.CreateExpression(parser->mRootNode->mChildArr.GetAs<BfAstNode*>(0));
+	parser->Close();
+
+	formatInfo.mCallStackIdx = callStackIdx;
+	
+	CePendingExpr* pendingExpr = new CePendingExpr();	
+	pendingExpr->mParser = parser;
+	pendingExpr->mCallStackIdx = callStackIdx;
+	pendingExpr->mCursorPos = cursorPos;
+	pendingExpr->mExpressionFlags = expressionFlags;
+	pendingExpr->mExprNode = exprNode;
+
+	BfType* explicitType = NULL;
+	String formatFlags;
+	String assignExpr;
+	int assignExprOffset = -1;
+
+	if ((exprNode != NULL) && (exprNode->GetSrcEnd() < (int)expr.length()))
+	{
+		int formatOffset = exprNode->GetSrcEnd();
+		while (formatOffset < (int)expr.length())
+		{
+			char c = expr[formatOffset];
+			if (c == ' ')
+				formatOffset++;
+			else
+				break;
+		}
+
+		formatFlags = Trim(expr.Substring(formatOffset));
+		bool isComplexType = false;
+		for (char c : formatFlags)
+			if (c == '>')
+				isComplexType = true;
+		if (isComplexType)
+		{
+			//explicitType = dbgModule->FindType(expr);
+		}
+
+		if ((explicitType == NULL) && (formatFlags.length() > 0))
+		{
+			String errorString = "Invalid expression";
+ 			if (!ParseFormatInfo(formatFlags, &formatInfo, &bfPassInstance, &assignExprOffset, &assignExpr, &errorString))
+ 			{
+ 				if (formatInfo.mRawString)
+ 					return "";
+ 				bfPassInstance.FailAt(errorString, parser->mSourceData, exprNode->GetSrcEnd(), (int)expr.length() - exprNode->GetSrcEnd());
+ 				formatFlags = "";
+ 			}
+			if (assignExprOffset != -1)
+				assignExprOffset += formatOffset;
+		}
+	}
+
+	if (assignExpr.length() > 0)
+	{
+		String newEvalStr = exprNode->ToString() + " = ";
+		int errorOffset = (int)newEvalStr.length();
+		newEvalStr += assignExpr;
+		String result = Evaluate(newEvalStr, formatInfo, callStackIdx, cursorPos, language, expressionFlags);
+		if (result[0] == '!')
+		{
+			int tabPos = (int)result.IndexOf('\t');
+			if (tabPos > 0)
+			{
+				int errorStart = atoi(result.Substring(1, tabPos - 1).c_str());
+				if (errorStart >= errorOffset)
+				{
+					result = StrFormat("!%d", errorStart - errorOffset + assignExprOffset) + result.Substring(tabPos);
+				}
+			}
+		}
+		return result;
+	}
+
+	pendingExpr->mExplitType = explicitType;
+	pendingExpr->mFormatInfo = formatInfo;
+	String result = EvaluateContinue(pendingExpr, bfPassInstance);
+	if (result == "!pending")
+	{
+		BF_ASSERT(mDebugPendingExpr == NULL);
+		if (mDebugPendingExpr != NULL)
+		{
+			return "!retry"; // We already have a pending
+		}
+		mDebugPendingExpr = pendingExpr;
+	}
+	else
+		delete pendingExpr;
+	return result;
+}
+
+void CeDebugger::ClearBreakpointCache()
+{
+	if (!mCeMachine->mDbgPaused)	
+		mCeMachine->mSpecialCheck = true;
+	mBreakpointFramesDirty = true;
+	mBreakpointCacheDirty = true;
+	for (auto kv : mFileInfo)
+		delete kv.mValue;
+	mFileInfo.Clear();
+}
+
+void CeDebugger::UpdateBreakpointAddrs()
+{
+	for (auto breakpoint : mBreakpoints)
+	{
+		breakpoint->mCurBindAddr = 1;
+	}
+	
+	CeFunction* ceFunction = NULL;
+	if (!mCeMachine->mFunctionIdMap.TryGetValue(mCurDisasmFuncId, &ceFunction))
+		return;
+
+	if (ceFunction->mBreakpointVersion != mBreakpointVersion)
+		UpdateBreakpoints(ceFunction);
+
+	for (auto kv : ceFunction->mBreakpoints)
+		kv.mValue.mBreakpoint->mCurBindAddr = ((intptr)ceFunction->mId << 32) | kv.mKey;
+}
+
+void CeDebugger::UpdateBreakpointCache()
+{
+	AutoCrit autoCrit(mCeMachine->mCritSect);
+
+	mBreakpointCacheDirty = false;
+	if (!mFileInfo.IsEmpty())
+		return;	
+	for (int i = 0; i < (int)mBreakpoints.mSize; i++)
+	{
+		auto breakpoint = mBreakpoints[i];
+		breakpoint->mIdx = i;
+		String fileName = breakpoint->mFilePath;
+		fileName = FixPathAndCase(fileName);
+		CeFileInfo** valuePtr;
+		CeFileInfo* fileInfo = NULL;
+		if (mFileInfo.TryAdd(fileName, NULL, &valuePtr))
+		{
+			fileInfo = new CeFileInfo();
+			*valuePtr = fileInfo;
+		}
+		else
+			fileInfo = *valuePtr;
+		fileInfo->mOrderedBreakpoints.Add(breakpoint);
+	}
+
+	for (auto kv : mFileInfo)
+	{
+		kv.mValue->mOrderedBreakpoints.Sort([](CeBreakpoint* lhs, CeBreakpoint* rhs)
+			{
+				return lhs->mLineNum < rhs->mLineNum;
+			});
+	}
+}
+
+static int CompareBreakpoint(CeBreakpoint* breakpoint, const int& lineNum)
+{
+	return breakpoint->mRequestedLineNum - lineNum;
+}
+
+void CeDebugger::UpdateBreakpoints(CeFunction* ceFunction)
+{
+	AutoCrit autoCrit(mCeMachine->mCritSect);
+
+	UpdateBreakpointCache();
+
+	ceFunction->UnbindBreakpoints();		
+
+	String path;
+	int scope = -1;
+	CeFileInfo* ceFileInfo = NULL;
+
+	BitSet usedBreakpointSet(mBreakpoints.mSize);
+
+	for (auto& emitEntry : ceFunction->mEmitTable)
+	{
+		if (emitEntry.mScope != scope)
+		{
+			if (emitEntry.mScope != -1)
+			{
+				path = FixPathAndCase(ceFunction->mDbgScopes[emitEntry.mScope].mFilePath);
+				if (!mFileInfo.TryGetValue(path, &ceFileInfo))
+					ceFileInfo = NULL;
+			}
+			else
+				ceFileInfo = NULL;
+			scope = emitEntry.mScope;
+		}
+
+		if (ceFileInfo != NULL)
+		{
+			int idx = ceFileInfo->mOrderedBreakpoints.BinarySearchAlt<int>(emitEntry.mLine, CompareBreakpoint);
+			if (idx < 0)
+				idx = ~idx - 1;
+
+			while (idx > 0)
+			{
+				auto breakpoint = ceFileInfo->mOrderedBreakpoints[idx - 1];
+				if (breakpoint->mLineNum < emitEntry.mLine)
+					break;
+				idx--;
+			}
+
+			int tryBindCount = 0;
+			int bestRequestedBindLine = 0;
+
+			while ((idx >= 0) && (idx < ceFileInfo->mOrderedBreakpoints.mSize))
+			{				
+				auto breakpoint = ceFileInfo->mOrderedBreakpoints[idx];
+				if (usedBreakpointSet.IsSet(breakpoint->mIdx))
+				{
+					idx++;
+					continue;
+				}
+				CeBreakpointBind* breakpointBind = NULL;
+
+				if (tryBindCount > 0)
+				{
+					if (breakpoint->mRequestedLineNum > bestRequestedBindLine)
+						break;
+				}
+				else
+				{
+					int lineDiff = emitEntry.mLine - breakpoint->mLineNum;
+					if ((lineDiff < 0) || (lineDiff > 4))
+						break;
+					
+					if ((breakpoint->mHasBound) && (lineDiff != 0))
+						break;
+					
+					bestRequestedBindLine = breakpoint->mRequestedLineNum;
+				}
+
+				tryBindCount++;
+
+				int codePos = emitEntry.mCodePos;
+				if (breakpoint->mInstrOffset > 0)
+				{
+					int instrOffsetLeft = breakpoint->mInstrOffset;
+					while (instrOffsetLeft > 0)
+					{
+						auto& opRef = *(CeOp*)(&ceFunction->mCode[codePos]);
+						int instSize = mCeMachine->GetInstSize(ceFunction, codePos);
+						codePos += instSize;
+						instrOffsetLeft--;
+					}
+				}
+
+				if (ceFunction->mBreakpoints.TryAdd(codePos, NULL, &breakpointBind))
+				{
+					usedBreakpointSet.Set(breakpoint->mIdx);
+					breakpoint->mLineNum = emitEntry.mLine;
+					breakpoint->mHasBound = true;
+
+					auto& opRef = *(CeOp*)(&ceFunction->mCode[codePos]);
+					breakpointBind->mPrevOpCode = opRef;
+					breakpointBind->mBreakpoint = breakpoint;
+					opRef = CeOp_DbgBreak;
+				}
+
+				idx++;
+			}
+		}
+	}
+
+	ceFunction->mBreakpointVersion = mBreakpointVersion;
+}
+
+CeDbgTypeInfo* CeDebugger::GetDbgTypeInfo(int typeId)
+{
+	CeDbgTypeInfo* dbgTypeInfo = NULL;
+	if (mDbgTypeInfoMap.TryAdd(typeId, NULL, &dbgTypeInfo))
+	{
+		auto type = mCeMachine->mCeModule->mContext->FindTypeById(typeId);
+		if (type == NULL)
+		{
+			mDbgTypeInfoMap.Remove(typeId);
+			return NULL;
+		}
+		dbgTypeInfo->mType = type;		
+
+		auto typeInst = type->ToTypeInstance();
+		if (typeInst != NULL)
+		{			
+			for (int fieldIdx = 0; fieldIdx < typeInst->mFieldInstances.mSize; fieldIdx++)
+			{
+				auto& fieldInst = typeInst->mFieldInstances[fieldIdx];
+				if (fieldInst.mDataIdx > 0)
+				{
+					while (fieldInst.mDataIdx >= dbgTypeInfo->mFieldOffsets.mSize)
+						dbgTypeInfo->mFieldOffsets.Add(CeDbgFieldEntry());
+					dbgTypeInfo->mFieldOffsets[fieldInst.mDataIdx].mType = fieldInst.mResolvedType;
+					dbgTypeInfo->mFieldOffsets[fieldInst.mDataIdx].mDataOffset = fieldInst.mDataOffset;
+				}
+
+				if (fieldInst.mConstIdx != -1)
+				{
+					auto constant = typeInst->mConstHolder->GetConstantById(fieldInst.mConstIdx);
+					if ((constant != NULL) && (BfIRConstHolder::IsInt(constant->mTypeCode)))
+					{
+						CeDbgTypeInfo::ConstIntEntry constIntEntry;
+						constIntEntry.mFieldIdx = fieldIdx;
+						constIntEntry.mVal = constant->mInt64;
+						dbgTypeInfo->mConstIntEntries.Add(constIntEntry);
+					}
+				}
+			}
+		}
+
+	}
+	return dbgTypeInfo;
+}
+
+CeDbgTypeInfo* CeDebugger::GetDbgTypeInfo(BfIRType irType)
+{
+	if ((irType.mKind == BfIRTypeData::TypeKind_TypeId) || (irType.mKind == BfIRTypeData::TypeKind_TypeInstId))
+		return GetDbgTypeInfo(irType.mId);
+	if (irType.mKind == BfIRTypeData::TypeKind_TypeInstPtrId)
+	{
+		auto type = mCeMachine->mCeModule->mContext->FindTypeById(irType.mId);
+		if (type->IsObjectOrInterface())
+			return GetDbgTypeInfo(irType.mId);
+		else
+			return GetDbgTypeInfo(mCeMachine->mCeModule->CreatePointerType(type)->mTypeId);
+	}
+	return NULL;
+}
+
+static bool IsNormalChar(uint32 c)
+{
+	return (c < 0x80);
+}
+
+template <typename T>
+static String IntTypeToString(T val, const StringImpl& name, DwDisplayInfo* displayInfo, CeFormatInfo& formatInfo)
+{
+	auto intDisplayType = displayInfo->mIntDisplayType;
+	if (formatInfo.mDisplayType == DwDisplayType_Decimal)
+		intDisplayType = DwIntDisplayType_Decimal;
+	else if (formatInfo.mDisplayType == DwDisplayType_HexUpper)
+		intDisplayType = DwIntDisplayType_HexadecimalUpper;
+	else if (formatInfo.mDisplayType == DwDisplayType_HexLower)
+		intDisplayType = DwIntDisplayType_HexadecimalLower;
+
+	if (intDisplayType == DwIntDisplayType_Binary)
+	{
+		String binary;
+		for (int i = 0; i < sizeof(T) * 8; i++)
+		{
+			if ((i != 0) && (i % 4 == 0))
+				binary = "'" + binary;
+
+			if ((i != 0) && (i % 16 == 0))
+				binary = "'" + binary;
+
+			binary = ((val & ((T)1 << i)) ? "1" : "0") + binary;
+
+		}
+		return StrFormat("0b'%s\n%s", binary.c_str(), name.c_str());
+	}
+
+	if (intDisplayType == DwIntDisplayType_Octal)
+	{
+		String format;
+		if (sizeof(T) == 8)
+		{
+			format = StrFormat("0o%%lo\n%s", name.c_str());
+		}
+		else
+			format = StrFormat("0o%%0%do\n%s", sizeof(val) * 2, name.c_str());
+		return StrFormat(format.c_str(), (std::make_unsigned<T>::type)(val));
+	}
+
+	if (intDisplayType == DwIntDisplayType_HexadecimalUpper)
+	{
+		String format;
+		if (sizeof(T) == 8)
+		{
+			format = StrFormat("0x%%l@\n%s", name.c_str());
+		}
+		else
+			format = StrFormat("0x%%0%dX\n%s", sizeof(val) * 2, name.c_str());
+		return StrFormat(format.c_str(), (std::make_unsigned<T>::type)(val));
+	}
+
+	//TODO: Implement HexadecimalLower
+	if (intDisplayType == DwIntDisplayType_HexadecimalLower)
+	{
+		String format;
+		if (sizeof(T) == 8)
+		{
+			format = StrFormat("0x%%l@\n%s", name.c_str());
+		}
+		else
+			format = StrFormat("0x%%0%dX\n%s", sizeof(val) * 2, name.c_str());
+		return StrFormat(format.c_str(), (std::make_unsigned<T>::type)(val));
+	}
+
+	if (std::is_unsigned<T>::value)
+	{
+		if (sizeof(T) == 8)
+		{
+			if (val > 0x7FFFFFFFF)
+				return StrFormat("%llu\n%s\n:editVal\t%lluUL", val, name.c_str(), val);
+			else
+				return StrFormat("%llu\n%s", val, name.c_str());
+		}
+		else
+			return StrFormat("%u\n%s", val, name.c_str());
+	}
+	else
+	{
+		if (sizeof(T) == 8)
+		{
+			if ((val > 0x7FFFFFFFF) || (val < -0x80000000LL))
+				return StrFormat("%lld\n%s\n:editVal\t%lldL", val, name.c_str(), val);
+			else
+				return StrFormat("%lld\n%s", val, name.c_str(), val);
+		}
+		else
+			return StrFormat("%d\n%s", val, name.c_str());
+	}
+}
+
+DwDisplayInfo* CeDebugger::GetDisplayInfo(const StringImpl& referenceId)
+{
+	DwDisplayInfo* displayInfo = &mDebugManager->mDefaultDisplayInfo;
+	if (!referenceId.empty())
+	{
+		mDebugManager->mDisplayInfos.TryGetValue(referenceId, &displayInfo);
+	}
+	return displayInfo;
+}
+
+String CeDebugger::GetMemberList(BfType* type, addr_ce addr, addr_ce addrInst, bool isStatic)
+{
+	auto typeInst = type->ToTypeInstance();
+	if (typeInst == NULL)
+		return "";
+	
+	auto module = typeInst->mModule;
+
+	String retVal;
+	int fieldCount = 0;
+
+	if ((typeInst->mBaseType != NULL) &&
+		(!typeInst->mBaseType->IsInstanceOf(mCompiler->mBfObjectTypeDef)) &&
+		(!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;
+	bool didStaticCtor = ceContext->mStaticCtorExecSet.Contains(type->mTypeId);
+
+	bool hasStaticFields = false;
+	for (auto& fieldInst : typeInst->mFieldInstances)
+	{
+		auto fieldDef = fieldInst.GetFieldDef();
+		if (fieldDef == NULL)
+			continue;
+
+		if (fieldDef->mIsStatic != isStatic)
+		{
+			if (fieldDef->mIsStatic)
+				hasStaticFields = true;
+			continue;
+		}
+
+		if (fieldCount > 0)
+			retVal += "\n";
+
+		retVal += fieldDef->mName;
+		if (fieldDef->mIsStatic)
+		{
+			if (didStaticCtor)
+				retVal += StrFormat("\tcomptype(%d).%s", type->mTypeId, fieldDef->mName.c_str());
+			else
+				retVal += StrFormat("\tcomptype(%d).%s", type->mTypeId, fieldDef->mName.c_str());
+		}
+		else
+		{
+			retVal += "\t";
+			retVal += fieldDef->mName;			
+			retVal += StrFormat(",this=%d@0x%X", typeInst->mTypeId, addrInst);
+		}
+
+		fieldCount++;
+	}
+
+	if (hasStaticFields)
+	{
+		if (fieldCount > 0)
+			retVal += "\n";
+			
+		retVal += StrFormat("Static values\tcomptype(%d)", typeInst->mTypeId);
+	}
+
+	return retVal;
+}
+
+bool CeDebugger::ParseFormatInfo(const StringImpl& formatInfoStr, CeFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExprString, String* errorString, BfTypedValue contextTypedValue)
+{
+	String formatFlags = formatInfoStr;
+	if (assignExprOffset != NULL)
+		*assignExprOffset = -1;
+
+	while (formatFlags.length() > 0)
+	{
+		formatFlags = Trim(formatFlags);
+		if (formatFlags.IsEmpty())
+			break;
+		if (formatFlags[0] != ',')
+		{
+			return false;
+		}
+		else
+		{
+			int nextComma = (int)formatFlags.IndexOf(',', 1);
+			int quotePos = (int)formatFlags.IndexOf('"', 1);
+			if ((quotePos != -1) && (quotePos < nextComma))
+			{
+				int nextQuotePos = (int)formatFlags.IndexOf('"', quotePos + 1);
+				if (nextQuotePos != -1)
+					nextComma = (int)formatFlags.IndexOf(',', nextQuotePos + 1);
+			}
+			if (nextComma == -1)
+				nextComma = (int)formatFlags.length();
+
+			String formatCmd = formatFlags.Substring(1, nextComma - 1);
+			formatCmd = Trim(formatCmd);
+			bool hadError = false;
+
+			if (strncmp(formatCmd.c_str(), "this=", 5) == 0)
+			{
+				formatCmd = formatFlags.Substring(1);
+				formatCmd = Trim(formatCmd);
+				String thisExpr = formatCmd.Substring(5);
+				if (thisExpr.empty())
+					break;
+				CeEvaluationContext dbgEvaluationContext(this, thisExpr, formatInfo);
+				formatInfo->mExplicitThis = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
+				if (dbgEvaluationContext.HadError())
+				{
+					if (errorString != NULL)
+						*errorString = dbgEvaluationContext.GetErrorStr();
+					return false;
+				}
+				formatFlags = thisExpr.Substring(dbgEvaluationContext.mExprString.GetLength());
+				continue;
+			}
+			else if (strncmp(formatCmd.c_str(), "count=", 6) == 0)
+			{
+				formatCmd = formatFlags.Substring(1);
+				formatCmd = Trim(formatCmd);
+				String countExpr = formatCmd.Substring(6);
+				if (countExpr.empty())
+					break;
+				CeEvaluationContext dbgEvaluationContext(this, countExpr, formatInfo);
+				BfTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
+				if ((countValue) && (countValue.mType->IsInteger()))
+					formatInfo->mOverrideCount = (intptr)ValueToInt(countValue);
+				if (dbgEvaluationContext.HadError())
+				{
+					if (errorString != NULL)
+						*errorString = dbgEvaluationContext.GetErrorStr();
+					return false;
+				}
+				formatFlags = countExpr.Substring(dbgEvaluationContext.mExprString.GetLength());
+				continue;
+			}
+			else if (strncmp(formatCmd.c_str(), "maxcount=", 9) == 0)
+			{
+				formatCmd = formatFlags.Substring(1);
+				formatCmd = Trim(formatCmd);
+				String countExpr = formatCmd.Substring(9);
+				if (countExpr.empty())
+					break;
+				CeEvaluationContext dbgEvaluationContext(this, countExpr, formatInfo);
+				BfTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
+				if ((countValue) && (countValue.mType->IsInteger()))
+					formatInfo->mMaxCount = (intptr)ValueToInt(countValue);
+				if (dbgEvaluationContext.HadError())
+				{
+					if (errorString != NULL)
+						*errorString = dbgEvaluationContext.GetErrorStr();
+					return false;
+				}
+				formatFlags = countExpr.Substring(dbgEvaluationContext.mExprString.GetLength());
+				continue;
+			}
+			else if (strncmp(formatCmd.c_str(), "arraysize=", 10) == 0)
+			{
+				formatCmd = formatFlags.Substring(1);
+				formatCmd = Trim(formatCmd);
+				String countExpr = formatCmd.Substring(10);
+				if (countExpr.empty())
+					break;
+				CeEvaluationContext dbgEvaluationContext(this, countExpr, formatInfo);
+				BfTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
+				if ((countValue) && (countValue.mType->IsInteger()))
+					formatInfo->mArrayLength = (intptr)ValueToInt(countValue);
+				if (dbgEvaluationContext.HadError())
+				{
+					if (errorString != NULL)
+						*errorString = dbgEvaluationContext.GetErrorStr();
+					return false;
+				}
+				formatFlags = countExpr.Substring(dbgEvaluationContext.mExprString.GetLength());
+				continue;
+			}
+			else if (strncmp(formatCmd.c_str(), "assign=", 7) == 0)
+			{
+				formatCmd = formatFlags.Substring(1);
+				formatCmd = Trim(formatCmd);
+				String assignExpr = formatCmd.Substring(7);
+				if (assignExpr.empty())
+					break;
+				CeEvaluationContext dbgEvaluationContext(this, assignExpr, formatInfo);
+				if (dbgEvaluationContext.HadError())
+				{
+					if (errorString != NULL)
+						*errorString = dbgEvaluationContext.GetErrorStr();
+					return false;
+				}
+				if (assignExprOffset != NULL)
+				{
+					//TODO: Keep track of the offset directly, this is a hack
+					*assignExprOffset = (int)formatInfoStr.IndexOf("assign=") + 7;
+				}
+				if (assignExprString != NULL)
+					*assignExprString = dbgEvaluationContext.mExprNode->ToString();
+				formatFlags = assignExpr.Substring(dbgEvaluationContext.mExprNode->GetSrcEnd());
+				continue;
+			}
+			else if (strncmp(formatCmd.c_str(), "refid=", 6) == 0)
+			{
+				formatInfo->mReferenceId = formatCmd.Substring(6);
+				if (formatInfo->mReferenceId[0] == '\"')
+					formatInfo->mReferenceId = formatInfo->mReferenceId.Substring(1, formatInfo->mReferenceId.length() - 2);
+			}
+			else if (strncmp(formatCmd.c_str(), "_=", 2) == 0)
+			{
+				formatInfo->mSubjectExpr = formatCmd.Substring(2);
+				if (formatInfo->mSubjectExpr[0] == '\"')
+					formatInfo->mSubjectExpr = formatInfo->mSubjectExpr.Substring(1, formatInfo->mSubjectExpr.length() - 2);
+			}
+			else if (strncmp(formatCmd.c_str(), "expectedType=", 13) == 0)
+			{
+				formatInfo->mExpectedType = formatCmd.Substring(13);
+				if (formatInfo->mExpectedType[0] == '\"')
+					formatInfo->mExpectedType = formatInfo->mExpectedType.Substring(1, formatInfo->mExpectedType.length() - 2);
+			}
+			else if (strncmp(formatCmd.c_str(), "namespaceSearch=", 16) == 0)
+			{
+				formatInfo->mNamespaceSearch = formatCmd.Substring(16);
+				if (formatInfo->mNamespaceSearch[0] == '\"')
+					formatInfo->mNamespaceSearch = formatInfo->mNamespaceSearch.Substring(1, formatInfo->mNamespaceSearch.length() - 2);
+			}
+			else if (formatCmd == "d")
+			{
+				formatInfo->mDisplayType = DwDisplayType_Decimal;
+			}
+			else if (formatCmd == "x")
+			{
+				formatInfo->mDisplayType = DwDisplayType_HexLower;
+			}
+			else if (formatCmd == "X")
+			{
+				formatInfo->mDisplayType = DwDisplayType_HexUpper;
+			}
+			else if (formatCmd == "s")
+			{
+				formatInfo->mHidePointers = true;
+				formatInfo->mDisplayType = DwDisplayType_Ascii;
+			}
+			else if (formatCmd == "s8")
+			{
+				formatInfo->mHidePointers = true;
+				formatInfo->mDisplayType = DwDisplayType_Utf8;
+			}
+			else if (formatCmd == "s16")
+			{
+				formatInfo->mHidePointers = true;
+				formatInfo->mDisplayType = DwDisplayType_Utf16;
+			}
+			else if (formatCmd == "s32")
+			{
+				formatInfo->mHidePointers = true;
+				formatInfo->mDisplayType = DwDisplayType_Utf32;
+			}
+			else if (formatCmd == "nd")
+			{
+				formatInfo->mIgnoreDerivedClassInfo = true;
+			}
+			else if (formatCmd == "na")
+			{
+				formatInfo->mHidePointers = true;
+			}
+			else if (formatCmd == "nm")
+			{
+				formatInfo->mNoMembers = true;
+			}
+			else if (formatCmd == "ne")
+			{
+				formatInfo->mNoEdit = true;
+			}
+			else if (formatCmd == "nv")
+			{
+				formatInfo->mNoVisualizers = true;
+			}
+			else if (formatCmd == "rawStr")
+			{
+				formatInfo->mRawString = true;
+			}
+			else if (((!formatCmd.IsEmpty()) && ((formatCmd[0] >= '0') && (formatCmd[0] <= '9'))) ||
+				(formatCmd.StartsWith("(")))
+			{
+				String countExpr = formatCmd;
+				if (countExpr.empty())
+					break;
+				CeEvaluationContext dbgEvaluationContext(this, countExpr, formatInfo);
+				BfTypedValue countValue = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
+				if ((countValue) && (countValue.mType->IsInteger()))
+					formatInfo->mArrayLength = (intptr)ValueToInt(countValue);
+				if (dbgEvaluationContext.HadError())
+				{
+					if (errorString != NULL)
+						*errorString = dbgEvaluationContext.GetErrorStr();
+					return false;
+				}
+				formatFlags = dbgEvaluationContext.mExprString;
+				continue;
+			}
+			else
+				hadError = true;
+
+			if (hadError)
+			{
+				if (errorString != NULL)
+					*errorString = "Invalid format flags";
+				return false;
+			}
+
+			formatFlags = formatFlags.Substring(nextComma);
+		}
+	}
+	return true;
+}
+
+String CeDebugger::MaybeQuoteFormatInfoParam(const StringImpl& str)
+{
+	bool needsQuote = false;
+	for (int i = 0; i < (int)str.length(); i++)
+	{
+		char c = str[i];
+		if (c == ',')
+			needsQuote = true;
+	}
+	if (!needsQuote)
+		return str;
+
+	String qStr = "\"";
+	qStr += str;
+	qStr += "\"";
+	return qStr;
+}
+
+BfTypedValue CeDebugger::EvaluateInContext(const BfTypedValue& contextTypedValue, const StringImpl& subExpr, CeFormatInfo* formatInfo, String* outReferenceId, String* outErrors)
+{	
+	CeEvaluationContext dbgEvaluationContext(this, subExpr, formatInfo, contextTypedValue);	
+// 	if (formatInfo != NULL)
+// 	{
+// 		dbgEvaluationContext.mDbgExprEvaluator->mSubjectExpr = formatInfo->mSubjectExpr;
+// 	}
+	//dbgEvaluationContext.mDbgExprEvaluator->mReferenceId = outReferenceId;
+
+	SetAndRestoreValue<CeEvaluationContext*> prevEvalContext(mCurEvaluationContext, &dbgEvaluationContext);
+
+	//mCountResultOverride = -1;
+	auto result = dbgEvaluationContext.EvaluateInContext(contextTypedValue);
+// 	if ((formatInfo != NULL) && (dbgEvaluationContext.mDbgExprEvaluator->mCountResultOverride != -1))
+// 		formatInfo->mOverrideCount = dbgEvaluationContext.mDbgExprEvaluator->mCountResultOverride;
+	if (dbgEvaluationContext.mPassInstance->HasFailed())
+	{
+		if (outErrors != NULL)
+		{
+			int errIdx = 0;
+			for (auto err : dbgEvaluationContext.mPassInstance->mErrors)
+			{
+				if (errIdx > 0)
+					(*outErrors) += "\n";
+				(*outErrors) += err->mError;
+				errIdx++;
+			}
+		}
+		return BfTypedValue();
+	}
+	return result;
+}
+
+void CeDebugger::DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors)
+{
+	bool onlyMemError = errors.StartsWith("Failed to read") && !errors.Contains('\n');
+	if ((!debugVis->mShowedError) && (!onlyMemError))
+	{
+		debugVis->mShowedError = true;
+		String errStr = StrFormat("DbgVis '%s' failed while evaluating condition '%s'\n", debugVis->mName.c_str(), evalString.c_str());
+		String spacedErrors = errors;
+		spacedErrors.Insert(0, " ");
+		spacedErrors.Replace("\n", "\n ");
+		errStr += spacedErrors;
+		OutputMessage(errStr);
+	}
+}
+
+bool CeDebugger::EvalCondition(DebugVisualizerEntry* debugVis, BfTypedValue typedVal, CeFormatInfo& formatInfo, const StringImpl& condition, const Array<String>& dbgVisWildcardCaptures, String& errorStr)
+{
+	auto ceModule = mCeMachine->mCeModule;
+
+	CeFormatInfo displayStrFormatInfo = formatInfo;
+	displayStrFormatInfo.mHidePointers = false;
+	displayStrFormatInfo.mRawString = false;
+
+	String errors;
+	const String conditionStr = mDebugManager->mDebugVisualizers->DoStringReplace(condition, dbgVisWildcardCaptures);
+	BfTypedValue evalResult = EvaluateInContext(typedVal, conditionStr, &displayStrFormatInfo, NULL, &errors);
+	if ((!evalResult) || (!evalResult.mType->IsBoolean()))
+	{
+		if (formatInfo.mRawString)
+			return false;
+
+		errorStr += "<DbgVis Failed>";
+		DbgVisFailed(debugVis, conditionStr, errors);
+		return false;
+	}
+
+	evalResult = ceModule->LoadValue(evalResult);
+	if (auto constant = ceModule->mBfIRBuilder->GetConstant(evalResult.mValue))
+	{
+		if (constant->mTypeCode == BfTypeCode_Boolean)
+			return constant->mBool;
+	}
+
+	return false;
+}
+
+String CeDebugger::GetArrayItems(DebugVisualizerEntry* debugVis, BfType* valueType, BfTypedValue& curNode, int& count, String* outContinuationData)
+{
+	CeEvaluationContext conditionEvaluationContext(this, debugVis->mCondition);
+	auto ceModule = mCeMachine->mCeModule;
+
+	String addrs;
+
+	bool checkLeft = true;
+
+	addr_ce curNodeAddr = 0;
+
+	int usedCount = 0;
+	while (usedCount < count)
+	{
+		if ((!curNode) || (!curNode.mType->IsPointer()))
+			break;
+		curNode = ceModule->LoadValue(curNode);
+
+		BfTypedValue condVal = conditionEvaluationContext.EvaluateInContext(curNode);
+		if (!condVal)
+			break;
+		
+		auto ceTypedVal = GetAddr(curNode);
+		if (!ceTypedVal)
+			break;
+		
+		if (ValueToInt(condVal) != 0)
+		{
+			auto val = curNode;
+			if (valueType == NULL)
+			{
+				//String typeAddr =  val.mType->ToStringRaw();
+				String typeAddr = StrFormat("comptype(%d)", val.mType->mTypeId);
+				// RPad
+				typeAddr.Append(' ', sizeof(addr_ce) * 2 - (int)typeAddr.length());
+				addrs += typeAddr;
+			}
+
+			String addr = EncodeDataPtr(ceTypedVal.mAddr, false);
+			addrs += addr;
+			usedCount++;
+		}
+		auto elemType = curNode.mType->GetUnderlyingType();
+		curNodeAddr = ceTypedVal.mAddr + elemType->GetStride();
+		curNode.mValue = ceModule->mBfIRBuilder->CreateIntToPtr(curNodeAddr, ceModule->mBfIRBuilder->MapType(curNode.mType));
+	}
+	count = usedCount;
+
+	if (outContinuationData != NULL)
+	{
+		*outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(valueType, false) +
+			EncodeDataPtr(curNode.mType, false) + EncodeDataPtr(curNodeAddr, false);
+	}
+
+	return addrs;
+}
+
+String CeDebugger::GetLinkedListItems(DebugVisualizerEntry* debugVis, addr_ce endNodePtr, BfType* valueType, BfTypedValue& curNode, int& count, String* outContinuationData)
+{
+	CeEvaluationContext nextEvaluationContext(this, debugVis->mNextPointer);
+	CeEvaluationContext valueEvaluationContext(this, debugVis->mValuePointer);
+
+	String addrs;
+
+	bool checkLeft = true;
+
+	//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);
+// 	}
+
+	return addrs;
+}
+
+String CeDebugger::GetDictionaryItems(DebugVisualizerEntry* debugVis, BfTypedValue dictValue, int bucketIdx, int nodeIdx, int& count, String* outContinuationData)
+{	
+	CeEvaluationContext nextEvaluationContext(this, debugVis->mNextPointer);
+
+	BfTypedValue bucketsPtr = EvaluateInContext(dictValue, debugVis->mBuckets);
+	BfTypedValue entriesPtr = EvaluateInContext(dictValue, debugVis->mEntries);
+	if ((!bucketsPtr) || (!entriesPtr))
+	{
+		count = -1;
+		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<int>(bucketsPtr.mPtr + bucketIdx * sizeof(int32));
+// 			else
+// 				nodeIdx = (int)ReadMemory<int64>(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);
+// 	}
+
+	return addrs;
+}
+
+String CeDebugger::GetTreeItems(DebugVisualizerEntry* debugVis, Array<addr_ce>& parentList, BfType*& valueType, BfTypedValue& curNode, int count, String* outContinuationData)
+{
+	CeEvaluationContext leftEvaluationContext(this, debugVis->mLeftPointer);
+	CeEvaluationContext rightEvaluationContext(this, debugVis->mRightPointer);
+	CeEvaluationContext valueEvaluationContext(this, debugVis->mValuePointer);
+
+	CeEvaluationContext conditionEvaluationContext(this, debugVis->mCondition);
+
+	String addrs;
+
+	//TODO:
+// 	bool checkLeft = true;
+// 
+// 	if ((curNode.mPtr & 2) != 0) // Flag from continuation
+// 	{
+// 		checkLeft = false;
+// 		curNode.mPtr &= (addr_ce)~2;
+// 	}
+// 
+// 	HashSet<intptr> seenAddrs;
+// 
+// 	for (int mapIdx = 0; mapIdx < count; mapIdx++)
+// 	{
+// 		BfTypedValue readNode;
+// 		while (true)
+// 		{
+// 			bool checkNode = (curNode.mPtr & 1) == 0;
+// 
+// 			readNode = curNode;
+// 			readNode.mPtr &= (addr_ce)~1;
+// 
+// 			if (checkLeft)
+// 			{
+// 				BfTypedValue leftValue = leftEvaluationContext.EvaluateInContext(readNode);
+// 				bool isEmpty = leftValue.mPtr == NULL;
+// 				if ((leftValue) && (conditionEvaluationContext.HasExpression()))
+// 				{
+// 					auto condValue = conditionEvaluationContext.EvaluateInContext(leftValue);
+// 					if (condValue)
+// 						isEmpty = !condValue.mBool;
+// 				}
+// 				if (isEmpty)
+// 				{
+// 					checkLeft = false;
+// 					break; // Handle node
+// 				}
+// 
+// 				parentList.push_back(curNode.mPtr);
+// 				curNode = leftValue;
+// 			}
+// 			else if (checkNode)
+// 			{
+// 				break; // Handle node
+// 			}
+// 			else
+// 			{
+// 				BfTypedValue rightValue = rightEvaluationContext.EvaluateInContext(readNode);
+// 				bool isEmpty = rightValue.mPtr == NULL;
+// 				if ((rightValue) && (conditionEvaluationContext.HasExpression()))
+// 				{
+// 					auto condValue = conditionEvaluationContext.EvaluateInContext(rightValue);
+// 					if (condValue)
+// 						isEmpty = !condValue.mBool;
+// 				}
+// 				if (!isEmpty)
+// 				{
+// 					curNode = rightValue;
+// 					checkLeft = true;
+// 				}
+// 				else
+// 				{
+// 					if (parentList.size() == 0)
+// 					{
+// 						// Failed
+// 						break;
+// 					}
+// 
+// 					curNode.mPtr = parentList.back();
+// 					parentList.pop_back();
+// 					continue; // Don't check against seenAddrs
+// 				}
+// 			}
+// 
+// 			if (!seenAddrs.Add(curNode.mPtr))
+// 			{
+// 				// Failed!
+// 				return "";
+// 			}
+// 		}
+// 
+// 
+// 		BfTypedValue val = valueEvaluationContext.EvaluateInContext(readNode);
+// 		if (valueType == NULL)
+// 			valueType = val.mType;
+// 
+// 		String addr = EncodeDataPtr(val.mPtr, false);
+// 		addrs += addr;
+// 
+// 		curNode.mPtr |= 1; // Node handled
+// 	}
+// 
+// 	if (!checkLeft)
+// 		curNode.mPtr |= 2;
+// 
+// 	if (outContinuationData != NULL)
+// 	{
+// 		*outContinuationData += EncodeDataPtr(debugVis, false) + EncodeDataPtr(valueType, false) + EncodeDataPtr(curNode.mType, false) + EncodeDataPtr(curNode.mPtr, false);
+// 		for (auto parent : parentList)
+// 			*outContinuationData += EncodeDataPtr(parent, false);
+// 	}
+
+	return addrs;
+}
+
+String CeDebugger::GetCollectionContinuation(const StringImpl& continuationData, int callStackIdx, int count)
+{	
+	if (!mCeMachine->mDbgPaused)
+		return "";
+
+	auto ceModule = mCeMachine->mCeModule;
+	const char* dataPtr = continuationData.c_str();
+	DebugVisualizerEntry* debugVis = (DebugVisualizerEntry*)DecodeLocalDataPtr(dataPtr);
+
+	if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_TreeItems)
+	{
+		//TODO:
+// 		DbgType* valueType = (DbgType*)DecodeLocalDataPtr(dataPtr);
+// 		BfTypedValue curNode;
+// 		curNode.mType = (DbgType*)DecodeLocalDataPtr(dataPtr);
+// 		curNode.mPtr = DecodeTargetDataPtr(dataPtr);
+// 
+// 		Array<addr_ce> parentList;
+// 		String newContinuationData;
+// 		while (*dataPtr != 0)
+// 			parentList.push_back(DecodeTargetDataPtr(dataPtr));
+// 
+// 		String retVal = GetTreeItems(dbgCompileUnit, debugVis, parentList, valueType, curNode, count, &newContinuationData);
+// 		retVal += "\n" + newContinuationData;
+// 		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;
+	}
+	else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Array)
+	{
+		BfType* valueType = (BfType*)DecodeLocalDataPtr(dataPtr);		
+		
+		auto 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 = GetArrayItems(debugVis, valueType, curNode, count, &newContinuationData);
+		retVal += "\n" + newContinuationData;
+		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;
+	}
+
+	return "";
+}
+
+CeTypedValue CeDebugger::GetAddr(BfConstant* constant)
+{
+	auto module = mCeMachine->mCeModule;
+	auto ceContext = mCeMachine->mCurContext;
+
+	if (constant->mConstType == BfConstType_GlobalVar)
+	{
+		auto globalVar = (BfGlobalVar*)constant;
+
+		String varName(globalVar->mName);
+	
+		if (varName.StartsWith("__bfStrObj"))
+		{			
+			int stringId = atoi(varName.c_str() + 10);
+			auto addr = ceContext->GetString(stringId);
+			return CeTypedValue(addr, globalVar->mType);
+		}
+		else if (varName.StartsWith("__bfStrData"))
+		{
+			auto stringType = module->ResolveTypeDef(module->mCompiler->mStringTypeDef)->ToTypeInstance();
+			int stringId = atoi(varName.c_str() + 11);
+			auto addr = ceContext->GetString(stringId) + stringType->mInstSize;
+			return CeTypedValue(addr, globalVar->mType);
+		}
+
+		CeStaticFieldInfo* fieldInfo = NULL;
+		if (ceContext->mStaticFieldMap.TryAdd(globalVar->mName, NULL, &fieldInfo))
+		{
+			auto dbgTypeInfo = GetDbgTypeInfo(globalVar->mType);
+			if (dbgTypeInfo != NULL)
+			{
+				uint8* ptr = ceContext->CeMalloc(dbgTypeInfo->mType->mSize);
+				if (dbgTypeInfo->mType->mSize > 0)
+					memset(ptr, 0, dbgTypeInfo->mType->mSize);
+				fieldInfo->mAddr = (addr_ce)(ptr - ceContext->mMemory.mVals);
+			}
+			else
+				fieldInfo->mAddr = 0;
+		}
+		return CeTypedValue(fieldInfo->mAddr, globalVar->mType);
+	}
+	else if (constant->mConstType == BfConstType_AggCE)
+	{
+		auto aggCE = (BfConstantAggCE*)constant;
+		return CeTypedValue(aggCE->mCEAddr, aggCE->mType);
+	}
+	else if (constant->mConstType == BfConstType_BitCast)
+	{
+		auto constBitCast = (BfConstantBitCast*)constant;
+		auto val = GetAddr(module->mBfIRBuilder->GetConstantById(constBitCast->mTarget));
+		if (!val)
+			return val;
+		return CeTypedValue(val.mAddr, constBitCast->mToType);
+	}
+	else if (constant->mConstType == BfConstType_IntToPtr)
+	{
+		auto fromPtrToInt = (BfConstantIntToPtr*)constant;
+		auto val = GetAddr(module->mBfIRBuilder->GetConstantById(fromPtrToInt->mTarget));
+		if (!val)
+			return val;
+		return CeTypedValue(val.mAddr, fromPtrToInt->mToType);
+	}
+	else if (constant->mConstType == BfConstType_GEP32_1)
+	{
+		auto gepConst = (BfConstantGEP32_1*)constant;
+
+		auto constant = module->mBfIRBuilder->GetConstantById(gepConst->mTarget);
+		auto typedVal = GetAddr(constant);
+		if (!typedVal)
+			return CeTypedValue();
+
+		auto dbgTypeInfo = GetDbgTypeInfo(typedVal.mType);		
+		if (dbgTypeInfo == NULL)
+			return CeTypedValue();
+
+		if (!dbgTypeInfo->mType->IsPointer())
+		{
+			NOP;
+		}
+
+		auto addr = typedVal.mAddr;
+
+		if (gepConst->mIdx0 != 0)
+			addr += gepConst->mIdx0 * dbgTypeInfo->mType->GetUnderlyingType()->GetStride();		
+		
+		return CeTypedValue(addr, module->mBfIRBuilder->MapType(dbgTypeInfo->mType));
+	}
+	else if (constant->mConstType == BfConstType_GEP32_2)
+	{
+		auto gepConst = (BfConstantGEP32_2*)constant;
+
+		auto constant = module->mBfIRBuilder->GetConstantById(gepConst->mTarget);
+		auto typedVal = GetAddr(constant);
+		if (!typedVal.mAddr)
+			return CeTypedValue();
+
+		auto dbgTypeInfo = GetDbgTypeInfo(typedVal.mType);
+
+		if ((dbgTypeInfo != NULL) && (dbgTypeInfo->mType->IsPointer()))
+			dbgTypeInfo = GetDbgTypeInfo(dbgTypeInfo->mType->GetUnderlyingType()->mTypeId);
+
+		if (dbgTypeInfo == NULL)
+			return CeTypedValue();
+
+		auto addr = typedVal.mAddr;
+
+		if (gepConst->mIdx0 != 0)
+			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);
+		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();
+}
+
+CeTypedValue CeDebugger::GetAddr(const BfTypedValue typedVal)
+{
+	auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(typedVal.mValue);
+	if (constant == NULL)
+		return CeTypedValue();
+	return GetAddr(constant);
+}
+
+#define GET_FROM(ptr, T) *((T*)(ptr += sizeof(T)) - 1)
+
+String CeDebugger::ReadString(BfTypeCode charType, intptr addr, intptr maxLength, CeFormatInfo& formatInfo)
+{
+	int origMaxLength = (int)maxLength;
+	if (addr == 0)
+		return "";
+
+	BP_ZONE("WinDebugger::ReadString");
+
+	String retVal = "\"";
+	bool wasTerminated = false;
+	String valString;
+	intptr maxShowSize = 255;
+
+	if (maxLength == -1)
+		maxLength = formatInfo.mOverrideCount;
+	else if (formatInfo.mOverrideCount != -1)
+		maxLength = BF_MIN(formatInfo.mOverrideCount, maxLength);
+	if (formatInfo.mMaxCount != -1)
+		maxLength = BF_MIN(formatInfo.mMaxCount, maxLength);
+
+	if (maxLength == -1)
+		maxLength = 8 * 1024 * 1024; // Is 8MB crazy?	
+	if (!formatInfo.mRawString)
+		maxLength = BF_MIN(maxLength, maxShowSize);
+
+	//EnableMemCache();
+	bool readFailed = false;
+	intptr strPtr = addr;
+
+	int charLen = 1;
+	if (charType == BfTypeCode_Char16)
+		charLen = 2;
+	else if (charType == BfTypeCode_Char32)
+		charLen = 4;
+
+	bool isUTF8 = formatInfo.mDisplayType == DwDisplayType_Utf8;
+
+	int readSize = BF_MIN(1024, (int)maxLength * charLen);
+	uint8 buf[1024];
+	uint8* bufPtr = NULL;
+	uint8* bufEnd = NULL;
+	bool hasHighAscii = false;
+
+	int i;
+	for (i = 0; i < maxLength; i++)
+	{
+		if (bufPtr >= bufEnd)
+		{
+			while (true)
+			{
+				if (readSize < charLen)
+				{
+					readFailed = true;
+					break;
+				}
+
+				if (ReadMemory(strPtr, readSize, buf))
+					break;
+
+				readSize /= 2;
+			}
+			if (readFailed)
+				break;
+
+			bufPtr = buf;
+			bufEnd = buf + readSize;
+		}
+
+		switch (charLen)
+		{
+		case 1:
+		{
+			char c = GET_FROM(bufPtr, char);
+			if ((c != 0) || (formatInfo.mOverrideCount != -1))
+			{
+				if ((uint8)c >= 0x80)
+					hasHighAscii = true;
+				valString.Append(c);
+			}
+			else
+				wasTerminated = true;
+		}
+		break;
+		case 2:
+		{
+			uint16 c16 = GET_FROM(bufPtr, uint16);
+			if ((c16 != 0) || (formatInfo.mOverrideCount != -1))
+			{
+				char str[8];
+				u8_toutf8(str, 8, c16);
+				valString += str;
+			}
+			else
+				wasTerminated = true;
+		}
+		break;
+		case 4:
+		{
+			uint32 c32 = GET_FROM(bufPtr, uint32);
+			if ((c32 != 0) || (formatInfo.mOverrideCount != -1))
+			{
+				char str[8];
+				u8_toutf8(str, 8, c32);
+				valString += str;
+			}
+			else
+				wasTerminated = true;
+		}
+		break;
+		}
+
+		if ((wasTerminated) && (formatInfo.mOverrideCount != -1))
+		{
+			valString += '\x00';
+			wasTerminated = false;
+		}
+
+		if ((wasTerminated) || (readFailed))
+		{
+			break;
+		}
+		strPtr += charLen;
+	}
+	//DisableMemCache();
+
+	if (formatInfo.mOverrideCount != -1)
+	{
+		if (i == formatInfo.mOverrideCount)
+			wasTerminated = true;
+	}
+
+	if (strPtr == addr + origMaxLength)
+		wasTerminated = true;
+
+	if (valString.length() == formatInfo.mOverrideCount)
+		wasTerminated = true;
+
+	// 	if (formatInfo.mDisplayType == DwDisplayType_Ascii)
+	// 	{
+	// 		// Our encoding for retVal is already assumed to be UTF8, so the special case here actually Ascii
+	// 		valString = UTF8Encode(ToWString(valString));
+	// 	}
+
+	if (formatInfo.mRawString)
+	{
+		if ((formatInfo.mDisplayType == DwDisplayType_Utf8) || (!hasHighAscii))
+			return valString;
+
+		String utf8Str;
+		for (int i = 0; i < (int)valString.length(); i++)
+		{
+			char c = valString[i];
+			if ((uint8)c >= 0x80)
+			{
+				utf8Str += (char)(0xC0 | (((uint8)c & 0xFF) >> 6));
+				utf8Str += (char)(0x80 | ((uint8)c & 0x3F));
+			}
+			else
+				utf8Str += c;
+		}
+		return utf8Str;
+	}
+
+	if ((readFailed) && (valString.IsEmpty()))
+		return "< Failed to read string >";
+
+	retVal += SlashString(valString, true, true, true);
+
+	// We could go over 'maxShowSize' if we have a lot of slashed chars. An uninitialized string can be filled with '\xcc' chars
+	if ((!formatInfo.mRawString) && ((int)retVal.length() > maxShowSize))
+	{
+		retVal = retVal.Substring(0, maxShowSize);
+		wasTerminated = false;
+	}
+
+	if (wasTerminated)
+		retVal += "\"";
+	else
+		retVal += "...";
+
+	return retVal;
+}
+
+void CeDebugger::ProcessEvalString(BfTypedValue useTypedValue, String& evalStr, String& displayString, CeFormatInfo& formatInfo, DebugVisualizerEntry* debugVis, bool limitLength)
+{
+	for (int i = 0; i < (int)evalStr.length(); i++)
+	{
+		char c = evalStr[i];
+		char nextC = 0;
+		if (i < (int)evalStr.length() - 1)
+			nextC = evalStr[i + 1];
+		if ((c == '{') && (nextC != '{'))
+		{
+			// Evaluate
+
+			int endIdx = i;
+			for (; endIdx < (int)evalStr.length(); endIdx++)
+			{
+				//TODO: Do better parsing - this paren could be inside a string, for example
+				if (evalStr[endIdx] == '}')
+					break;
+			}
+
+			CeFormatInfo displayStrFormatInfo = formatInfo;
+			displayStrFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + (int)displayString.length();
+			displayStrFormatInfo.mHidePointers = false;
+
+			if ((limitLength) && (displayStrFormatInfo.mTotalSummaryLength > 255))
+			{
+				displayString += "...";
+			}
+			else
+			{
+				String evalString = evalStr.Substring(i + 1, endIdx - i - 1);
+				String errors;
+				BfTypedValue evalResult = EvaluateInContext(useTypedValue, evalString, &displayStrFormatInfo, NULL, &errors);
+				if (evalResult)
+				{
+					if (displayStrFormatInfo.mNoEdit)
+						formatInfo.mNoEdit = true;
+
+					String result = TypedValueToString(evalResult, evalString, displayStrFormatInfo, NULL);
+
+					if ((formatInfo.mRawString) && (limitLength))
+					{
+						displayString = result;
+						return;
+					}
+
+					int crPos = (int)result.IndexOf('\n');
+					if (crPos != -1)
+						displayString += result.Substring(0, crPos);
+					else
+						displayString += result;
+				}
+				else if (debugVis != NULL)
+				{
+					displayString += "<DbgVis Failed>";
+					DbgVisFailed(debugVis, evalString, errors);
+				}
+				else
+				{
+					displayString += "<Eval Failed>";
+				}
+			}
+
+			i = endIdx;
+			continue;
+		}
+		else if ((c == '{') && (nextC == '{'))
+		{
+			// Skip next paren
+			i++;
+		}
+		else if ((c == '}') && (nextC == '}'))
+		{
+			// Skip next paren
+			i++;
+		}
+
+		displayString += c;
+	}
+}
+
+String CeDebugger::TypedValueToString(const BfTypedValue& typedValue, const StringImpl& expr, CeFormatInfo& formatInfo, bool fullPrecision)
+{
+	auto module = mCeMachine->mCeModule;
+
+	String retVal;
+	if (typedValue.IsNoValueType())
+	{
+		retVal += "\n";
+		retVal += module->TypeToString(typedValue.mType);
+		retVal += "\n";
+		retVal += GetMemberList(typedValue.mType, 0, 0, true);
+		return retVal;
+	}
+
+	auto constant = module->mBfIRBuilder->GetConstant(typedValue.mValue);
+	auto ceContext = mCeMachine->mCurContext;
+	if (constant == NULL)
+	{
+		return "!Invalid expression";
+	}
+	
+	bool didAlloc = false;
+	addr_ce addr = 0;	
+
+	defer(
+		{
+			if (didAlloc)
+				mCurDbgState->mCeContext->CeFree(addr);
+		}		
+		);
+
+	if (constant->mConstType == BfConstType_AggCE)
+	{
+		auto aggCE = (BfConstantAggCE*)constant;
+		addr = aggCE->mCEAddr;
+	}
+	else if ((typedValue.IsAddr()) || (typedValue.mType->IsObjectOrInterface()) || (typedValue.mType->IsPointer()))
+	{
+		CeTypedValue typedVal = GetAddr(constant);
+		addr = typedVal.mAddr;
+		if (!typedVal)
+		{
+			return "!Invalid addr type";
+		}
+	}
+	else
+	{
+		int allocSize = typedValue.mType->mSize;
+		auto typeInst = typedValue.mType->ToTypeInstance();
+		if (typeInst != NULL)
+			allocSize = typeInst->mInstSize;
+		if (allocSize < 0)
+			return "!Invalid size";
+
+		addr = (addr_ce)(mCurDbgState->mCeContext->CeMalloc(allocSize) - mCurDbgState->mCeContext->mMemory.mVals);
+		didAlloc = true;
+
+		if (!mCurDbgState->mCeContext->WriteConstant(mCeMachine->mCeModule, addr, constant, typedValue.mType))
+		{
+			return StrFormat("!Failed to encode value");
+		}		
+	}
+
+	DwDisplayInfo* displayInfo = GetDisplayInfo(formatInfo.mReferenceId);
+
+	char str[32];
+	String result;	
+	auto memStart = mCurDbgState->mCeContext->mMemory.mVals;
+
+	int checkMemSize = typedValue.mType->mSize;
+	if (typedValue.mType->IsPointer())
+		checkMemSize = typedValue.mType->GetUnderlyingType()->mSize;
+	
+	uint8* data = ceContext->GetMemoryPtr(addr, checkMemSize);
+	if ((addr != 0) && (data == NULL))
+		return "!Invalid address";
+
+	addr_ce dataAddr = addr;	
+	if ((typedValue.IsAddr()) && (typedValue.mType->IsObjectOrInterface()))
+		dataAddr = *(addr_ce*)data;	
+
+	if (formatInfo.mRawString)
+	{
+		//if ((dwValueType->mTypeCode != DbgType_Struct) && (dwValueType->mTypeCode != DbgType_Class) && (dwValueType->mTypeCode != DbgType_Ptr) && (dwValueType->mTypeCode != DbgType_SizedArray))
+		if ((!typedValue.mType->IsPointer()) && (!typedValue.mType->IsObjectOrStruct()) && (!typedValue.mType->IsStruct()) && (!typedValue.mType->IsSizedArray()))
+			return "";
+	}
+
+	auto _ShowArraySummary = [&](String& retVal, addr_ce ptrVal, int64 arraySize, BfType* innerType)
+	{
+		auto ptrType = module->CreatePointerType(innerType);
+
+		String displayString;
+		displayString += "{";
+		for (int idx = 0; idx < arraySize; idx++)
+		{
+			if (formatInfo.mTotalSummaryLength + retVal.length() + displayString.length() > 255)
+			{
+				displayString += "...";
+				break;
+			}
+
+			if ((idx != 0) && (!displayString.EndsWith('{')))
+				displayString += ", ";
+
+			CeFormatInfo displayStrFormatInfo = formatInfo;
+			displayStrFormatInfo.mExpandItemDepth = 1;
+			displayStrFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + (int)retVal.length() + (int)displayString.length();
+			displayStrFormatInfo.mHidePointers = false;
+			displayStrFormatInfo.mArrayLength = -1;
+
+			// Why did we have this "na" on here? It made "void*[3]" type things show up as "{,,}"
+			//String evalStr = "((" + innerType->ToStringRaw(language) + "*)" + EncodeDataPtr(ptrVal, true) + StrFormat(")[%d], na", idx);			
+
+			String evalStr = StrFormat("((comptype(%d))(void*)", ptrType->mTypeId) + EncodeDataPtr(ptrVal, true) + StrFormat(")[%lld]", idx);
+			BfTypedValue evalResult = EvaluateInContext(typedValue, evalStr, &displayStrFormatInfo);
+			String result;
+			if (evalResult)
+			{
+				result = TypedValueToString(evalResult, evalStr, displayStrFormatInfo, NULL);
+				int crPos = (int)result.IndexOf('\n');
+				if (crPos != -1)
+					result.RemoveToEnd(crPos);
+			}
+			else
+				result = "???";
+
+			displayString += result;
+		}
+		displayString += "}";
+		retVal += displayString;
+	};
+
+	if (formatInfo.mArrayLength != -1)
+	{
+		if (formatInfo.mRawString)
+			return "";
+
+		if (typedValue.mType->IsPointer())
+		{
+			auto elementType = typedValue.mType->GetUnderlyingType();
+
+			String retVal;
+			addr_ce ptrVal = addr;
+			if (!formatInfo.mHidePointers)
+			{
+				retVal = EncodeDataPtr(ptrVal, true) + " ";
+				retVal += module->TypeToString(elementType);
+				retVal += StrFormat("[%lld] ", (int64)formatInfo.mArrayLength);
+			}
+
+			_ShowArraySummary(retVal, ptrVal, formatInfo.mArrayLength, elementType);
+
+			String idxStr = "[{0}]";			
+
+			retVal += "\n" + module->TypeToString(typedValue.mType);
+
+			String evalStr = StrFormat("((comptype(%d))(void*)", typedValue.mType->mTypeId) + EncodeDataPtr(ptrVal, true) + ")[{0}]";
+
+			retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, (int)BF_MAX(formatInfo.mArrayLength, 0), 10000) +
+				"\t" + idxStr + "\t" + evalStr;
+			return retVal;
+		}
+		else
+		{
+			CeFormatInfo newFormatInfo = formatInfo;
+			newFormatInfo.mArrayLength = -1;
+
+			String retVal = TypedValueToString(typedValue, expr, newFormatInfo);
+
+			int crPos = (int)retVal.IndexOf('\n');
+			if (crPos != -1)
+				retVal = "!Array length flag not valid with this type" + retVal.Substring(crPos);
+			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_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);
+
+					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>(*(int8*)(data), "int8", displayInfo, formatInfo);
+		case BfTypeCode_UInt8:
+			return IntTypeToString<uint8>(*(uint8*)(data), "uint8", displayInfo, formatInfo);
+		case BfTypeCode_Int16:
+			return IntTypeToString<int16>(*(int16*)(data), "int16", displayInfo, formatInfo);
+		case BfTypeCode_UInt16:
+			return IntTypeToString<uint16>(*(uint16*)(data), "uint16", displayInfo, formatInfo);
+		case BfTypeCode_Int32:
+			return IntTypeToString<int32>(*(int32*)(data), "int32", displayInfo, formatInfo);
+		case BfTypeCode_UInt32:
+			return IntTypeToString<uint32>(*(uint32*)(data), "uint32", displayInfo, formatInfo);
+		case BfTypeCode_Int64:
+			return IntTypeToString<int64>(*(int64*)(data), "int64", displayInfo, formatInfo);
+		case BfTypeCode_UInt64:
+			return IntTypeToString<uint64>(*(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");
+			}
+		}
+	}
+	
+	if (typedValue.mType->IsPointer())
+	{
+		//ceContext->
+
+		addr_ce ptrVal = addr;
+
+		String retVal;
+		BfType* innerType = typedValue.mType->GetUnderlyingType();
+		if (innerType == NULL)
+			return EncodeDataPtr((uint32)ptrVal, true) + "\nvoid*";
+
+		bool isChar = false;
+
+		if (innerType->IsChar())
+			isChar = true;
+
+		if ((isChar) && (formatInfo.mArrayLength == -1))
+		{
+			auto primType = (BfPrimitiveType*)innerType;
+
+			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));
+// 			}
+
+			SetAndRestoreValue<intptr> prevOverrideLen(formatInfo.mOverrideCount, strLen);
+			String strResult = ReadString(primType->mTypeDef->mTypeCode, ptrVal, strLen, formatInfo);
+			if (formatInfo.mRawString)
+				return strResult;
+			if (!strResult.IsEmpty())
+			{
+				if (!retVal.IsEmpty())
+					retVal += " ";
+				retVal += strResult;
+			}
+			retVal += "\n" + module->TypeToString(typedValue.mType);
+			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);
+// 
+// 			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
+ 		{
+			if (formatInfo.mRawString)
+				return "";			
+			
+			String retVal;
+			if (!formatInfo.mHidePointers)
+				retVal = EncodeDataPtr((uint32)ptrVal, true);
+
+			if (ptrVal != 0)
+			{
+				BfTypedValue innerTypedVal = BfTypedValue(module->mBfIRBuilder->CreateConstAggCE(module->mBfIRBuilder->MapType(innerType), (addr_ce)ptrVal), innerType, true);
+
+				innerTypedVal.mType = innerType;
+
+				if (innerTypedVal)
+				{
+					CeFormatInfo defaultFormatInfo;					
+					defaultFormatInfo.mTotalSummaryLength = formatInfo.mTotalSummaryLength + 2; // Take into accout the necessary {}'s
+					defaultFormatInfo.mExpandItemDepth++;
+					defaultFormatInfo.mCallStackIdx = formatInfo.mCallStackIdx;
+					String innerStr = TypedValueToString(innerTypedVal, "", defaultFormatInfo);
+					int crIdx = (int)innerStr.IndexOf('\n');
+					if (crIdx != -1)
+					{
+						String innerDataStr = innerStr.Substring(0, crIdx);
+						if (!innerDataStr.empty())
+						{
+							if (!retVal.empty())
+								retVal += " ";
+							retVal += "{" + innerDataStr + "}";
+						}
+					}
+					else
+					{
+						retVal += " { ??? }";
+					}
+				}
+			}
+
+			retVal += "\n" + module->TypeToString(typedValue.mType);
+			module->PopulateType(innerType);
+
+			if (ptrVal != 0)				
+			{
+				//String ptrDataStr = StrFormat("(%s)", dwValueType->ToStringRaw(language).c_str()) + EncodeDataPtr(typedValue.mPtr, true);
+				retVal += "\n*\t";
+				// Why did we have this?  It messed up a pointer to sized array
+				/*if (language == DbgLanguage_Beef)
+					retVal += "this";
+				else*/
+				retVal += "this";
+
+				if (!formatInfo.mReferenceId.empty())
+					retVal += ", refid=" + MaybeQuoteFormatInfoParam(formatInfo.mReferenceId);
+
+				retVal += StrFormat(", this=%d@0x%X", innerType->mTypeId, ptrVal);
+			}
+			
+			retVal += "\n:editVal\t" + EncodeDataPtr((uint32)addr, true);			
+
+			return retVal;
+		}
+	}
+
+	if (typedValue.mType->IsSizedArray())
+	{
+		auto arrayType = (BfSizedArrayType*)typedValue.mType;
+		auto innerType = arrayType->mElementType;
+
+		String retVal;
+		addr_ce ptrVal = addr;
+		
+		intptr arraySize = arrayType->mElementCount;
+		intptr innerSize = innerType->GetStride();
+		
+		String idxStr = "[{0}]";
+
+		if (innerType->IsChar())
+		{
+			auto primType = (BfPrimitiveType*)innerType;
+			String strVal = ReadString(primType->mTypeDef->mTypeCode, ptrVal, arraySize, formatInfo);
+			if (formatInfo.mRawString)
+				return strVal;
+			retVal += strVal;
+		}
+		else
+		{
+			if (formatInfo.mRawString)
+				return "";
+
+			_ShowArraySummary(retVal, ptrVal, arraySize, innerType);
+		}
+
+		retVal += "\n" + module->TypeToString(typedValue.mType);
+
+		String referenceId = module->TypeToString(typedValue.mType);
+		String evalStr;
+
+		// Why did we have the "na"? Do we not want to show addresses for all members?		
+
+		auto ptrType = module->CreatePointerType(innerType);
+
+		evalStr = StrFormat("((comptype(%d))(void*)", ptrType->mTypeId) + EncodeDataPtr(ptrVal, true) + ")[{0}], refid=" + MaybeQuoteFormatInfoParam(referenceId + ".[]");
+		if (typedValue.IsReadOnly())
+			evalStr += ", ne";
+		retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, (int)BF_MAX(arraySize, 0), 10000) +
+			"\t" + idxStr + "\t" + evalStr;
+		return retVal;
+	}
+	
+	if (typedValue.mType->IsEnum())
+	{
+		String retVal;
+		int64 bitsLeft = ValueToInt(typedValue);
+		int valueCount = 0;
+
+		String editVal;
+		
+		auto typeInst = typedValue.mType->ToTypeInstance();
+		auto dbgTypeInfo = GetDbgTypeInfo(typedValue.mType->mTypeId);
+
+		while ((dbgTypeInfo != NULL) && ((bitsLeft != 0) || (valueCount == 0)))
+		{			
+			CeDbgTypeInfo::ConstIntEntry* bestMatch = NULL;
+
+			for (auto& constIntEntry : dbgTypeInfo->mConstIntEntries)
+			{
+				if (constIntEntry.mVal == bitsLeft)
+				{
+					bestMatch = &constIntEntry;
+					break;
+				}
+			}
+
+			if (bestMatch == NULL)
+			{
+				for (auto& constIntEntry : dbgTypeInfo->mConstIntEntries)
+				{
+					if ((constIntEntry.mVal != 0) &&
+						((constIntEntry.mVal & bitsLeft) == constIntEntry.mVal))
+					{
+						bestMatch = &constIntEntry;
+						break;
+					}
+				}
+			}
+
+			if (bestMatch == NULL)
+				break;
+
+			if (valueCount > 0)
+			{
+				retVal += " | ";				
+			}
+			
+			auto bestFieldInstance = &typeInst->mFieldInstances[bestMatch->mFieldIdx];
+
+			retVal += ".";
+			retVal += bestFieldInstance->GetFieldDef()->mName;
+
+			valueCount++;
+			bitsLeft &= ~bestMatch->mVal;
+		}
+
+		if ((valueCount == 0) || (bitsLeft != 0))
+		{
+			if (valueCount > 0)
+				retVal += " | ";
+			retVal += StrFormat("%lld", bitsLeft);			
+		}
+
+		retVal += "\n" + module->TypeToString(typedValue.mType);
+		retVal += "\n:canEdit";
+
+		return retVal;
+	}
+
+	if (typedValue.mType->IsTypedPrimitive())
+	{
+		auto innerType = typedValue.mType->GetUnderlyingType();
+
+		BfTypedValue innerTypedVal = typedValue;
+		innerTypedVal.mType = innerType;
+
+		auto innerReturn = TypedValueToString(innerTypedVal, expr, formatInfo, fullPrecision);
+		if (innerReturn.StartsWith("!"))
+			return innerReturn;
+
+		int crPos = (int)innerReturn.IndexOf('\n');
+		if (crPos == -1)
+			return innerReturn;
+
+		retVal += "{ ";
+		retVal += innerReturn.Substring(0, crPos);
+		retVal += " }";
+		retVal += "\n" + module->TypeToString(typedValue.mType);
+		return retVal;
+	}
+
+	bool isCompositeType = typedValue.mType->IsStruct() || typedValue.mType->IsObject();
+
+	if (isCompositeType)
+	{
+		BfTypeInstance* displayType = typedValue.mType->ToTypeInstance();
+
+		bool isMemoryValid = true;
+
+		if ((dataAddr == 0) && (addr != 0))
+			dataAddr = *(addr_ce*)data;
+
+		if (((typedValue.mType->IsObjectOrInterface()) &&
+			(!formatInfo.mHidePointers) || (dataAddr == 0)))
+		{				
+			retVal = EncodeDataPtr((uint32)dataAddr, true);
+			retVal += " ";
+
+			if (!ceContext->CheckMemory(dataAddr, displayType->mInstSize))
+				isMemoryValid = false;
+		}
+		
+		bool isBadSrc = false;
+		bool isNull = dataAddr == 0;
+		bool hadCustomDisplayString = false;
+
+		BfTypeInstance* actualType = displayType;
+		bool useActualRawType = false;
+
+		bool isTuple = typedValue.mType->IsTuple();
+		
+		String ptrDataStr;
+
+		if (!formatInfo.mIgnoreDerivedClassInfo)
+		{
+			if (actualType->IsObject())
+			{
+				if (dataAddr != 0)
+				{
+					uint8* dataPtr = ceContext->GetMemoryPtr(dataAddr, 4);
+					if (dataPtr == 0)
+						return "!Invalid object address";
+					int actualTypeid = *(int32*)dataPtr;
+					auto checkType = mCompiler->mContext->FindTypeById(actualTypeid);
+					if (checkType != NULL)
+						actualType = checkType->ToTypeInstance();
+				}
+			}
+		}
+
+		DebugVisualizerEntry* debugVis = NULL;
+		Array<String> dbgVisWildcardCaptures;
+
+		if ((!formatInfo.mNoVisualizers) && (!isNull) && (!isBadSrc))
+		{			
+			debugVis = FindVisualizerForType(displayType, &dbgVisWildcardCaptures);
+		}
+
+		bool wantsCustomExpandedItems = false;
+		String displayString;
+		if (debugVis != NULL)
+		{
+			auto& displayStringList = formatInfo.mRawString ? debugVis->mStringViews : debugVis->mDisplayStrings;
+
+			for (auto displayEntry : displayStringList)
+			{
+				if (!displayEntry->mCondition.empty())
+				{
+					if (!EvalCondition(debugVis, typedValue, formatInfo, displayEntry->mCondition, dbgVisWildcardCaptures, displayString))
+						continue;
+				}
+
+				hadCustomDisplayString = true;
+				String displayStr = mDebugManager->mDebugVisualizers->DoStringReplace(displayEntry->mString, dbgVisWildcardCaptures);
+				if (displayString.length() > 0)
+					displayString += " ";
+				ProcessEvalString(typedValue, displayStr, displayString, formatInfo, debugVis, true);
+				if (formatInfo.mRawString)
+					return displayString;
+
+				break;
+			}
+
+			if ((!debugVis->mExpandItems.empty()) || (debugVis->mCollectionType != DebugVisualizerEntry::CollectionType_None))
+			{
+				wantsCustomExpandedItems = true;
+			}
+		}
+
+		if (formatInfo.mRawString)
+			return "";
+
+		if ((!isNull) && (!formatInfo.mNoVisualizers) && (!hadCustomDisplayString))
+		{
+			// Create our own custom display			
+			
+			String firstRet;
+			String bigRet = isTuple ? "(" : "{ ";
+
+			int memberIdx = 0;
+			BfType* summaryType = typedValue.mType;
+			bool summaryDone = false;
+			bool truncatedMemberList = false;
+
+			BfTypedValue summaryTypedValue = typedValue;
+			String summaryDataStr = ptrDataStr;
+			String splatStr;
+			if (dataAddr == -1)
+				splatStr = expr;
+
+			while ((summaryType != NULL) && (isMemoryValid))
+			{	
+				if ((summaryType->IsTypedPrimitive()) 
+					//&& ((summaryType->mBaseTypes.IsEmpty()) || (!summaryType->mBaseTypes.front()->mBaseType->IsTypedPrimitive())))
+					)
+				{
+					if (formatInfo.mTotalSummaryLength + (int)displayString.length() > 255)
+					{
+						truncatedMemberList = true;
+						summaryDone = true;
+						bigRet += "...";
+					}
+					else
+					{
+						CeFormatInfo displayStrFormatInfo = formatInfo;
+						displayStrFormatInfo.mExpandItemDepth = 1;
+						displayStrFormatInfo.mTotalSummaryLength += (int)displayString.length();
+						displayStrFormatInfo.mHidePointers = false;
+
+						BfType* primType = summaryType->GetUnderlyingType();
+						String result;
+
+						if (primType->IsInteger())
+							formatInfo.mTypeKindFlags = (DbgTypeKindFlags)(formatInfo.mTypeKindFlags | DbgTypeKindFlag_Int);
+
+						if ((dataAddr != 0) && (dataAddr != -1))
+						{
+							//String evalString = "(" + primType->ToString() + ")" + ptrDataStr;
+// 							BfTypedValue evalResult = EvaluateInContext(dbgCompileUnit, origTypedValue, evalString, &displayStrFormatInfo);
+// 							if (evalResult)
+// 								result = TypedValueToString(evalResult, evalString, displayStrFormatInfo, NULL);
+						}
+						else
+						{
+// 							BfTypedValue evalResult = origTypedValue;
+// 							evalResult.mType = primType;
+// 							String evalString = "(" + primType->ToString() + ")" + expr;
+// 							result = TypedValueToString(evalResult, evalString, displayStrFormatInfo, NULL);
+						}
+
+						if (formatInfo.mRawString)
+							return result;
+
+						int crPos = (int)result.IndexOf('\n');
+						if (crPos != -1)
+							result.RemoveToEnd(crPos);
+
+						if (memberIdx == 0)
+							firstRet = result;
+
+						bigRet += result;
+						memberIdx++;
+					}
+				}
+
+				auto summaryTypeInst = summaryType->ToTypeInstance();
+				if (summaryTypeInst == NULL)
+					break;
+
+				module->PopulateType(summaryTypeInst);
+				for (auto& fieldInst : summaryTypeInst->mFieldInstances)
+				{
+					auto fieldDef = fieldInst.GetFieldDef();
+					if (!fieldDef->mIsStatic)
+					{
+						if (formatInfo.mTotalSummaryLength + retVal.length() + bigRet.length() > 255)
+						{
+							truncatedMemberList = true;
+							summaryDone = true;
+							bigRet += "...";
+							break;
+						}
+
+						//if (fieldDef->mName != NULL)
+						{
+// 							if (member->mName[0] == '$')
+// 								continue;
+
+							if (!isdigit(fieldDef->mName[0]))
+							{
+								if (memberIdx != 0)
+									bigRet += isTuple ? ", " : " ";
+
+								if ((!isTuple) || (fieldDef->mName[0] != '_'))
+								{
+									bigRet += String(fieldDef->mName);
+									bigRet += isTuple ? ":" : "=";
+								}
+							}
+							else
+							{
+								if (memberIdx != 0)
+									bigRet += ", ";
+							}
+
+							CeFormatInfo displayStrFormatInfo = formatInfo;
+							displayStrFormatInfo.mExpandItemDepth = 1;
+							displayStrFormatInfo.mHidePointers = false;
+							displayStrFormatInfo.mTotalSummaryLength = (int)(formatInfo.mTotalSummaryLength + retVal.length() + bigRet.length());
+
+// 							String evalString;
+// 							if (dataPtr != -1)
+// 							{
+// 								if ((fieldDef->mName[0] >= '0') && (fieldDef->mName[0] <= '9'))
+// 									evalString += "this.";
+// 								evalString += String(member->mName); // +", this=" + summaryDataStr;
+// 							}
+// 							else
+// 							{
+// 								evalString = "(";
+// 								evalString += splatStr;
+// 								evalString += ").";
+// 								evalString += fieldDef->mName;
+// 							}
+							String referenceId;
+							String result;
+							if (!fieldInst.mResolvedType->IsValuelessType())
+							{
+								auto addrVal = dataAddr + fieldInst.mDataOffset;
+
+								BfTypedValue evalResult;
+								if (fieldInst.mResolvedType->IsObjectOrInterface())
+								{
+									auto typeInst = fieldInst.mResolvedType->ToTypeInstance();
+									evalResult = BfTypedValue(module->mBfIRBuilder->CreateConstAggCE(module->mBfIRBuilder->MapTypeInst(typeInst), (addr_ce)addrVal), typeInst, true);
+								}
+								else
+								{
+									evalResult = BfTypedValue(module->mBfIRBuilder->CreateConstAggCE(module->mBfIRBuilder->MapType(fieldInst.mResolvedType), (addr_ce)addrVal), fieldInst.mResolvedType, true);
+								}
+
+								//BfTypedValue evalResult = EvaluateInContext(dbgCompileUnit, summaryTypedValue, evalString, &displayStrFormatInfo, &referenceId);
+								if (evalResult)
+								{
+									displayStrFormatInfo.mReferenceId = referenceId;
+									result = TypedValueToString(evalResult, "", displayStrFormatInfo, NULL);
+									int crPos = (int)result.IndexOf('\n');
+									if (crPos != -1)
+										result.RemoveToEnd(crPos);
+								}
+								else
+									result = "???";
+							}
+
+							if (fieldInst.mResolvedType->IsInteger())
+								formatInfo.mTypeKindFlags = (DbgTypeKindFlags)(formatInfo.mTypeKindFlags | DbgTypeKindFlag_Int);
+
+							if (formatInfo.mRawString)
+								return result;
+
+							if (memberIdx == 0)
+								firstRet = result;
+
+							bigRet += result;
+							//formatInfo.mEmbeddedDisplayCount = displayStrFormatInfo.mEmbeddedDisplayCount;
+							memberIdx++;
+						}						
+					}
+				}
+
+				if (truncatedMemberList)
+					break;
+
+				// Find first base class with members
+				BfType* nextSummaryType = summaryTypeInst->mBaseType;				
+				summaryType = nextSummaryType;
+
+				if ((summaryType == NULL) || (summaryType == module->mContext->mBfObjectType))
+					break;
+				
+				// If we don't have many members then find a base class with some members to show
+				if ((memberIdx != 0) && (displayString.length() >= 255))
+				{
+					truncatedMemberList = true;
+					bigRet += "...";
+					break;
+				}
+			}
+
+			bigRet += isTuple ? ")" : " }";
+
+			if (displayString.length() > 0)
+				displayString += " ";
+			if ((memberIdx == 1) && (!truncatedMemberList) && (firstRet.IndexOf('{') == -1) && (!isTuple))
+				displayString += "{ " + firstRet + " }";
+			else
+				displayString += bigRet;						
+		}
+
+		retVal += displayString;
+		retVal += "\n" + module->TypeToString(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 (formatInfo.mNoMembers)
+		{
+			//
+		}
+		else if (wantsCustomExpandedItems)
+		{
+			HandleCustomExpandedItems(retVal, debugVis, typedValue, addr, dataAddr, dbgVisWildcardCaptures, formatInfo);
+		}
+		else if ((!isNull) && (!isBadSrc))
+		{
+			retVal += "\n" + GetMemberList(displayType, addr, dataAddr, false);
+		}
+
+		if (typedValue.mType->IsObjectOrInterface())
+		{
+			retVal += "\n:editVal\t" + EncodeDataPtr((uint32)dataAddr, true);
+		}
+		return retVal;
+	}
+
+	return "!unknown type";
+}
+
+void CeDebugger::HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* debugVis, BfTypedValue typedValue, addr_ce addr, addr_ce addrInst, Array<String>& dbgVisWildcardCaptures, CeFormatInfo& formatInfo)
+{
+	auto debugVisualizers = mDebugManager->mDebugVisualizers;
+	auto ceModule = mCeMachine->mCeModule;
+	
+	if (formatInfo.mExpandItemDepth > 10) // Avoid crashing on circular ExpandItems
+		return;
+	
+	bool isReadOnly = false;
+// 	if (useTypedValue.mIsReadOnly)
+// 		isReadOnly = true;
+
+	String ptrUseDataStr = StrFormat("%d@0x%X", typedValue.mType->mTypeId, addrInst);
+
+	for (auto entry : debugVis->mExpandItems)
+	{
+		if (!entry->mCondition.empty())
+		{
+			String error;
+			if (!EvalCondition(debugVis, typedValue, formatInfo, entry->mCondition, dbgVisWildcardCaptures, error))
+			{
+				if (!error.empty())
+					retVal += "\n" + entry->mName + "\t@!<DbgVis Failed>@!";
+				continue;
+			}
+		}
+		String replacedStr = debugVisualizers->DoStringReplace(entry->mValue, dbgVisWildcardCaptures);
+		retVal += "\n" + entry->mName + "\t" + replacedStr + ", this=" + ptrUseDataStr;
+	}
+
+	String referenceId = ceModule->TypeToString(typedValue.mType);
+
+	if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_ExpandedItem)
+	{
+		BfTypedValue itemValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
+		if (itemValue)
+		{
+			CeFormatInfo itemFormatInfo = formatInfo;
+			itemFormatInfo.mExpandItemDepth++;
+			String itemRetVal = TypedValueToString(itemValue, "", itemFormatInfo, NULL);
+
+			int crIdx = (int)itemRetVal.IndexOf('\n');
+			if (crIdx != -1)
+			{
+				crIdx = (int)itemRetVal.IndexOf('\n', crIdx + 1);
+				if (crIdx != -1)
+					retVal += itemRetVal.Substring(crIdx);
+			}
+		}
+	}
+	else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Array)
+	{
+		BfTypedValue sizeValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
+		Array<int> lowerDimSizes;
+		for (auto lowerDim : debugVis->mLowerDimSizes)
+		{
+			BfTypedValue lowerDimValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(lowerDim, dbgVisWildcardCaptures), &formatInfo);
+			int dimSize = 0;
+			if ((lowerDimValue) && (lowerDimValue.mType->IsInteger()))
+				dimSize = (int)ValueToInt(lowerDimValue);
+			dimSize = BF_MAX(dimSize, 1);
+			lowerDimSizes.push_back(dimSize);
+		}
+
+		if ((sizeValue) && (sizeValue.mType->IsInteger()) && (ValueToInt(sizeValue) > 0))
+		{
+			if (!debugVis->mCondition.IsEmpty())
+			{
+				int size = (int)ValueToInt(sizeValue);
+				BfTypedValue headPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
+
+				BfTypedValue curNode = headPointer;
+				Array<addr_ce> parentList;
+				String continuationData;
+
+				int totalSize = 2;
+				auto valueType = headPointer.mType;
+				String addrs = GetArrayItems(debugVis, valueType, headPointer, totalSize, &continuationData);
+				String firstAddr;
+				String secondAddr;
+				bool hasSecondAddr = valueType == NULL;
+				if (addrs.length() > 0)
+				{
+					const char* addrsPtr = addrs.c_str();
+					firstAddr = addrs.Substring(0, sizeof(addr_ce) * 2);
+					if (hasSecondAddr)
+						secondAddr = addrs.Substring(sizeof(addr_ce) * 2, sizeof(addr_ce) * 2);
+				}
+
+				String evalStr;
+				if (valueType != NULL)
+				{
+					auto ptrType = valueType;
+					if (!valueType->IsPointer())
+						ptrType = ceModule->CreatePointerType(valueType);
+					evalStr = StrFormat("(comptype(%d)", ptrType->mTypeId);
+					evalStr += ")(void*)0x{1}";
+				}
+				else
+				{
+					evalStr += "({1})(void*)0x{2}";
+				}
+				if (!debugVis->mShowElementAddrs)
+					evalStr.Insert(0, "*");
+
+				if (addrs.length() > 0)
+				{
+					evalStr += ", refid=\"" + referenceId + ".[]\"";
+					if (isReadOnly)
+						evalStr += ", ne";
+					retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, BF_MAX(size, 0), 10000) +
+						"\t[{0}]\t" + evalStr + "\t" + firstAddr;
+
+					if (hasSecondAddr)
+						retVal += "\t" + secondAddr;
+
+					if (size != 0)
+					{
+						retVal += "\n:addrs\t" + addrs;
+						if (valueType == NULL)
+							retVal += "\n:addrsEntrySize\t2";
+						if (continuationData.length() > 0)
+							retVal += "\n:continuation\t" + continuationData;
+					}
+				}
+			}
+			else if (lowerDimSizes.size() == 1)
+			{
+				int dimSize1 = lowerDimSizes[0];
+
+				String evalStr = "(" + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) +
+					StrFormat(" + {0} * %d), arraysize=%d, na, this=", dimSize1, dimSize1) + ptrUseDataStr;
+				evalStr += ", refid=\"" + referenceId + ".[]\"";
+				if (isReadOnly)
+					evalStr += ", ne";
+				retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, ValueToInt(sizeValue) / dimSize1, 50000) +
+					"\t[{0}]\t" + evalStr;
+			}
+			else if (lowerDimSizes.size() == 2)
+			{
+				int dimSize1 = lowerDimSizes[0];
+				int dimSize2 = lowerDimSizes[1];
+
+				BfTypedValue headPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
+				if ((headPointer.mType != NULL) && (headPointer.mType->IsPointer()))
+				{
+					String evalStr = StrFormat("((%s[%d]*)", ceModule->TypeToString(headPointer.mType->GetUnderlyingType()).c_str(), dimSize2) + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) +
+						StrFormat(" + {0} * %d), arraysize=%d, na, this=", dimSize1, dimSize1) + ptrUseDataStr;
+					evalStr += ", refid=\"" + referenceId + ".[]\"";
+					if (isReadOnly)
+						evalStr += ", ne";
+					retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, ValueToInt(sizeValue) / dimSize1 / dimSize2, 50000) +
+						"\t[{0}]\t" + evalStr;
+				}
+			}
+			else if (lowerDimSizes.size() == 3)
+			{
+				int dimSize1 = lowerDimSizes[0];
+				int dimSize2 = lowerDimSizes[1];
+				int dimSize3 = lowerDimSizes[2];
+				
+				BfTypedValue headPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures), &formatInfo);
+				if ((headPointer.mType != NULL) && (headPointer.mType->IsPointer()))
+				{
+					String evalStr = StrFormat("((%s[%d][%d]*)", ceModule->TypeToString(headPointer.mType->GetUnderlyingType()).c_str(), dimSize2, dimSize3) + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) +
+						StrFormat(" + {0} * %d), arraysize=%d, na, this=", dimSize1, dimSize1) + ptrUseDataStr;
+					evalStr += ", refid=\"" + referenceId + ".[]\"";
+					if (isReadOnly)
+						evalStr += ", ne";
+					retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, ValueToInt(sizeValue) / dimSize1 / dimSize2 / dimSize3, 50000) +
+						"\t[{0}]\t" + evalStr;
+				}
+			}
+			else
+			{
+				String evalStr = "*(" + debugVisualizers->DoStringReplace(debugVis->mValuePointer, dbgVisWildcardCaptures) + " + {0}), this=" + ptrUseDataStr;
+				evalStr += ", refid=\"" + referenceId + ".[]\"";
+				if (isReadOnly)
+					evalStr += ", ne";
+				retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, ValueToInt(sizeValue), 50000) +
+					"\t[{0}]\t" + evalStr;
+			}
+		}
+	}
+	else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_IndexItems)
+	{
+		BfTypedValue sizeValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
+
+		if ((sizeValue) && (sizeValue.mType->IsInteger()) && (ValueToInt(sizeValue) > 0))
+		{
+			String evalStr = debugVis->mValuePointer + ", this=" + ptrUseDataStr;
+			evalStr.Replace("$i", "{0}");
+
+			evalStr += ", refid=\"" + referenceId + ".[]\"";
+			if (isReadOnly)
+				evalStr += ", ne";
+			retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, ValueToInt(sizeValue), 50000) +
+				"\t[{0}]\t" + evalStr;
+		}
+	}
+	else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_LinkedList)
+	{
+		BfType* valueType = NULL;
+		if (!debugVis->mValueType.empty())
+		{
+			valueType = FindType(debugVisualizers->DoStringReplace(debugVis->mValueType, dbgVisWildcardCaptures));			
+		}
+
+		BfTypedValue headPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mHeadPointer, dbgVisWildcardCaptures), &formatInfo);
+		if (headPointer)
+		{
+			BfTypedValue endPointer;
+			if (!debugVis->mEndPointer.empty())
+				endPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mEndPointer, dbgVisWildcardCaptures), &formatInfo);
+			BfTypedValue nextPointer = EvaluateInContext(headPointer, debugVisualizers->DoStringReplace(debugVis->mNextPointer, dbgVisWildcardCaptures), &formatInfo);
+
+			int size = -1;
+			if (!debugVis->mSize.empty())
+			{
+				auto sizeValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
+				if (sizeValue)
+					size = (int)ValueToInt(sizeValue);
+			}
+
+			BfTypedValue curNode = headPointer;
+			Array<addr_ce> parentList;
+			String continuationData;
+
+			int totalSize = 2;
+			String addrs; //TODO: = GetLinkedListItems(debugVis, endPointer.mPtr, valueType, curNode, totalSize, &continuationData);
+			String firstAddr;
+			String secondAddr;
+			bool hasSecondAddr = valueType == NULL;
+			if (addrs.length() > 0)
+			{
+				const char* addrsPtr = addrs.c_str();
+				firstAddr = addrs.Substring(0, sizeof(addr_ce) * 2);
+				if (hasSecondAddr)
+					secondAddr = addrs.Substring(sizeof(addr_ce) * 2, sizeof(addr_ce) * 2);
+			}
+
+			String evalStr;
+			if (valueType != NULL)
+			{
+				auto ptrType = valueType;
+				if (!valueType->IsPointer())
+					ptrType = ceModule->CreatePointerType(valueType);
+				evalStr = StrFormat("(comptype(%d)", ptrType->mTypeId);
+				evalStr += ")0x{1}";
+			}
+			else
+			{
+				evalStr += "({1})0x{2}";
+			}
+			if (!debugVis->mShowElementAddrs)
+				evalStr.Insert(0, "*");
+
+			if (addrs.length() > 0)
+			{
+				evalStr += ", refid=\"" + referenceId + ".[]\"";
+				if (isReadOnly)
+					evalStr += ", ne";
+				retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, size, 10000) +
+					"\t[{0}]\t" + evalStr + "\t" + firstAddr;
+
+				if (hasSecondAddr)
+					retVal += "\t" + secondAddr;
+
+				if (size != 0)
+				{
+					retVal += "\n:addrs\t" + addrs;
+					if (valueType == NULL)
+						retVal += "\n:addrsEntrySize\t2";
+					if (continuationData.length() > 0)
+						retVal += "\n:continuation\t" + continuationData;
+				}
+			}
+		}
+	}
+	else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_TreeItems)
+	{
+		BfType* valueType = NULL;
+		if (!debugVis->mValueType.empty())
+		{
+			valueType = FindType(debugVisualizers->DoStringReplace(debugVis->mValueType, dbgVisWildcardCaptures));			
+		}
+
+		BfTypedValue sizeValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
+		BfTypedValue headPointer = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mHeadPointer, dbgVisWildcardCaptures), &formatInfo);
+		
+		if ((sizeValue) && (headPointer) && (sizeValue.mType->IsInteger()) && (ValueToInt(sizeValue) > 0))
+		{
+			BfTypedValue curNode = headPointer;
+			Array<addr_ce> parentList;
+			String continuationData;
+
+			int getItemCount = (int)BF_MIN(ValueToInt(sizeValue), 32LL);
+
+			String addrs; //TODO: = GetTreeItems(dbgCompileUnit, debugVis, parentList, valueType, curNode, getItemCount, &continuationData);
+			addr_ce firstAddr = 0;
+			addr_ce secondAddr = 0;
+			bool hasSecondAddr = valueType == NULL;
+			if (addrs.length() > 0)
+			{
+				const char* addrsPtr = addrs.c_str();
+				firstAddr = DecodeTargetDataPtr(addrsPtr);
+				if (hasSecondAddr)
+					secondAddr = DecodeTargetDataPtr(addrsPtr);
+			}
+
+			String evalStr;
+			if (valueType != NULL)
+			{
+				auto ptrType = valueType;
+				if (!valueType->IsPointer())
+					ptrType = ceModule->CreatePointerType(valueType);
+				evalStr = StrFormat("(comptype(%d)", ptrType->mTypeId);
+				evalStr += ")0x{1}";;
+			}
+			else
+			{
+				evalStr += "*(_T_{1}*)0x{2}";
+			}
+
+			int size = (int)ValueToInt(sizeValue);
+			if (addrs.length() == 0)
+			{
+				evalStr = ""; // Failed
+			}
+
+			evalStr += ", refid=\"" + referenceId + ".[]\"";
+			if (isReadOnly)
+				evalStr += ", ne";
+			retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, size, 10000) +
+				"\t[{0}]\t" + evalStr + "\t" + EncodeDataPtr(firstAddr, false);			
+
+			if (hasSecondAddr)
+				retVal += "\t" + EncodeDataPtr(secondAddr, false);
+
+			if (addrs.length() > 0)
+			{
+				retVal += "\n:addrs\t" + addrs;
+				if (continuationData.length() > 0)
+					retVal += "\n:continuation\t" + continuationData;
+			}
+		}
+	}
+	else if (debugVis->mCollectionType == DebugVisualizerEntry::CollectionType_Dictionary)
+	{
+		BfTypedValue sizeValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mSize, dbgVisWildcardCaptures), &formatInfo);
+		BfTypedValue entriesPtrValue = EvaluateInContext(typedValue, debugVisualizers->DoStringReplace(debugVis->mEntries, dbgVisWildcardCaptures), &formatInfo);
+		
+		if ((sizeValue) && (entriesPtrValue) && (sizeValue.mType->IsInteger()) && (ValueToInt(sizeValue) > 0))
+		{
+			String continuationData;
+
+			BfType* valueType = entriesPtrValue.mType;
+
+			int getItemCount = (int)BF_MIN(ValueToInt(sizeValue), 2LL);
+
+			BfType* useTypedValType = typedValue.mType;
+
+			String addrs; //TODO: = GetDictionaryItems(debugVis, useTypedValue, 0, -1, getItemCount, &continuationData);
+			addr_ce firstAddr = 0;
+			if (addrs.length() > 0)
+			{
+				const char* addrsPtr = addrs.c_str();
+				firstAddr = DecodeTargetDataPtr(addrsPtr);
+			}
+
+			String evalStr = "((comptype(" + StrFormat("%d", valueType->mTypeId) + "))0x{1}), na";
+
+			evalStr += ", refid=\"" + referenceId + ".[]\"";
+			if (isReadOnly)
+				evalStr += ", ne";
+			retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)ValueToInt(sizeValue), 10000) +
+				"\t[{0}]\t" + evalStr + "\t" + EncodeDataPtr(firstAddr, false);
+
+			if (addrs.length() > 0)
+			{
+				retVal += "\n:addrs\t" + addrs;
+				if (continuationData.length() > 0)
+					retVal += "\n:continuation\t" + continuationData;
+			}
+		}
+	}
+
+	if (formatInfo.mExpandItemDepth == 0)
+	{		
+		retVal += "\n[Raw View]\tthis,this=" + ptrUseDataStr + ", nv";
+	}
+}
+
+String CeDebugger::Evaluate(const StringImpl& expr, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags)
+{
+	CeFormatInfo formatInfo;
+	return Evaluate(expr, formatInfo, callStackIdx, cursorPos, language, expressionFlags);
+}
+
+String CeDebugger::EvaluateContinue()
+{
+	return String();
+}
+
+void CeDebugger::EvaluateContinueKeep()
+{
+}
+
+String CeDebugger::EvaluateToAddress(const StringImpl& expr, int callStackIdx, int cursorPos)
+{
+	return String();
+}
+
+String CeDebugger::EvaluateAtAddress(const StringImpl& expr, intptr atAddr, int cursorPos)
+{
+	return String();
+}
+
+String CeDebugger::GetAutoExpressions(int callStackIdx, uint64 memoryRangeStart, uint64 memoryRangeLen)
+{
+	return String();
+}
+
+String CeDebugger::GetAutoLocals(int callStackIdx, bool showRegs)
+{
+	String result;
+
+	auto ceFrame = GetFrame(callStackIdx);
+	if (ceFrame != NULL)
+	{
+		if (ceFrame->mFunction->mDbgInfo != NULL)
+		{
+			for (auto& dbgVar : ceFrame->mFunction->mDbgInfo->mVariables)
+			{
+				result += dbgVar.mName;
+				result += "\n";
+			}
+		}
+	}
+
+	return result;
+}
+
+String CeDebugger::CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx)
+{
+	return String();
+}
+
+String CeDebugger::GetProcessInfo()
+{
+	return String();
+}
+
+DebugVisualizerEntry* CeDebugger::FindVisualizerForType(BfType* dbgType, Array<String>* wildcardCaptures)
+{
+	auto ceModule = mCeMachine->mCeModule;
+
+	ceModule->PopulateType(dbgType);
+	auto entry = mDebugManager->mDebugVisualizers->FindEntryForType(ceModule->TypeToString(dbgType), DbgFlavor_Unknown, wildcardCaptures);
+
+	if (entry == NULL)
+	{				
+		auto typeInst = dbgType->ToTypeInstance();
+		if ((typeInst != NULL) && (typeInst->mBaseType != NULL))
+			entry = FindVisualizerForType(typeInst->mBaseType, wildcardCaptures);		
+	}
+
+	return entry;
+}
+
+String CeDebugger::GetThreadInfo()
+{
+	return String();
+}
+
+void CeDebugger::SetActiveThread(int threadId)
+{
+}
+
+int CeDebugger::GetActiveThread()
+{
+	return 0;
+}
+
+void CeDebugger::FreezeThread(int threadId)
+{
+}
+
+void CeDebugger::ThawThread(int threadId)
+{
+}
+
+bool CeDebugger::IsActiveThreadWaiting()
+{
+	return false;
+}
+
+void CeDebugger::ClearCallStack()
+{
+}
+
+void CeDebugger::UpdateCallStack(bool slowEarlyOut)
+{
+}
+
+int CeDebugger::GetCallStackCount()
+{
+	auto ceContext = mCeMachine->mCurContext;
+	if (ceContext == NULL)
+		return 0;
+	return ceContext->mCallStack.mSize;	
+}
+
+int CeDebugger::GetRequestedStackFrameIdx()
+{
+	return 0;
+}
+
+int CeDebugger::GetBreakStackFrameIdx()
+{
+	return 0;
+}
+
+bool CeDebugger::ReadMemory(intptr address, uint64 length, void* dest, bool local)
+{
+	auto ceContext = mCeMachine->mCurContext;
+	if (ceContext == NULL)
+		return false;
+	auto ptr = ceContext->GetMemoryPtr((addr_ce)address, (int32)length);
+	if (ptr == NULL)
+		return false;
+	memcpy(dest, ptr, length);
+	return true;
+}
+
+bool CeDebugger::WriteMemory(intptr address, void* src, uint64 length)
+{
+	auto ceContext = mCeMachine->mCurContext;
+	if (ceContext == NULL)
+		return false;
+	auto ptr = ceContext->GetMemoryPtr((addr_ce)address, (int32)length);
+	if (ptr == NULL)
+		return false;
+	memcpy(ptr, src, length);
+	return true;
+}
+
+DbgMemoryFlags CeDebugger::GetMemoryFlags(intptr address)
+{
+	return (DbgMemoryFlags)(DbgMemoryFlags_Read | DbgMemoryFlags_Write);
+}
+
+void CeDebugger::UpdateRegisterUsage(int stackFrameIdx)
+{
+}
+
+void CeDebugger::UpdateCallStackMethod(int stackFrameIdx)
+{
+}
+
+void CeDebugger::GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn)
+{
+}
+
+void CeDebugger::GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx)
+{
+	*outThreadId = 0;
+	if (outStackIdx != NULL)
+		*outStackIdx = -1;
+
+	auto ceContext = mCeMachine->mCurContext;
+	for (int i = 0; i < (int)ceContext->mCallStack.mSize; i++)
+	{
+		auto ceFrame = &ceContext->mCallStack[i];
+		if ((addr_ce)addr > ceFrame->mFrameAddr)
+		{
+			if (outStackIdx != NULL)
+				*outStackIdx = (int)ceContext->mCallStack.mSize - i - 1;
+		}
+	}	
+}
+
+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)
+{
+	enum FrameFlags
+	{
+		FrameFlags_Optimized = 1,
+		FrameFlags_HasPendingDebugInfo = 2,
+		FrameFlags_CanGetOldSource = 4,
+		FrameFlags_WasHotReplaced = 8,
+		FrameFlags_HadError = 0x10
+	};
+
+	auto ceContext = mCeMachine->mCurContext;
+	
+	*addr = 0;
+	*outFile = "";
+	*outHotIdx = 0;
+	*outDefLineStart = -1;
+	*outDefLineEnd = -1;
+	*outLine = -1;
+	*outColumn = 0;
+	*outLanguage = DbgLanguage_Beef;
+	*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 (ceFunction->mFailed)
+			*outFlags |= FrameFlags_HadError;
+
+		int instIdx = (int)(ceFrame->mInstPtr - &ceFunction->mCode[0] - 2);
+
+		BF_ASSERT(ceFunction->mId != -1);
+		*addr = ((intptr)ceFunction->mId << 32) | instIdx;
+
+		CeEmitEntry* emitEntry = ceFunction->FindEmitEntry(instIdx);
+		
+		if (stackIdx > 0)
+		{
+			auto prevFrame = &ceContext->mCallStack[stackIdx - 1];
+			*outStackSize = prevFrame->mStackAddr - ceFrame->mStackAddr;
+		}
+		else
+		{
+			*outStackSize = ceContext->mStackSize - ceFrame->mStackAddr;
+		}
+
+		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 "?";
+}
+
+BfType* CeDebugger::FindType(const StringImpl& name)
+{
+	//TODO:
+	return NULL;
+}
+
+String CeDebugger::Callstack_GetStackFrameOldFileInfo(int stackFrameIdx)
+{
+	return String();
+}
+
+#define CE_GET(T) *((T*)(ptr += sizeof(T)) - 1)
+
+int CeDebugger::GetJmpState(int stackFrameIdx)
+{
+	if (stackFrameIdx != 0)
+		return -1;
+
+	auto ceFrame = GetFrame(stackFrameIdx);
+	if (ceFrame == NULL)
+		return -1;
+
+	int instIdx = ceFrame->GetInstIdx();
+
+	auto ptr = &ceFrame->mFunction->mCode[instIdx];
+	auto op = CE_GET(CeOp);
+	switch (op)
+	{
+	case CeOp_Jmp:
+		return 1;
+	case CeOp_JmpIf:
+	case CeOp_JmpIfNot:
+		{
+			CE_GET(int32);
+			int frameOfs = CE_GET(int32);
+			bool willJump = *(bool*)(mCeMachine->mCurContext->mMemory.mVals + ceFrame->mFrameAddr + frameOfs);
+			if (op == CeOp_JmpIfNot)
+				willJump = !willJump;
+			return willJump ? 1 : 0;
+		}
+	}
+
+	return -1;
+}
+
+intptr CeDebugger::GetStackFrameCalleeAddr(int stackFrameIdx)
+{
+	return intptr();
+}
+
+String CeDebugger::GetStackMethodOwner(int stackFrameIdx, int& language)
+{
+	return String();
+}
+
+String CeDebugger::FindCodeAddresses(const StringImpl& fileName, int line, int column, bool allowAutoResolve)
+{
+	return String();
+}
+
+String CeDebugger::GetAddressSourceLocation(intptr address)
+{
+	return String();
+}
+
+String CeDebugger::GetAddressSymbolName(intptr address, bool demangle)
+{
+	return String();
+}
+
+String CeDebugger::DisassembleAtRaw(intptr address)
+{
+	return String();
+}
+
+String CeDebugger::DisassembleAt(intptr address)
+{
+	auto ceContext = mCeMachine->mCurContext;
+
+	mCurDisasmFuncId = (int)(address >> 32);
+	UpdateBreakpointAddrs();
+		
+	CeFunction* ceFunction = NULL;
+	if (!mCeMachine->mFunctionIdMap.TryGetValue(mCurDisasmFuncId, &ceFunction))
+		return "";
+
+	CeDumpContext dumpCtx;
+	dumpCtx.mCeFunction = ceFunction;
+	dumpCtx.mStart = &ceFunction->mCode[0];
+	dumpCtx.mPtr = dumpCtx.mStart;
+	dumpCtx.mEnd = dumpCtx.mPtr + ceFunction->mCode.mSize;
+
+	uint8* start = dumpCtx.mStart;
+	
+	dumpCtx.mStr += StrFormat("T Frame Size: %d\n", ceFunction->mFrameSize);
+	dumpCtx.mStr += StrFormat("A %llX\n", (intptr)mCurDisasmFuncId << 32);
+
+	int curEmitIdx = 0;
+	CeEmitEntry* prevEmitEntry = NULL;
+	CeEmitEntry* curEmitEntry = NULL;	
+
+	while (dumpCtx.mPtr < dumpCtx.mEnd)
+	{
+		int ofs = (int)(dumpCtx.mPtr - start);
+
+		while ((curEmitIdx < ceFunction->mEmitTable.mSize - 1) && (ofs >= ceFunction->mEmitTable[curEmitIdx + 1].mCodePos))
+			curEmitIdx++;
+		if (curEmitIdx < ceFunction->mEmitTable.mSize)
+			curEmitEntry = &ceFunction->mEmitTable[curEmitIdx];
+
+		if (prevEmitEntry != curEmitEntry)
+		{
+			if ((curEmitEntry != NULL) && (curEmitEntry->mLine != -1))
+			{
+				if ((prevEmitEntry == NULL) || (curEmitEntry->mScope != prevEmitEntry->mScope))
+				{
+					dumpCtx.mStr += StrFormat("S %s\n", ceFunction->mDbgScopes[curEmitEntry->mScope].mFilePath.c_str());
+				}
+
+				if ((prevEmitEntry != NULL) && (curEmitEntry->mScope == prevEmitEntry->mScope))
+				{
+					dumpCtx.mStr += StrFormat("L %d %d\n", prevEmitEntry->mLine + 1, curEmitEntry->mLine - prevEmitEntry->mLine);
+				}
+				else
+				{
+					int startLine = BF_MAX(0, curEmitEntry->mLine - 5);
+					dumpCtx.mStr += StrFormat("L %d %d\n", startLine, curEmitEntry->mLine - startLine + 1);
+				}
+
+				prevEmitEntry = curEmitEntry;
+			}			
+		}
+		
+		dumpCtx.mStr += StrFormat("D %04X: ", ofs);
+		dumpCtx.Next();		
+		dumpCtx.mStr += "\n";
+
+		if (dumpCtx.mJmp != -1)
+		{
+			dumpCtx.mStr += StrFormat("J %X\n", dumpCtx.mJmp);
+			dumpCtx.mJmp = -1;
+		}
+	}	
+
+	return dumpCtx.mStr;
+}
+
+String CeDebugger::FindLineCallAddresses(intptr address)
+{
+	return String();
+}
+
+String CeDebugger::GetCurrentException()
+{
+	return String();
+}
+
+String CeDebugger::GetModulesInfo()
+{
+	return String();
+}
+
+void CeDebugger::SetAliasPath(const StringImpl& origPath, const StringImpl& localPath)
+{
+}
+
+void CeDebugger::CancelSymSrv()
+{
+}
+
+bool CeDebugger::HasPendingDebugLoads()
+{
+	return false;
+}
+
+int CeDebugger::LoadImageForModule(const StringImpl& moduleName, const StringImpl& debugFileName)
+{
+	return 0;
+}
+
+int CeDebugger::LoadDebugInfoForModule(const StringImpl& moduleName)
+{
+	return 0;
+}
+
+int CeDebugger::LoadDebugInfoForModule(const StringImpl& moduleName, const StringImpl& debugFileName)
+{
+	return 0;
+}
+
+void CeDebugger::StopDebugging()
+{
+	mRunState = RunState_Terminating;
+	mCeMachine->mDebugEvent.Set(true);
+}
+
+void CeDebugger::Terminate()
+{
+}
+
+void CeDebugger::Detach()
+{
+	mRunState = RunState_Terminated;
+}
+
+Profiler* CeDebugger::StartProfiling()
+{
+	return nullptr;
+}
+
+Profiler* CeDebugger::PopProfiler()
+{
+	return nullptr;
+}
+
+void CeDebugger::ReportMemory(MemReporter* memReporter)
+{
+}
+
+bool CeDebugger::IsOnDemandDebugger()
+{
+	return true;
+}

+ 357 - 0
IDEHelper/Compiler/CeDebugger.h

@@ -0,0 +1,357 @@
+#pragma once
+
+#include "BfSystem.h"
+#include "BfModule.h"
+#include "BeefySysLib/util/Heap.h"
+#include "BeefySysLib/util/AllocDebug.h"
+#include "../Debugger.h"
+
+NS_BF_BEGIN
+
+class BfCompiler;
+class CeFrame;
+class CeExprEvaluator;
+class CeContext;
+class CeMachine;
+class CeFunction;
+class BfReducer;
+class CeDebugger;
+class DebugVisualizerEntry;
+
+class CeBreakpoint : public Breakpoint
+{
+public:		
+	uintptr mCurBindAddr;
+	bool mHasBound;
+	int mIdx;
+
+public:
+	CeBreakpoint()
+	{				
+		mCurBindAddr = 1;
+		mHasBound = false;
+		mIdx = -1;
+	}
+
+	virtual uintptr GetAddr() { return mCurBindAddr; }
+	virtual bool IsMemoryBreakpointBound() { return false; }
+};
+
+struct CeFormatInfo
+{
+	int mCallStackIdx;
+	bool mHidePointers;
+	bool mIgnoreDerivedClassInfo;
+	bool mNoVisualizers;
+	bool mNoMembers;
+	bool mRawString;
+	bool mNoEdit;
+	DbgTypeKindFlags mTypeKindFlags;
+	intptr mArrayLength;
+	intptr mOverrideCount;
+	intptr mMaxCount;
+	DwDisplayType mDisplayType;	
+	int mTotalSummaryLength;
+	String mReferenceId;
+	String mSubjectExpr;
+	String mExpectedType;
+	String mNamespaceSearch;
+	int mExpandItemDepth;
+	BfTypedValue mExplicitThis;
+
+	CeFormatInfo()
+	{
+		mCallStackIdx = -1;
+		mHidePointers = false;
+		mIgnoreDerivedClassInfo = false;
+		mRawString = false;
+		mNoVisualizers = false;
+		mNoMembers = false;
+		mNoEdit = false;
+		mTypeKindFlags = DbgTypeKindFlag_None;
+		mArrayLength = -1;
+		mOverrideCount = -1;
+		mMaxCount = -1;
+		mTotalSummaryLength = 0;
+		mDisplayType = DwDisplayType_NotSpecified;
+		mExpandItemDepth = 0;		
+	}
+};
+
+class CeEvaluationContext
+{
+public:
+	CeDebugger* mDebugger;
+	BfParser* mParser;
+	BfReducer* mReducer;
+	BfPassInstance* mPassInstance;
+	BfExprEvaluator* mExprEvaluator;
+	BfExpression* mExprNode;
+	BfTypedValue mResultOverride;	
+	String mExprString;
+
+	BfTypedValue mExplicitThis;
+	int mCallStackIdx;
+
+public:
+	CeEvaluationContext(CeDebugger* winDebugger, const StringImpl& expr, CeFormatInfo* formatInfo = NULL, BfTypedValue contextValue = BfTypedValue());
+	void Init(CeDebugger* winDebugger, const StringImpl& expr, CeFormatInfo* formatInfo = NULL, BfTypedValue contextValue = BfTypedValue());
+	bool HasExpression();
+	~CeEvaluationContext();
+	BfTypedValue EvaluateInContext(BfTypedValue contextTypedValue);
+	String GetErrorStr();
+	bool HadError();
+};
+
+class CeDbgState
+{
+public:
+	CeFrame* mActiveFrame;
+	CeContext* mCeContext;
+	BfTypedValue mExplicitThis;
+	DwEvalExpressionFlags mDbgExpressionFlags;
+	bool mHadSideEffects;
+	bool mBlockedSideEffects;
+
+public:
+	CeDbgState()
+	{
+		mActiveFrame = NULL;
+		mCeContext = NULL;
+		mDbgExpressionFlags = DwEvalExpressionFlag_None;
+		mHadSideEffects = false;
+		mBlockedSideEffects = false;
+	}
+};
+
+class CePendingExpr
+{
+public:
+	int mThreadId;
+	BfParser* mParser;
+	BfType* mExplitType;
+	CeFormatInfo mFormatInfo;
+	DwEvalExpressionFlags mExpressionFlags;
+	int mCursorPos;
+	BfAstNode* mExprNode;
+	String mReferenceId;
+	int mCallStackIdx;
+	String mResult;	
+	int mIdleTicks;
+	String mException;
+
+	CePendingExpr();
+	~CePendingExpr();
+};
+
+class CeFileInfo
+{
+public:
+	Array<CeBreakpoint*> mOrderedBreakpoints;
+};
+
+class CeDbgFieldEntry
+{
+public:
+	BfType* mType;
+	int mDataOffset;
+
+public:
+	CeDbgFieldEntry()
+	{
+		mType = NULL;
+		mDataOffset = 0;
+	}
+};
+
+class CeDbgTypeInfo
+{
+public:
+	struct ConstIntEntry
+	{
+	public:
+		int mFieldIdx;
+		int64 mVal;		
+	};
+
+public:
+	BfType* mType;
+	Array<CeDbgFieldEntry> mFieldOffsets;
+	Array<ConstIntEntry> mConstIntEntries;
+};
+
+struct CeTypedValue
+{
+	addr_ce mAddr;
+	BfIRType mType;
+
+	CeTypedValue()
+	{
+		mAddr = 0;
+		mType = BfIRType();
+	}
+
+	CeTypedValue(addr_ce addr, BfIRType type)
+	{
+		mAddr = addr;
+		mType = type;
+	}
+
+	operator bool() const
+	{
+		return mType.mKind != BfIRTypeData::TypeKind_None;
+	}
+};
+
+class CeDebugger : public Debugger
+{
+public:
+	BfCompiler* mCompiler;
+	CeMachine* mCeMachine;
+	DebugManager* mDebugManager;
+	CePendingExpr* mDebugPendingExpr;
+	CeDbgState* mCurDbgState;	
+	Array<CeBreakpoint*> mBreakpoints;
+	Dictionary<String, CeFileInfo*> mFileInfo;
+	Dictionary<int, CeDbgTypeInfo> mDbgTypeInfoMap;
+
+	CeEvaluationContext* mCurEvaluationContext;
+	CeBreakpoint* mActiveBreakpoint;
+	int mBreakpointVersion;
+	bool mBreakpointCacheDirty;	
+	bool mBreakpointFramesDirty;
+	int mCurDisasmFuncId;
+
+public:
+	bool SetupStep(int frameIdx = 0);
+	CeFrame* GetFrame(int callStackIdx);
+	String EvaluateContinue(CePendingExpr* pendingExpr, BfPassInstance& bfPassInstance);
+	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);
+	DebugVisualizerEntry* FindVisualizerForType(BfType* dbgType, Array<String>* wildcardCaptures);
+	bool ParseFormatInfo(const StringImpl& formatInfoStr, CeFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExprString, String* errorString, BfTypedValue contextTypedValue = BfTypedValue());
+	String MaybeQuoteFormatInfoParam(const StringImpl& str);
+	BfTypedValue EvaluateInContext(const BfTypedValue& contextTypedValue, const StringImpl& subExpr, CeFormatInfo* formatInfo = NULL, String* outReferenceId = NULL, String* outErrors = NULL);
+	void DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors);
+	String GetArrayItems(DebugVisualizerEntry* debugVis, BfType* valueType, BfTypedValue& curNode, int& count, String* outContinuationData);
+	String GetLinkedListItems(DebugVisualizerEntry* debugVis, addr_ce endNodePtr, BfType* valueType, BfTypedValue& curNode, int& count, String* outContinuationData);
+	String GetDictionaryItems(DebugVisualizerEntry* debugVis, BfTypedValue dictValue, int bucketIdx, int nodeIdx, int& count, String* outContinuationData);
+	String GetTreeItems(DebugVisualizerEntry* debugVis, Array<addr_ce>& parentList, BfType*& valueType, BfTypedValue& curNode, int count, String* outContinuationData);
+	bool EvalCondition(DebugVisualizerEntry* debugVis, BfTypedValue typedVal, CeFormatInfo& formatInfo, const StringImpl& condition, const Array<String>& dbgVisWildcardCaptures, String& errorStr);
+	CeTypedValue GetAddr(BfConstant* constant);
+	CeTypedValue GetAddr(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);
+	void HandleCustomExpandedItems(String& retVal, DebugVisualizerEntry* debugVis, BfTypedValue typedValue, addr_ce addr, addr_ce addrInst, Array<String>& dbgVisWildcardCaptures, CeFormatInfo& formatInfo);
+	void ClearBreakpointCache();
+	void UpdateBreakpointCache();
+	void UpdateBreakpointFrames();
+	void UpdateBreakpointAddrs();
+	void UpdateBreakpoints(CeFunction* ceFunction);	
+	void Continue();
+	CeDbgTypeInfo* GetDbgTypeInfo(int typeId);
+	CeDbgTypeInfo* GetDbgTypeInfo(BfIRType irType);
+	int64 ValueToInt(const BfTypedValue& typedVal);
+	BfType* FindType(const StringImpl& name);
+
+public:
+	CeDebugger(DebugManager* debugManager, BfCompiler* bfCompiler);
+	~CeDebugger();
+
+	virtual void OutputMessage(const StringImpl& msg) override;
+	virtual void OutputRawMessage(const StringImpl& msg) override;
+	virtual int GetAddrSize() override;
+	virtual bool CanOpen(const StringImpl& fileName, DebuggerResult* outResult) override;
+	virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled) override;
+	virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) override;
+	virtual void Run() override;
+	virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) override;
+	virtual void InitiateHotResolve(DbgHotResolveFlags flags) override;
+	virtual intptr GetDbgAllocHeapSize() override;
+	virtual String GetDbgAllocInfo() override;
+	virtual void Update() override;
+	virtual void ContinueDebugEvent() override;
+	virtual void ForegroundTarget() override;
+	virtual Breakpoint* CreateBreakpoint(const StringImpl& fileName, int lineNum, int wantColumn, int instrOffset) override;
+	virtual Breakpoint* CreateMemoryBreakpoint(intptr addr, int byteCount) override;
+	virtual Breakpoint* CreateSymbolBreakpoint(const StringImpl& symbolName) override;
+	virtual Breakpoint* CreateAddressBreakpoint(intptr address) override;
+	virtual uintptr GetBreakpointAddr(Breakpoint* breakpoint) override;
+	virtual void CheckBreakpoint(Breakpoint* breakpoint) override;
+	virtual void HotBindBreakpoint(Breakpoint* wdBreakpoint, int lineNum, int hotIdx) override;
+	virtual void DeleteBreakpoint(Breakpoint* wdBreakpoint) override;
+	virtual void DetachBreakpoint(Breakpoint* wdBreakpoint) override;
+	virtual void MoveBreakpoint(Breakpoint* wdBreakpoint, int lineNum, int wantColumn, bool rebindNow) override;
+	virtual void MoveMemoryBreakpoint(Breakpoint* wdBreakpoint, intptr addr, int byteCount) override;
+	virtual void DisableBreakpoint(Breakpoint* wdBreakpoint) override;
+	virtual void SetBreakpointCondition(Breakpoint* wdBreakpoint, const StringImpl& condition) override;
+	virtual void SetBreakpointLogging(Breakpoint* wdBreakpoint, const StringImpl& logging, bool breakAfterLogging) override;
+	virtual Breakpoint* FindBreakpointAt(intptr address) override;
+	virtual Breakpoint* GetActiveBreakpoint() override;
+	virtual void BreakAll() override;
+	virtual bool TryRunContinue() override;
+	virtual void StepInto(bool inAssembly) override;
+	virtual void StepIntoSpecific(intptr addr) override;
+	virtual void StepOver(bool inAssembly) override;
+	virtual void StepOut(bool inAssembly) override;
+	virtual void SetNextStatement(bool inAssembly, const StringImpl& fileName, int64 lineNumOrAsmAddr, int wantColumn) override;	
+	//virtual DbgTypedValue GetRegister(const StringImpl& regName, CPURegisters* registers, Array<RegForm>* regForms = NULL) override;
+	virtual String Evaluate(const StringImpl& expr, int callStackIdx, int cursorPos, int language, DwEvalExpressionFlags expressionFlags) override;
+	virtual String EvaluateContinue() override;
+	virtual void EvaluateContinueKeep() override;
+	virtual String EvaluateToAddress(const StringImpl& expr, int callStackIdx, int cursorPos) override;
+	virtual String EvaluateAtAddress(const StringImpl& expr, intptr atAddr, int cursorPos) override;
+	virtual String GetCollectionContinuation(const StringImpl& continuationData, int callStackIdx, int count) override;
+	virtual String GetAutoExpressions(int callStackIdx, uint64 memoryRangeStart, uint64 memoryRangeLen) override;
+	virtual String GetAutoLocals(int callStackIdx, bool showRegs) override;
+	virtual String CompactChildExpression(const StringImpl& expr, const StringImpl& parentExpr, int callStackIdx) override;
+	virtual String GetProcessInfo() override;
+	virtual String GetThreadInfo() override;
+	virtual void SetActiveThread(int threadId) override;
+	virtual int GetActiveThread() override;
+	virtual void FreezeThread(int threadId) override;
+	virtual void ThawThread(int threadId) override;
+	virtual bool IsActiveThreadWaiting() override;
+	virtual void ClearCallStack() override;
+	virtual void UpdateCallStack(bool slowEarlyOut = true) override;
+	virtual int GetCallStackCount() override;
+	virtual int GetRequestedStackFrameIdx() override;
+	virtual int GetBreakStackFrameIdx() override;
+	virtual bool ReadMemory(intptr address, uint64 length, void* dest, bool local = false) override;
+	virtual bool WriteMemory(intptr address, void* src, uint64 length) override;
+	virtual DbgMemoryFlags GetMemoryFlags(intptr address) override;
+	virtual void UpdateRegisterUsage(int stackFrameIdx) override;
+	virtual void UpdateCallStackMethod(int stackFrameIdx) override;
+	virtual void GetCodeAddrInfo(intptr addr, String* outFile, int* outHotIdx, int* outDefLineStart, int* outDefLineEnd, int* outLine, int* outColumn) override;
+	virtual void GetStackAllocInfo(intptr addr, int* outThreadId, int* outStackIdx) override;
+	virtual String GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* outFile, int32* outHotIdx, int32* outDefLineStart, int32* outDefLineEnd, int32* outLine, int32* outColumn, int32* outLanguage, int32* outStackSize, int8* outFlags) override;
+	virtual String Callstack_GetStackFrameOldFileInfo(int stackFrameIdx) override;
+	virtual int GetJmpState(int stackFrameIdx) override;
+	virtual intptr GetStackFrameCalleeAddr(int stackFrameIdx) override;
+	virtual String GetStackMethodOwner(int stackFrameIdx, int& language) override;
+	virtual String FindCodeAddresses(const StringImpl& fileName, int line, int column, bool allowAutoResolve) override;
+	virtual String GetAddressSourceLocation(intptr address) override;
+	virtual String GetAddressSymbolName(intptr address, bool demangle) override;
+	virtual String DisassembleAtRaw(intptr address) override;
+	virtual String DisassembleAt(intptr address) override;
+	virtual String FindLineCallAddresses(intptr address) override;
+	virtual String GetCurrentException() override;
+	virtual String GetModulesInfo() override;
+	virtual void SetAliasPath(const StringImpl& origPath, const StringImpl& localPath) override;
+	virtual void CancelSymSrv() override;
+	virtual bool HasPendingDebugLoads() override;
+	virtual int LoadImageForModule(const StringImpl& moduleName, const StringImpl& debugFileName) override;
+	virtual int LoadDebugInfoForModule(const StringImpl& moduleName) override;
+	virtual int LoadDebugInfoForModule(const StringImpl& moduleName, const StringImpl& debugFileName) override;
+	virtual void StopDebugging() override;
+	virtual void Terminate() override;
+	virtual void Detach() override;
+	virtual Profiler* StartProfiling() override;
+	virtual Profiler* PopProfiler() override; // Profiler requested by target program
+	virtual void ReportMemory(MemReporter* memReporter) override;
+	virtual bool IsOnDemandDebugger() override;
+};
+
+NS_BF_END

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 546 - 199
IDEHelper/Compiler/CeMachine.cpp


+ 160 - 52
IDEHelper/Compiler/CeMachine.h

@@ -24,6 +24,8 @@ class BeSwitchInst;
 class BeGlobalVariable;
 class BeGlobalVariable;
 class CeMachine;
 class CeMachine;
 class CeFunction;
 class CeFunction;
+class CeDebugger;
+class CeBreakpoint;
 
 
 #define CEOP_SIZED(OPNAME) \
 #define CEOP_SIZED(OPNAME) \
 	CeOp_##OPNAME##_8, \
 	CeOp_##OPNAME##_8, \
@@ -69,6 +71,7 @@ enum CeErrorKind
 enum CeOp : int16
 enum CeOp : int16
 {
 {
 	CeOp_InvalidOp,
 	CeOp_InvalidOp,
+	CeOp_DbgBreak,
 	CeOp_Ret,
 	CeOp_Ret,
 	CeOp_SetRetType,
 	CeOp_SetRetType,
 	CeOp_Jmp,
 	CeOp_Jmp,
@@ -204,10 +207,55 @@ enum CeOp : int16
 	CeOp_COUNT
 	CeOp_COUNT
 };
 };
 
 
+enum CeOperandKind
+{
+	CeOperandKind_None,
+	CeOperandKind_FrameOfs,
+	CeOperandKind_AllocaAddr,
+	CeOperandKind_Block,
+	CeOperandKind_Immediate,
+	CeOperandKind_ConstStructTableIdx,
+	CeOperandKind_CallTableIdx
+};
+
+class CeOperand
+{
+public:
+	CeOperandKind mKind;
+	union
+	{
+		int mFrameOfs;
+		int mBlockIdx;
+		int mImmediate;
+		int mCallTableIdx;
+		int mStructTableIdx;
+		BeConstant* mConstant;
+	};
+	BeType* mType;
+
+public:
+	CeOperand()
+	{
+		mKind = CeOperandKind_None;
+		mFrameOfs = 0;
+		mType = NULL;
+	}
+
+	operator bool() const
+	{
+		return mKind != CeOperandKind_None;
+	}
+
+	bool IsImmediate()
+	{
+		return mKind == CeOperandKind_Immediate;
+	}
+};
+
 struct CeEmitEntry
 struct CeEmitEntry
 {
 {
 	int mCodePos;
 	int mCodePos;
-	int mFile;
+	int mScope;
 	int mLine;
 	int mLine;
 	int mColumn;
 	int mColumn;
 };
 };
@@ -490,6 +538,40 @@ public:
 	}
 	}
 };
 };
 
 
+class CeDbgVariable
+{
+public:
+	String mName;
+	CeOperand mValue;
+	BfType* mType;
+};
+
+class CeDbgFunctionInfo
+{
+public:
+	Array<CeDbgVariable> mVariables;
+};
+
+class CeBreakpointBind
+{
+public:
+	CeOp mPrevOpCode;
+	CeBreakpoint* mBreakpoint;
+};
+
+struct CeDbgScope
+{
+public:
+	String mFilePath;
+	int mInlinedAt;
+
+public:
+	CeDbgScope()
+	{
+		mInlinedAt = -1;
+	}
+};
+
 class CeFunction
 class CeFunction
 {
 {
 public:
 public:
@@ -511,7 +593,7 @@ public:
 	bool mFailed;
 	bool mFailed;
 	bool mIsVarReturn;
 	bool mIsVarReturn;
 	Array<uint8> mCode;	
 	Array<uint8> mCode;	
-	Array<String> mFiles;
+	Array<CeDbgScope> mDbgScopes;
 	Array<CeEmitEntry> mEmitTable;
 	Array<CeEmitEntry> mEmitTable;
 	Array<CeCallEntry> mCallTable;
 	Array<CeCallEntry> mCallTable;
 	Array<CeStringEntry> mStringTable;
 	Array<CeStringEntry> mStringTable;
@@ -519,10 +601,13 @@ public:
 	Array<CeStaticFieldEntry> mStaticFieldTable;
 	Array<CeStaticFieldEntry> mStaticFieldTable;
 	Array<BfType*> mTypeTable;
 	Array<BfType*> mTypeTable;
 	Array<CeFunction*> mInnerFunctions;
 	Array<CeFunction*> mInnerFunctions;
+	Dictionary<int, CeBreakpointBind> mBreakpoints;
 	String mGenError;
 	String mGenError;
 	int mFrameSize;	
 	int mFrameSize;	
 	int mMaxReturnSize;
 	int mMaxReturnSize;
-	int mId;	
+	int mId;
+	int mBreakpointVersion;
+	CeDbgFunctionInfo* mDbgInfo;
 
 
 public:
 public:
 	CeFunction()
 	CeFunction()
@@ -537,11 +622,15 @@ public:
 		mIsVarReturn = false;
 		mIsVarReturn = false;
 		mFrameSize = 0;
 		mFrameSize = 0;
 		mMaxReturnSize = 0;
 		mMaxReturnSize = 0;
+		mBreakpointVersion = 0;
 		mId = -1;
 		mId = -1;
+		mDbgInfo = NULL;
 	}	
 	}	
 
 
 	~CeFunction();
 	~CeFunction();
 	void Print();
 	void Print();
+	void UnbindBreakpoints();
+	CeEmitEntry* FindEmitEntry(int loc, int* entryIdx = NULL);
 };
 };
 
 
 enum CeEvalFlags
 enum CeEvalFlags
@@ -551,52 +640,8 @@ enum CeEvalFlags
 	CeEvalFlags_PersistantError = 2,
 	CeEvalFlags_PersistantError = 2,
 	CeEvalFlags_DeferIfNotOnlyError = 4,
 	CeEvalFlags_DeferIfNotOnlyError = 4,
 	CeEvalFlags_NoRebuild = 8,
 	CeEvalFlags_NoRebuild = 8,
-	CeEvalFlags_ForceReturnThis = 0x10
-};
-
-enum CeOperandKind
-{
-	CeOperandKind_None,
-	CeOperandKind_FrameOfs,
-	CeOperandKind_AllocaAddr,
-	CeOperandKind_Block,
-	CeOperandKind_Immediate,
-	CeOperandKind_ConstStructTableIdx,	
-	CeOperandKind_CallTableIdx
-};
-
-class CeOperand
-{
-public:
-	CeOperandKind mKind;
-	union
-	{
-		int mFrameOfs;
-		int mBlockIdx;
-		int mImmediate;
-		int mCallTableIdx;
-		int mStructTableIdx;
-		BeConstant* mConstant;
-	};
-	BeType* mType;
-
-public:
-	CeOperand()
-	{
-		mKind = CeOperandKind_None;
-		mFrameOfs = 0;
-		mType = NULL;
-	}
-
-	operator bool() const
-	{
-		return mKind != CeOperandKind_None;
-	}
-
-	bool IsImmediate()
-	{
-		return mKind == CeOperandKind_Immediate;
-	}
+	CeEvalFlags_ForceReturnThis = 0x10,
+	CeEvalFlags_DbgCall = 0x20
 };
 };
 
 
 #define BF_CE_DEFAULT_STACK_SIZE 4*1024*1024
 #define BF_CE_DEFAULT_STACK_SIZE 4*1024*1024
@@ -609,7 +654,21 @@ public:
 enum CeOperandInfoKind
 enum CeOperandInfoKind
 {
 {
 	CEOI_None,
 	CEOI_None,
+	CEOI_None8 = CEOI_None,
+	CEOI_None16 = CEOI_None,
+	CEOI_None32 = CEOI_None,
+	CEOI_None64 = CEOI_None,
+	CEOI_NoneF32 = CEOI_None,
+	CEOI_NoneF64 = CEOI_None,
+
 	CEOI_FrameRef,
 	CEOI_FrameRef,
+	CEOI_FrameRef8,
+	CEOI_FrameRef16,
+	CEOI_FrameRef32,
+	CEOI_FrameRef64,
+	CEOI_FrameRefF32,
+	CEOI_FrameRefF64,
+
 	CEOI_IMM8,
 	CEOI_IMM8,
 	CEOI_IMM16,
 	CEOI_IMM16,
 	CEOI_IMM32,
 	CEOI_IMM32,
@@ -631,18 +690,24 @@ enum CeSizeClass
 
 
 class CeDumpContext
 class CeDumpContext
 {
 {
-
-
 public:	
 public:	
+	Dictionary<int, CeDbgVariable*> mVarMap;
 	CeFunction* mCeFunction;
 	CeFunction* mCeFunction;
 	String mStr;
 	String mStr;
 	uint8* mStart;
 	uint8* mStart;
 	uint8* mPtr;
 	uint8* mPtr;
 	uint8* mEnd;
 	uint8* mEnd;
+	int mJmp;
 
 
 public:
 public:
+	CeDumpContext()
+	{
+		mJmp = -1;
+	}
+
 	void DumpOperandInfo(CeOperandInfoKind operandInfoKind);
 	void DumpOperandInfo(CeOperandInfoKind operandInfoKind);
 
 
+	void Next();
 	void Dump();	
 	void Dump();	
 };
 };
 
 
@@ -760,6 +825,11 @@ public:
 		mInstPtr = NULL;
 		mInstPtr = NULL;
 		mReturnType = NULL;
 		mReturnType = NULL;
 	}
 	}
+
+	int GetInstIdx()
+	{
+		return (int)(mInstPtr - &mFunction->mCode[0] - 2);
+	}
 };
 };
 
 
 class CeStaticFieldInfo
 class CeStaticFieldInfo
@@ -909,6 +979,7 @@ public:
 	BfType* GetBfType(BfIRType irType);
 	BfType* GetBfType(BfIRType irType);
 	void PrepareConstStructEntry(CeConstStructData& constStructData);
 	void PrepareConstStructEntry(CeConstStructData& constStructData);
 	bool CheckMemory(addr_ce addr, int32 size);
 	bool CheckMemory(addr_ce addr, int32 size);
+	uint8* GetMemoryPtr(addr_ce addr, int32 size);
 	bool GetStringFromAddr(addr_ce strInstAddr, StringImpl& str);
 	bool GetStringFromAddr(addr_ce strInstAddr, StringImpl& str);
 	bool GetStringFromStringView(addr_ce addr, StringImpl& str);
 	bool GetStringFromStringView(addr_ce addr, StringImpl& str);
 	bool GetCustomAttribute(BfModule* module, BfIRConstHolder* constHolder, BfCustomAttributes* customAttributes, int attributeIdx, addr_ce resultAddr);
 	bool GetCustomAttribute(BfModule* module, BfIRConstHolder* constHolder, BfCustomAttributes* customAttributes, int attributeIdx, addr_ce resultAddr);
@@ -928,12 +999,40 @@ struct CeTypeInfo
 	int mRevision;
 	int mRevision;
 };
 };
 
 
+class CeStepState
+{
+public:
+	enum Kind
+	{
+		Kind_None,
+		Kind_StepOver,
+		Kind_StepOver_Asm,
+		Kind_StepInfo,
+		Kind_StepInfo_Asm,
+		Kind_StepOut,
+		Kind_StepOut_Asm,
+		Kind_Jmp
+	};
+
+	Kind mKind;	
+	int mNextInstIdx;
+	int mStartDepth;
+
+public:
+	CeStepState()
+	{
+		mKind = Kind_None;		
+		mNextInstIdx = -1;
+		mStartDepth = 0;
+	}
+};
+
 class CeMachine
 class CeMachine
 {
 {
 public:
 public:
 	Dictionary<BfMethodInstance*, CeFunctionInfo*> mFunctions;
 	Dictionary<BfMethodInstance*, CeFunctionInfo*> mFunctions;
 	Dictionary<String, CeFunctionInfo*> mNamedFunctionMap;
 	Dictionary<String, CeFunctionInfo*> mNamedFunctionMap;
-	Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit			
+	Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit and debugging
 	Dictionary<BfType*, CeTypeInfo> mTypeInfoMap;
 	Dictionary<BfType*, CeTypeInfo> mTypeInfoMap;
 	HashSet<BfMethodInstance*> mMethodInstanceSet;
 	HashSet<BfMethodInstance*> mMethodInstanceSet;
 	HashSet<BfFieldInstance*> mFieldInstanceSet;
 	HashSet<BfFieldInstance*> mFieldInstanceSet;
@@ -959,6 +1058,14 @@ public:
 	BfReducer* mTempReducer;
 	BfReducer* mTempReducer;
 	BfPassInstance* mTempPassInstance;
 	BfPassInstance* mTempPassInstance;
 
 
+	CritSect mCritSect;
+	SyncEvent mDebugEvent;
+	CeStepState mStepState;
+	CeDebugger* mDebugger;
+	bool mDbgPaused;	
+	bool mSpecialCheck;
+	bool mDbgWantBreak;
+
 public:
 public:
 	CeMachine(BfCompiler* compiler);
 	CeMachine(BfCompiler* compiler);
 	~CeMachine();		
 	~CeMachine();		
@@ -967,6 +1074,7 @@ public:
 	BeContext* GetBeContext();
 	BeContext* GetBeContext();
 	BeModule* GetBeModule();
 	BeModule* GetBeModule();
 
 
+	int GetInstSize(CeFunction* ceFunction, int instIdx);
 	void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo);
 	void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo);
 	void RemoveFunc(CeFunction* ceFunction);
 	void RemoveFunc(CeFunction* ceFunction);
 	void RemoveMethod(BfMethodInstance* methodInstance);					
 	void RemoveMethod(BfMethodInstance* methodInstance);					

+ 1 - 1
IDEHelper/DbgExprEvaluator.cpp

@@ -7676,7 +7676,7 @@ DbgTypedValue DbgExprEvaluator::MatchMethod(BfAstNode* targetSrc, DbgTypedValue
 			if (bitCount <= 0)
 			if (bitCount <= 0)
 				return argValues[0];
 				return argValues[0];
 			
 			
-			int64 andBits = (0x8000000000000000LL) >> ((argValues[0].mType->GetByteCount() - 8) * 8 + bitCount - 1);			
+			int64 andBits = (0x8000000000000000LL) >> ((argValues[0].mType->GetByteCount() - 8) * 8 + bitCount - 1);
 			DbgTypedValue result;
 			DbgTypedValue result;
 			result.mType = argValues[0].mType;
 			result.mType = argValues[0].mType;
 			result.mInt64 = val & ~andBits;
 			result.mInt64 = val & ~andBits;

+ 43 - 0
IDEHelper/DbgExprEvaluator.h

@@ -184,6 +184,49 @@ public:
 	}
 	}
 };
 };
 
 
+struct DwFormatInfo
+{
+	int mCallStackIdx;
+	bool mHidePointers;
+	bool mIgnoreDerivedClassInfo;
+	bool mNoVisualizers;
+	bool mNoMembers;
+	bool mRawString;
+	bool mNoEdit;
+	DbgTypeKindFlags mTypeKindFlags;
+	intptr mArrayLength;
+	intptr mOverrideCount;
+	intptr mMaxCount;
+	DwDisplayType mDisplayType;
+	DbgTypedValue mExplicitThis;
+	int mTotalSummaryLength;
+	String mReferenceId;
+	String mSubjectExpr;
+	String mExpectedType;
+	String mNamespaceSearch;
+	int mExpandItemDepth;
+	DbgLanguage mLanguage;
+
+	DwFormatInfo()
+	{
+		mCallStackIdx = -1;
+		mHidePointers = false;
+		mIgnoreDerivedClassInfo = false;
+		mRawString = false;
+		mNoVisualizers = false;
+		mNoMembers = false;
+		mNoEdit = false;
+		mTypeKindFlags = DbgTypeKindFlag_None;
+		mArrayLength = -1;
+		mOverrideCount = -1;
+		mMaxCount = -1;
+		mTotalSummaryLength = 0;
+		mDisplayType = DwDisplayType_NotSpecified;
+		mExpandItemDepth = 0;
+		mLanguage = DbgLanguage_Unknown;
+	}
+};
+
 struct DbgMethodArgument
 struct DbgMethodArgument
 {
 {
 	DbgTypedValue mTypedValue;
 	DbgTypedValue mTypedValue;

+ 17 - 4
IDEHelper/DebugManager.cpp

@@ -11,6 +11,7 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "BeefySysLib/util/BeefPerf.h"
 #include "BeefySysLib/util/BeefPerf.h"
 #include "NetManager.h"
 #include "NetManager.h"
+#include "Compiler/CeDebugger.h"
 
 
 #ifdef BF_PLATFORM_WINDOWS
 #ifdef BF_PLATFORM_WINDOWS
 #include "DbgMiniDump.h"
 #include "DbgMiniDump.h"
@@ -79,7 +80,7 @@ DebugManager::DebugManager()
 	mStepOverExternalFiles = false;
 	mStepOverExternalFiles = false;
 
 
 	mDebugger32 = NULL;
 	mDebugger32 = NULL;
-	mDebugger64 = NULL;
+	mDebugger64 = NULL;	
 	mNetManager = new NetManager();
 	mNetManager = new NetManager();
 	mNetManager->mDebugManager = this;
 	mNetManager->mDebugManager = this;
 
 
@@ -97,14 +98,20 @@ DebugManager::DebugManager()
 
 
 DebugManager::~DebugManager()
 DebugManager::~DebugManager()
 {
 {
+	if ((gDebugger != NULL) && (gDebugger->IsOnDemandDebugger()))
+	{
+		delete gDebugger;
+		gDebugger = NULL;
+	}
+
 	delete mNetManager;
 	delete mNetManager;
 	delete mDebugger64;
 	delete mDebugger64;
-	delete mDebugger32;	
+	delete mDebugger32;		
 	/*for (auto stepFilter : mStepFilters)
 	/*for (auto stepFilter : mStepFilters)
 	{
 	{
 
 
 	}*/
 	}*/
-	delete mDebugVisualizers;
+	delete mDebugVisualizers;	
 }
 }
 
 
 void DebugManager::OutputMessage(const StringImpl& msg)
 void DebugManager::OutputMessage(const StringImpl& msg)
@@ -779,6 +786,12 @@ BF_EXPORT bool BF_CALLTYPE Debugger_OpenFile(const char* launchPath, const char*
 	return true;
 	return true;
 }
 }
 
 
+BF_EXPORT bool BF_CALLTYPE Debugger_ComptimeAttach(void* bfCompiler)
+{	
+	gDebugger = new CeDebugger(gDebugManager, (BfCompiler*)bfCompiler);
+	return true;
+}
+
 BF_EXPORT void BF_CALLTYPE Debugger_SetSymSrvOptions(const char* symCacheDir, const char* symSrvStr, int flags)
 BF_EXPORT void BF_CALLTYPE Debugger_SetSymSrvOptions(const char* symCacheDir, const char* symSrvStr, int flags)
 {
 {
 	Array<String> symServers;
 	Array<String> symServers;
@@ -1021,7 +1034,7 @@ BF_EXPORT uintptr BF_CALLTYPE Breakpoint_GetAddress(Breakpoint* wdBreakpoint, Br
 {
 {
 	if (outLinkedSibling != NULL)
 	if (outLinkedSibling != NULL)
 		*outLinkedSibling = wdBreakpoint->mLinkedSibling;
 		*outLinkedSibling = wdBreakpoint->mLinkedSibling;
-	return wdBreakpoint->GetAddr();
+	return gDebugger->GetBreakpointAddr(wdBreakpoint);
 }
 }
 
 
 BF_EXPORT bool BF_CALLTYPE Breakpoint_IsMemoryBreakpointBound(Breakpoint* wdBreakpoint)
 BF_EXPORT bool BF_CALLTYPE Breakpoint_IsMemoryBreakpointBound(Breakpoint* wdBreakpoint)

+ 1 - 1
IDEHelper/DebugManager.h

@@ -65,7 +65,7 @@ class DebugManager
 {
 {
 public:
 public:
 	Debugger* mDebugger32;
 	Debugger* mDebugger32;
-	Debugger* mDebugger64;
+	Debugger* mDebugger64;	
 
 
 	CritSect mCritSect;
 	CritSect mCritSect;
 	Dictionary<String, StepFilter> mStepFilters;
 	Dictionary<String, StepFilter> mStepFilters;

+ 9 - 1
IDEHelper/Debugger.h

@@ -62,6 +62,13 @@ public:
 	virtual bool IsMemoryBreakpointBound() = 0;
 	virtual bool IsMemoryBreakpointBound() = 0;
 };
 };
 
 
+
+enum DbgTypeKindFlags
+{
+	DbgTypeKindFlag_None = 0,
+	DbgTypeKindFlag_Int = 1
+};
+
 enum DwDisplayType : int8
 enum DwDisplayType : int8
 {
 {
 	DwDisplayType_NotSpecified,
 	DwDisplayType_NotSpecified,
@@ -282,6 +289,7 @@ public:
 	virtual void SetBreakpointLogging(Breakpoint* wdBreakpoint, const StringImpl& logging, bool breakAfterLogging) = 0;
 	virtual void SetBreakpointLogging(Breakpoint* wdBreakpoint, const StringImpl& logging, bool breakAfterLogging) = 0;
 	virtual Breakpoint* FindBreakpointAt(intptr address) = 0;
 	virtual Breakpoint* FindBreakpointAt(intptr address) = 0;
 	virtual Breakpoint* GetActiveBreakpoint() = 0;
 	virtual Breakpoint* GetActiveBreakpoint() = 0;
+	virtual uintptr GetBreakpointAddr(Breakpoint* breakpoint) { return breakpoint->GetAddr(); }
 	virtual void BreakAll() = 0;
 	virtual void BreakAll() = 0;
 	virtual bool TryRunContinue() = 0;
 	virtual bool TryRunContinue() = 0;
 	virtual void StepInto(bool inAssembly) = 0;
 	virtual void StepInto(bool inAssembly) = 0;
@@ -343,7 +351,7 @@ public:
 	virtual Profiler* StartProfiling() = 0;
 	virtual Profiler* StartProfiling() = 0;
 	virtual Profiler* PopProfiler() = 0; // Profiler requested by target program
 	virtual Profiler* PopProfiler() = 0; // Profiler requested by target program
 	virtual void ReportMemory(MemReporter* memReporter) = 0;
 	virtual void ReportMemory(MemReporter* memReporter) = 0;
-	virtual bool IsOnDemandDebugger() = 0;		
+	virtual bool IsOnDemandDebugger() = 0;			
 };
 };
 
 
 class Profiler
 class Profiler

+ 2 - 0
IDEHelper/IDEHelper.vcxproj

@@ -331,6 +331,7 @@
     <ClCompile Include="Compiler\BfTargetTriple.cpp" />
     <ClCompile Include="Compiler\BfTargetTriple.cpp" />
     <ClCompile Include="Compiler\BfUtil.cpp" />
     <ClCompile Include="Compiler\BfUtil.cpp" />
     <ClCompile Include="Compiler\BfVarDeclChecker.cpp" />
     <ClCompile Include="Compiler\BfVarDeclChecker.cpp" />
+    <ClCompile Include="Compiler\CeDebugger.cpp" />
     <ClCompile Include="Compiler\CeMachine.cpp" />
     <ClCompile Include="Compiler\CeMachine.cpp" />
     <ClCompile Include="Compiler\MemReporter.cpp" />
     <ClCompile Include="Compiler\MemReporter.cpp" />
     <ClCompile Include="DbgMiniDump.cpp" />
     <ClCompile Include="DbgMiniDump.cpp" />
@@ -399,6 +400,7 @@
     <ClInclude Include="Compiler\BfCompiler.h" />
     <ClInclude Include="Compiler\BfCompiler.h" />
     <ClInclude Include="Compiler\BfUtil.h" />
     <ClInclude Include="Compiler\BfUtil.h" />
     <ClInclude Include="Compiler\BfVarDeclChecker.h" />
     <ClInclude Include="Compiler\BfVarDeclChecker.h" />
+    <ClInclude Include="Compiler\CeDebugger.h" />
     <ClInclude Include="Compiler\CeMachine.h" />
     <ClInclude Include="Compiler\CeMachine.h" />
     <ClInclude Include="third_party\FtsFuzzyMatch.h" />
     <ClInclude Include="third_party\FtsFuzzyMatch.h" />
     <ClInclude Include="Compiler\MemReporter.h" />
     <ClInclude Include="Compiler\MemReporter.h" />

+ 6 - 0
IDEHelper/IDEHelper.vcxproj.filters

@@ -214,6 +214,9 @@
     <ClCompile Include="Compiler\CeMachine.cpp">
     <ClCompile Include="Compiler\CeMachine.cpp">
       <Filter>Compiler</Filter>
       <Filter>Compiler</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Compiler\CeDebugger.cpp">
+      <Filter>Compiler</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="Compiler\BfAst.h">
     <ClInclude Include="Compiler\BfAst.h">
@@ -405,5 +408,8 @@
     <ClInclude Include="third_party\FtsFuzzyMatch.h">
     <ClInclude Include="third_party\FtsFuzzyMatch.h">
       <Filter>third_party</Filter>
       <Filter>third_party</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Compiler\CeDebugger.h">
+      <Filter>Compiler</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 4 - 3
IDEHelper/WinDebugger.cpp

@@ -5825,7 +5825,7 @@ bool WinDebugger::EvalCondition(DebugVisualizerEntry* debugVis, DbgCompileUnit*
 		return false;
 		return false;
 	}
 	}
 
 
-	return evalResult.mBool;		
+	return evalResult.mBool;
 }
 }
 
 
 String WinDebugger::GetArrayItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, DbgType* valueType, DbgTypedValue& curNode, int& count, String* outContinuationData)
 String WinDebugger::GetArrayItems(DbgCompileUnit* dbgCompileUnit, DebugVisualizerEntry* debugVis, DbgType* valueType, DbgTypedValue& curNode, int& count, String* outContinuationData)
@@ -8156,7 +8156,7 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c
 				displayString += "{ " + firstRet + " }";
 				displayString += "{ " + firstRet + " }";
 			else
 			else
 				displayString += bigRet;			
 				displayString += bigRet;			
-		}		
+		}
 		
 		
 		DbgType* memberListType = actualType;				
 		DbgType* memberListType = actualType;				
 		bool memberListForceCast = false;
 		bool memberListForceCast = false;
@@ -8231,7 +8231,7 @@ String WinDebugger::DbgTypedValueToString(const DbgTypedValue& origTypedValue, c
 					return "";
 					return "";
 			}
 			}
 
 
-			retVal += "\n" + displayType->ToString(DbgLanguage_Unknown, true);						
+			retVal += "\n" + displayType->ToString(DbgLanguage_Unknown, true);
 			memberListType = innerType;
 			memberListType = innerType;
 		}
 		}
 		
 		
@@ -11026,6 +11026,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
 		FrameFlags_HasPendingDebugInfo = 2,
 		FrameFlags_HasPendingDebugInfo = 2,
 		FrameFlags_CanGetOldSource = 4,
 		FrameFlags_CanGetOldSource = 4,
 		FrameFlags_WasHotReplaced = 8,
 		FrameFlags_WasHotReplaced = 8,
+		FrameFlags_HadError = 0x10
 	};
 	};
 
 
 	AutoCrit autoCrit(mDebugManager->mCritSect);
 	AutoCrit autoCrit(mDebugManager->mCritSect);

+ 3 - 50
IDEHelper/WinDebugger.h

@@ -272,55 +272,6 @@ public:
 	}
 	}
 };
 };
 
 
-enum DbgTypeKindFlags
-{
-	DbgTypeKindFlag_None = 0,
-	DbgTypeKindFlag_Int = 1
-};
-
-struct DwFormatInfo
-{
-	int mCallStackIdx;
-	bool mHidePointers;
-	bool mIgnoreDerivedClassInfo;
-	bool mNoVisualizers;
-	bool mNoMembers;
-	bool mRawString;	
-	bool mNoEdit;
-	DbgTypeKindFlags mTypeKindFlags;
-	intptr mArrayLength;
-	intptr mOverrideCount;
-	intptr mMaxCount;
-	DwDisplayType mDisplayType;
-	DbgTypedValue mExplicitThis;
-	int mTotalSummaryLength;	
-	String mReferenceId;
-	String mSubjectExpr;
-	String mExpectedType;
-	String mNamespaceSearch;	
-	int mExpandItemDepth;
-	DbgLanguage mLanguage;
-
-	DwFormatInfo()
-	{
-		mCallStackIdx = -1;
-		mHidePointers = false;
-		mIgnoreDerivedClassInfo = false;
-		mRawString = false;		
-		mNoVisualizers = false;
-		mNoMembers = false;		
-		mNoEdit = false;
-		mTypeKindFlags = DbgTypeKindFlag_None;
-		mArrayLength = -1;
-		mOverrideCount = -1;
-		mMaxCount = -1;
-		mTotalSummaryLength = 0;
-		mDisplayType = DwDisplayType_NotSpecified;		
-		mExpandItemDepth = 0;
-		mLanguage = DbgLanguage_Unknown;
-	}
-};
-
 class DbgPendingExpr
 class DbgPendingExpr
 {
 {
 public:	
 public:	
@@ -411,6 +362,8 @@ public:
 	}
 	}
 };
 };
 
 
+struct DwFormatInfo;
+
 class WinDebugger : public Debugger
 class WinDebugger : public Debugger
 {
 {
 public:	
 public:	
@@ -542,7 +495,7 @@ public:
 	bool SetHotJump(DbgSubprogram* oldSubprogram, addr_target newTarget, int newTargetSize);
 	bool SetHotJump(DbgSubprogram* oldSubprogram, addr_target newTarget, int newTargetSize);
 	DbgSubprogram* TryFollowHotJump(DbgSubprogram* subprogram, addr_target addr);	
 	DbgSubprogram* TryFollowHotJump(DbgSubprogram* subprogram, addr_target addr);	
 
 
-	bool ParseFormatInfo(DbgModule* dbgModule, const StringImpl& formatInfoStr, DwFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExpr = NULL, String* errorString = NULL,  DbgTypedValue contextTypedValue = DbgTypedValue());
+	bool ParseFormatInfo(DbgModule* dbgModule, const StringImpl& formatInfoStr, DwFormatInfo* formatInfo, BfPassInstance* bfPassInstance, int* assignExprOffset, String* assignExpr = NULL, String* errorString = NULL, DbgTypedValue contextTypedValue = DbgTypedValue());
 	String MaybeQuoteFormatInfoParam(const StringImpl& str);
 	String MaybeQuoteFormatInfoParam(const StringImpl& str);
 	void DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors);
 	void DbgVisFailed(DebugVisualizerEntry* debugVis, const StringImpl& evalString, const StringImpl& errors);
 	DbgTypedValue EvaluateInContext(DbgCompileUnit* dbgCompileUnit, const DbgTypedValue& contextTypedValue, const StringImpl& subExpr, DwFormatInfo* formatInfo = NULL, String* outReferenceId = NULL, String* outErrors = NULL);
 	DbgTypedValue EvaluateInContext(DbgCompileUnit* dbgCompileUnit, const DbgTypedValue& contextTypedValue, const StringImpl& subExpr, DwFormatInfo* formatInfo = NULL, String* outReferenceId = NULL, String* outErrors = NULL);

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно