diff --git a/BeefLibs/corlib/src/Attribute.bf b/BeefLibs/corlib/src/Attribute.bf index 5f5d5495..34afeb47 100644 --- a/BeefLibs/corlib/src/Attribute.bf +++ b/BeefLibs/corlib/src/Attribute.bf @@ -274,10 +274,36 @@ namespace System } - [AttributeUsage(.Method | .Invocation)] + [AttributeUsage(.Method)] + public struct ComptimeAttribute : Attribute + { + public this() + { + + } + + public bool OnlyFromComptime + { + set + { + } + } + + public bool ConstEval + { + set + { + } + } + } + + [AttributeUsage(.Invocation)] public struct ConstEvalAttribute : Attribute { + public this() + { + } } [AttributeUsage(.Method /*2*/)] diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf index b34bb38e..edc842a6 100644 --- a/BeefLibs/corlib/src/Compiler.bf +++ b/BeefLibs/corlib/src/Compiler.bf @@ -1,7 +1,38 @@ +using System.Reflection; namespace System { + [AttributeUsage(.Method)] + struct OnCompileAttribute : Attribute + { + public enum Kind + { + None, + TypeInit, + TypeDone + } + + public this(Kind kind) + { + } + } + static class Compiler { + public struct MethodBuilder + { + void* mNative; + + public void Emit(String str) + { + Comptime_MethodBuilder_EmitStr(mNative, str); + } + + public void Emit(Type type) + { + + } + } + [LinkName("#CallerLineNum")] public static extern int CallerLineNum; @@ -32,8 +63,8 @@ namespace System [LinkName("#TimeLocal")] public static extern String TimeLocal; - [LinkName("#IsConstEval")] - public static extern bool IsConstEval; + [LinkName("#IsComptime")] + public static extern bool IsComptime; [LinkName("#IsBuilding")] public static extern bool IsBuilding; @@ -44,11 +75,39 @@ namespace System [LinkName("#CompileRev")] public static extern int32 CompileRev; - [ConstEval] + [Comptime] public static void Assert(bool cond) { if (!cond) Runtime.FatalError("Assert failed"); } + + static extern void* Comptime_MethodBuilder_EmitStr(void* native, StringView str); + static extern void* Comptime_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags); + static extern void Comptime_EmitDefinition(int32 typeId, StringView text); + + [Comptime(OnlyFromComptime=true)] + public static MethodBuilder CreateMethod(Type owner, StringView methodName, Type returnType, MethodFlags methodFlags) + { + MethodBuilder builder = .(); + builder.[Friend]mNative = Comptime_CreateMethod((.)owner.TypeId, methodName, returnType, methodFlags); + return builder; + } + + [Comptime(OnlyFromComptime=true)] + public static void EmitDefinition(Type owner, StringView text) + { + Comptime_EmitDefinition((.)owner.TypeId, text); + } + + interface IComptimeTypeApply + { + void ApplyToType(Type type); + } + + interface IComptimeMethodApply + { + void ApplyToMethod(Type type); + } } } diff --git a/BeefLibs/corlib/src/Globalization/CultureInfo.bf b/BeefLibs/corlib/src/Globalization/CultureInfo.bf index 9e6b9ca0..8b29b163 100644 --- a/BeefLibs/corlib/src/Globalization/CultureInfo.bf +++ b/BeefLibs/corlib/src/Globalization/CultureInfo.bf @@ -83,7 +83,7 @@ namespace System.Globalization { get { - if (Compiler.IsConstEval) + if (Compiler.IsComptime) return InitUserDefaultCulture(); if (tlCurrentCulture == null) tlCurrentCulture = CultureInfo.DefaultThreadCurrentCulture ?? CultureInfo.UserDefaultCulture; diff --git a/BeefLibs/corlib/src/Internal.bf b/BeefLibs/corlib/src/Internal.bf index 1fa1a978..815dd2b0 100644 --- a/BeefLibs/corlib/src/Internal.bf +++ b/BeefLibs/corlib/src/Internal.bf @@ -131,7 +131,7 @@ namespace System public static T* AllocRawArrayUnmarked(int size) { #if BF_ENABLE_REALTIME_LEAK_CHECK - if (Compiler.IsConstEval) + if (Compiler.IsComptime) return new T[size]*(?); // We don't want to use the default mark function because the GC will mark the entire array, // whereas we have a custom marking routine because we only want to mark up to mSize diff --git a/BeefLibs/corlib/src/NumberFormatter.bf b/BeefLibs/corlib/src/NumberFormatter.bf index 9b03a7e3..d4680f65 100644 --- a/BeefLibs/corlib/src/NumberFormatter.bf +++ b/BeefLibs/corlib/src/NumberFormatter.bf @@ -1235,7 +1235,7 @@ namespace System // _isCustomFormat, _specifierIsUpper, _specifier & _precision. this(CultureInfo cultureInfo) { - if (Compiler.IsConstEval) + if (Compiler.IsComptime) _cbuf = new char8[0]; else _cbuf = sEmtpyBuf; diff --git a/BeefLibs/corlib/src/Object.bf b/BeefLibs/corlib/src/Object.bf index a664e084..6ea3acfa 100644 --- a/BeefLibs/corlib/src/Object.bf +++ b/BeefLibs/corlib/src/Object.bf @@ -40,12 +40,12 @@ namespace System return false; } #endif - extern Type ConstEval_GetType(); + extern Type Comptime_GetType(); public Type GetType() { - if (Compiler.IsConstEval) - return ConstEval_GetType(); + if (Compiler.IsComptime) + return Comptime_GetType(); Type type; #if BF_ENABLE_OBJECT_DEBUG_FLAGS @@ -65,8 +65,8 @@ namespace System [NoShow] Type RawGetType() { - if (Compiler.IsConstEval) - return ConstEval_GetType(); + if (Compiler.IsComptime) + return Comptime_GetType(); Type type; #if BF_ENABLE_OBJECT_DEBUG_FLAGS diff --git a/BeefLibs/corlib/src/Reflection/TypeInstance.bf b/BeefLibs/corlib/src/Reflection/TypeInstance.bf index 7099a05e..2c0e16de 100644 --- a/BeefLibs/corlib/src/Reflection/TypeInstance.bf +++ b/BeefLibs/corlib/src/Reflection/TypeInstance.bf @@ -35,6 +35,11 @@ namespace System return .Ok(matched); } + public virtual Result GetMethod(int methodIdx) + { + return .Err(.NoResults); + } + public virtual Result CreateObject() { return .Err; @@ -61,6 +66,13 @@ namespace System.Reflection return MethodInfo.Enumerator(this, bindingFlags); } + public override Result GetMethod(int methodIdx) + { + if ((methodIdx < 0) || (methodIdx >= mMethodDataCount)) + return .Err(.NoResults); + return MethodInfo(this, &mMethodDataPtr[methodIdx]); + } + public override Result CreateObject() { if (mTypeClassVData == null) diff --git a/BeefLibs/corlib/src/Type.bf b/BeefLibs/corlib/src/Type.bf index db556780..66ef8052 100644 --- a/BeefLibs/corlib/src/Type.bf +++ b/BeefLibs/corlib/src/Type.bf @@ -471,19 +471,19 @@ namespace System return (int32)mTypeId; } - static extern Type ConstEval_GetTypeById(int32 typeId); + static extern Type Comptime_GetTypeById(int32 typeId); protected static Type GetType(TypeId typeId) { - if (Compiler.IsConstEval) - return ConstEval_GetTypeById((.)typeId); + if (Compiler.IsComptime) + return Comptime_GetTypeById((.)typeId); return sTypes[(int32)typeId]; } protected static Type GetType_(int32 typeId) { - if (Compiler.IsConstEval) - return ConstEval_GetTypeById(typeId); + if (Compiler.IsComptime) + return Comptime_GetTypeById(typeId); return sTypes[typeId]; } @@ -547,6 +547,11 @@ namespace System return .Err; } + public virtual Result GetField(int idx) + { + return .Err; + } + public virtual FieldInfo.Enumerator GetFields(BindingFlags bindingFlags = cDefaultLookup) { return FieldInfo.Enumerator(null, bindingFlags); @@ -912,6 +917,13 @@ namespace System.Reflection return .Err; } + public override Result GetField(int fieldIdx) + { + if ((fieldIdx < 0) || (fieldIdx >= mFieldDataCount)) + return .Err; + return FieldInfo(this, &mFieldDataPtr[fieldIdx]); + } + public override FieldInfo.Enumerator GetFields(BindingFlags bindingFlags = cDefaultLookup) { return FieldInfo.Enumerator(this, bindingFlags); diff --git a/IDE/src/CommandQueueManager.bf b/IDE/src/CommandQueueManager.bf index d083b799..213fee60 100644 --- a/IDE/src/CommandQueueManager.bf +++ b/IDE/src/CommandQueueManager.bf @@ -132,6 +132,11 @@ namespace IDE } + public virtual void RequestFastFinish() + { + + } + public void CancelBackground() { RequestCancelBackground(); diff --git a/IDE/src/Compiler/BfCompiler.bf b/IDE/src/Compiler/BfCompiler.bf index efa0547f..bceef606 100644 --- a/IDE/src/Compiler/BfCompiler.bf +++ b/IDE/src/Compiler/BfCompiler.bf @@ -61,6 +61,9 @@ namespace IDE.Compiler [CallingConvention(.Stdcall), CLink] static extern void BfCompiler_Cancel(void* bfCompiler); + [CallingConvention(.Stdcall), CLink] + static extern void BfCompiler_RequestFastFinish(void* bfCompiler); + [CallingConvention(.Stdcall), CLink] static extern void BfCompiler_ClearCompletionPercentage(void* bfCompiler); @@ -111,6 +114,12 @@ namespace IDE.Compiler [CallingConvention(.Stdcall), CLink] static extern void BfCompiler_ForceRebuild(void* bfCompiler); + [CallingConvention(.Stdcall), CLink] + static extern char8* BfCompiler_GetEmitSource(void* bfCompiler, char8* fileName); + + [CallingConvention(.Stdcall), CLink] + static extern int32 BfCompiler_GetEmitSourceVersion(void* bfCompiler, char8* fileName); + public enum HotTypeFlags { None = 0, @@ -267,6 +276,20 @@ namespace IDE.Compiler BfCompiler_ForceRebuild(mNativeBfCompiler); } + public bool GetEmitSource(StringView fileName, String outText) + { + char8* str = BfCompiler_GetEmitSource(mNativeBfCompiler, fileName.ToScopeCStr!()); + if (str == null) + return false; + outText.Append(str); + return true; + } + + public int32 GetEmitVersion(StringView fileName) + { + return BfCompiler_GetEmitSourceVersion(mNativeBfCompiler, fileName.ToScopeCStr!()); + } + public void QueueSetPassInstance(BfPassInstance passInstance) { SetPassInstanceCommand command = new SetPassInstanceCommand(); @@ -658,6 +681,15 @@ namespace IDE.Compiler } } + public override void RequestFastFinish() + { + if ([Friend]mThreadWorker.mThreadRunning || [Friend]mThreadWorkerHi.mThreadRunning) + { + if (mNativeBfCompiler != null) + BfCompiler_RequestFastFinish(mNativeBfCompiler); + } + } + public void ClearCompletionPercentage() { BfCompiler_ClearCompletionPercentage(mNativeBfCompiler); diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 22c3c9a2..64d5b94c 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -1407,6 +1407,23 @@ namespace IDE } } + BfCompiler compiler = null; + + if (fileName.Contains("$EmitR$")) + compiler = mBfResolveCompiler; + else if (fileName.Contains("$Emit$")) + compiler = mBfBuildCompiler; + + if (compiler != null) + { + if (compiler.GetEmitSource(fileName, outBuffer)) + { + if (onPreFilter != null) + onPreFilter(); + return .Ok; + } + } + return Utils.LoadTextFile(fileName, outBuffer, autoRetry, onPreFilter); } @@ -6145,6 +6162,16 @@ namespace IDE useFilePath = scope:: String(useFilePath); } + int32 emitRevision = -1; + // + { + int barPos = useFilePath.IndexOf('|'); + if (barPos != -1) + { + emitRevision = int32.Parse(useFilePath.Substring(barPos + 1)).Value; + useFilePath.RemoveToEnd(barPos); + } + } if ((useFilePath != null) && (!IDEUtils.FixFilePath(useFilePath))) return null; @@ -6219,6 +6246,8 @@ namespace IDE sourceViewPanelTab.mTabbedView.FinishTabAnim(); if (setFocus) sourceViewPanel.FocusEdit(); + + sourceViewPanel.CheckEmitRevision(); } } @@ -6236,6 +6265,7 @@ namespace IDE } else success = sourceViewPanel.Show(useFilePath, !mInitialized); + sourceViewPanel.mEmitRevision = emitRevision; if (!success) { diff --git a/IDE/src/ui/SourceViewPanel.bf b/IDE/src/ui/SourceViewPanel.bf index 2284cdc4..8e3ec28f 100644 --- a/IDE/src/ui/SourceViewPanel.bf +++ b/IDE/src/ui/SourceViewPanel.bf @@ -153,6 +153,17 @@ namespace IDE.ui } } + public class HoverResolveTask + { + public int32 mCursorPos; + public String mResult ~ delete _; + + public ~this() + { + NOP!(); + } + } + public class SourceFindTask { public WaitEvent mDoneEvent = new WaitEvent() ~ delete _; @@ -306,6 +317,7 @@ namespace IDE.ui public List mDeferredResolveResults = new .() ~ DeleteContainerAndItems!(_); public bool mTrackedTextElementViewListDirty; public String mFilePath ~ delete _; + public int32 mEmitRevision = -1; public bool mIsBinary; public String mAliasFilePath ~ delete _; #if IDE_C_SUPPORT @@ -321,6 +333,7 @@ namespace IDE.ui HTTPRequest mOldVerHTTPRequest ~ delete _; IDEApp.ExecutionInstance mOldVerLoadExecutionInstance ~ { if (_ != null) _.mAutoDelete = true; }; SourceFindTask mSourceFindTask ~ delete _; + HoverResolveTask mHoverResolveTask ~ delete _; bool mWantsFastClassify; bool mWantsFullClassify; // This triggers a classify bool mWantsFullRefresh; // If mWantsFullClassify is set, mWantsFullRefresh makes the whole thing refresh @@ -579,6 +592,8 @@ namespace IDE.ui if (ResolveCompiler.mThreadWorkerHi.mThreadRunning) { + ResolveCompiler.RequestFastFinish(); + //Debug.WriteLine("Deferred DoAutoComplete"); DeleteAndNullify!(mQueuedAutoComplete); mQueuedAutoComplete = new .(); @@ -968,6 +983,11 @@ namespace IDE.ui //return; }*/ + if (compiler.IsPerformingBackgroundOperation()) + { + compiler.RequestFastFinish(); + } + if (bfSystem == null) return false; @@ -1023,7 +1043,7 @@ namespace IDE.ui bool doBackground = (useResolveType == ResolveType.Classify) || (useResolveType == ResolveType.ClassifyFullRefresh); if (mAsyncAutocomplete) { - if ((useResolveType == .Autocomplete) || (useResolveType == .GetCurrentLocation) || (useResolveType == .GetSymbolInfo)) + if ((useResolveType == .Autocomplete) || (useResolveType == .GetCurrentLocation) || (useResolveType == .GetSymbolInfo) || (useResolveType == .GetResultString)) doBackground = true; } @@ -1111,7 +1131,9 @@ namespace IDE.ui bool isHi = (resolveType != .ClassifyFullRefresh) && (resolveType != .Classify); if (isHi) + { Debug.Assert(!bfCompiler.mThreadWorkerHi.mThreadRunning); + } else Debug.Assert(!bfCompiler.mThreadWorker.mThreadRunning); @@ -1209,7 +1231,10 @@ namespace IDE.ui var bfCompiler = BfResolveCompiler; //var bfSystem = IDEApp.sApp.mBfResolveSystem; //bfCompiler.StartTiming(); - DoClassify(ResolveType.Classify, resolveParams); + ResolveType resolveType = ResolveType.Classify; + if (resolveParams != null) + resolveType = resolveParams.mResolveType; + DoClassify(resolveType, resolveParams); //bfCompiler.StopTiming(); if (bfCompiler != null) bfCompiler.QueueDeferredResolveAll(); @@ -1600,6 +1625,11 @@ namespace IDE.ui } else if (resolveType == ResolveType.GetResultString) { + if ((mHoverResolveTask != null) && (mHoverResolveTask.mCursorPos == resolveParams.mOverrideCursorPos)) + { + mHoverResolveTask.mResult = new String(autocompleteInfo); + } + resolveParams.mResultString = new String(autocompleteInfo); } else if (resolveType == ResolveType.GetCurrentLocation) @@ -1664,7 +1694,7 @@ namespace IDE.ui var bfCompiler = BfResolveCompiler; //var compiler = ResolveCompiler; - bool isBackground = (resolveType == ResolveType.Classify) || (resolveType == ResolveType.ClassifyFullRefresh); + bool isBackground = (resolveType == ResolveType.Classify) || (resolveType == ResolveType.ClassifyFullRefresh) || (resolveType == .GetResultString); bool fullRefresh = resolveType == ResolveType.ClassifyFullRefresh; if (!isBackground) @@ -1775,15 +1805,18 @@ namespace IDE.ui int cursorPos = mEditWidget.mEditWidgetContent.CursorTextPos; /*if (resolveType == ResolveType.Autocomplete) cursorPos--;*/ - if ((resolveParams != null) && (resolveParams.mOverrideCursorPos != -1)) - cursorPos = resolveParams.mOverrideCursorPos; + if (resolveParams != null) + { + if (resolveParams.mOverrideCursorPos != -1) + cursorPos = resolveParams.mOverrideCursorPos; + } if ((resolveType == ResolveType.GetNavigationData) || (resolveType == ResolveType.GetFixits)) parser.SetAutocomplete(-1); else { bool setAutocomplete = ((!isBackground) && (resolveType != ResolveType.RenameSymbol)); - if ((resolveType == .Autocomplete) || (resolveType == .GetCurrentLocation) || (resolveType == .GetSymbolInfo)) + if ((resolveType == .Autocomplete) || (resolveType == .GetCurrentLocation) || (resolveType == .GetSymbolInfo) || (resolveType == .GetResultString)) setAutocomplete = true; if (setAutocomplete) parser.SetAutocomplete(Math.Max(0, cursorPos)); @@ -1866,7 +1899,9 @@ namespace IDE.ui resolveParams.mCancelled = true; if (resolveType == ResolveType.ClassifyFullRefresh) + { QueueFullRefresh(false); + } bfCompiler.QueueDeferredResolveAll(); } } @@ -4639,6 +4674,7 @@ namespace IDE.ui public void UpdateMouseover(bool mouseoverFired, bool mouseInbounds, int line, int lineChar) { + #unwarn CompilerBase compiler = ResolveCompiler; @@ -4839,7 +4875,7 @@ namespace IDE.ui } } - if (((mHoverWatch == null) && (mouseoverFired)) || (debugExpr == null) || (hasClangHoverErrorData)) + if (((mHoverWatch == null) && (mouseoverFired)) || (debugExpr == null) || (hasClangHoverErrorData) || (mHoverResolveTask?.mResult != null)) { float x; float y; @@ -4857,18 +4893,22 @@ namespace IDE.ui String origDebugExpr = null; + bool handlingHoverResolveTask = false; + if ((debugExpr != null) || (isOverMessage)) { - let resolveParams = scope ResolveParams(); - resolveParams.mOverrideCursorPos = (int32)textIdx; - if (!gApp.mDebugger.IsPaused()) - Classify(ResolveType.GetResultString, resolveParams); - if (!String.IsNullOrEmpty(resolveParams.mResultString)) + if (mHoverResolveTask != null) + { + if (mHoverResolveTask.mCursorPos != textIdx) + DeleteAndNullify!(mHoverResolveTask); + } + + if ((!String.IsNullOrEmpty(mHoverResolveTask?.mResult))) { origDebugExpr = scope:: String(); origDebugExpr.Set(debugExpr); - debugExpr.Set(resolveParams.mResultString); + debugExpr.Set(mHoverResolveTask.mResult); if (debugExpr.StartsWith(':')) { @@ -4889,6 +4929,12 @@ namespace IDE.ui } } + if (mHoverResolveTask?.mResult != null) + { + handlingHoverResolveTask = true; + DeleteAndNullify!(mHoverResolveTask); + } + if (!triedShow) { mHoverWatch.Show(this, x, y, debugExpr, debugExpr); @@ -4899,6 +4945,22 @@ namespace IDE.ui if ((!didShow) && ((debugExpr == null) || (isOverMessage) || (!mHoverWatch.Show(this, x, y, origDebugExpr ?? debugExpr, debugExpr)))) { + if (mHoverResolveTask == null) + { + if ((!handlingHoverResolveTask) && (!ResolveCompiler.mThreadWorkerHi.mThreadRunning)) + { + ResolveParams resolveParams = new .(); + resolveParams.mOverrideCursorPos = (int32)textIdx; + Classify(ResolveType.GetResultString, resolveParams); + //Debug.WriteLine($"GetResultString {resolveParams} {resolveParams.mInDeferredList}"); + if (!resolveParams.mInDeferredList) + delete resolveParams; + + mHoverResolveTask = new HoverResolveTask(); + mHoverResolveTask.mCursorPos = (int32)textIdx; + } + } + #if IDE_C_SUPPORT if ((mIsClang) && (textIdx != -1)) { @@ -4994,7 +5056,6 @@ namespace IDE.ui { mWantsFullRefresh = true; mRefireMouseOverAfterRefresh = true; - //Debug.WriteLine("Full refresh..."); } } @@ -5026,7 +5087,6 @@ namespace IDE.ui { if (mHoverWatch.mCloseDelay > 0) { - //Debug.WriteLine("mHoverWatch.mCloseCountdown = 20"); mHoverWatch.mCloseDelay--; mHoverWatch.mCloseCountdown = 20; } @@ -5042,7 +5102,6 @@ namespace IDE.ui } else { - //Debug.WriteLine("mCloseCountdown = 0"); mHoverWatch.mCloseCountdown = 0; } } @@ -5088,7 +5147,7 @@ namespace IDE.ui #if IDE_C_SUPPORT hasClangHoverErrorData = mClangHoverErrorData != null; #endif - if (((mouseoverFired) || (mHoverWatch != null) || (hasClangHoverErrorData)) && + if (((mouseoverFired) || (mHoverWatch != null) || (hasClangHoverErrorData) || (mHoverResolveTask?.mResult != null)) && (mousePos.x >= 0)) { int line; @@ -5105,455 +5164,6 @@ namespace IDE.ui } } - public void UpdateMouseover2() - { - if (mWidgetWindow == null) - return; - - if (CheckLeftMouseover()) - { - return; - } - - if ((DarkTooltipManager.sTooltip != null) && (DarkTooltipManager.sTooltip.mRelWidget == this)) - DarkTooltipManager.CloseTooltip(); - - if (!CheckAllowHoverWatch()) - { - return; - } - - /*if ((mHoverWatch != null) && (mHoverWatch.mCloseDelay > 0)) - return;*/ - var editWidgetContent = mEditWidget.Content; - Point mousePos; - bool mouseoverFired = DarkTooltipManager.CheckMouseover(editWidgetContent, 10, out mousePos); - -#unwarn - CompilerBase compiler = ResolveCompiler; - - bool hasClangHoverErrorData = false; - -#if IDE_C_SUPPORT - hasClangHoverErrorData = mClangHoverErrorData != null; -#endif - if (((mouseoverFired) || (mHoverWatch != null) || (hasClangHoverErrorData)) && - (mousePos.x >= 0)) - { - int line; - int lineChar; - String debugExpr = null; - - BfSystem bfSystem = IDEApp.sApp.mBfResolveSystem; - BfPassInstance passInstance = null; - BfParser parser = null; - int textIdx = -1; - - bool isOverMessage = false; - float overflowX; - if (editWidgetContent.GetLineCharAtCoord(mousePos.x, mousePos.y, out line, out lineChar, out overflowX)) - { - textIdx = editWidgetContent.GetTextIdx(line, lineChar); - - int startIdx = editWidgetContent.GetTextIdx(line, lineChar); - - uint8 checkFlags = (uint8)SourceElementFlags.Error; - if (!IDEApp.sApp.mDebugger.mIsRunning) - { - // Prioritize debug info over warning when we are debugging - checkFlags |= (uint8)SourceElementFlags.Warning; - } - if ((editWidgetContent.mData.mText[startIdx].mDisplayFlags & checkFlags) != 0) - isOverMessage = true; - - bool doSimpleMouseover = false; - - if ((editWidgetContent.mSelection != null) && - (textIdx >= editWidgetContent.mSelection.Value.MinPos) && - (textIdx < editWidgetContent.mSelection.Value.MaxPos)) - { - debugExpr = scope:: String(); - editWidgetContent.GetSelectionText(debugExpr); - } - else if (mIsBeefSource) - { - if (bfSystem != null) - { - parser = bfSystem.CreateEmptyParser(null); - - var text = scope String(); - mEditWidget.GetText(text); - parser.SetSource(text, mFilePath); - parser.SetAutocomplete(textIdx); - passInstance = bfSystem.CreatePassInstance("Mouseover"); - parser.SetCompleteParse(); - parser.Parse(passInstance, !mIsBeefSource); - parser.Reduce(passInstance); - debugExpr = scope:: String(); - if (parser.GetDebugExpressionAt(textIdx, debugExpr)) - { - if (debugExpr.StartsWith("`")) - debugExpr[0] = ':'; - else if (debugExpr.StartsWith(":")) - debugExpr = null; - } - } - } - else if (mIsClang) - doSimpleMouseover = true; - - if (doSimpleMouseover) - SimpleMouseover: do - { - int endIdx = startIdx; - String sb = scope:: String(); - bool isInvalid = false; - bool prevWasSpace = false; - - if (editWidgetContent.mData.mText[startIdx].mChar.IsWhiteSpace) - break; - - startIdx--; - while (startIdx > 0) - { - var char8Data = editWidgetContent.mData.mText[startIdx]; - if (char8Data.mDisplayTypeId == (uint8)SourceElementType.Comment) - { - if (startIdx == endIdx - 1) - { - // Inside comment - isInvalid = true; - break; - } - } - else - { - char8 c = (char8)char8Data.mChar; - if ((c == ' ') || (c == '\t')) - { - // Ignore - prevWasSpace = true; - } - else if (c == '\n') - { - break; - } - else - { - if (c == '>') - { - // Is this "->"? - if ((startIdx > 1) && ((char8)editWidgetContent.mData.mText[startIdx - 1].mChar == '-')) - { - sb.Insert(0, "->"); - startIdx--; - } - else - break; - } - else if (c == ':') - { - // Is this "::"? - if ((startIdx > 1) && ((char8)editWidgetContent.mData.mText[startIdx - 1].mChar == ':')) - { - sb.Insert(0, "::"); - startIdx--; - } - else - break; - } - else if (c == '.') - sb.Insert(0, c); - else if ((c == '_') || (c.IsLetterOrDigit)) - { - if (prevWasSpace) - break; - sb.Insert(0, c); - } - else - break; - - prevWasSpace = false; - } - } - startIdx--; - } - - prevWasSpace = false; - while ((endIdx < editWidgetContent.mData.mTextLength) && (endIdx > startIdx)) - { - var char8Data = editWidgetContent.mData.mText[endIdx]; - if (char8Data.mDisplayTypeId == (uint8)SourceElementType.Comment) - { - // Ignore - prevWasSpace = true; - } - else - { - char8 c = (char8)char8Data.mChar; - if ((c == ' ') || (c == '\t')) - { - // Ignore - prevWasSpace = true; - } - else if ((c == '_') || (c.IsLetterOrDigit)) - { - if (prevWasSpace) - break; - - sb.Append(c); - } - else - break; - - prevWasSpace = false; - } - endIdx++; - } - - if (!isInvalid) - debugExpr = sb; - } - } - - bool triedShow = false; - - if (mHoverWatch != null) - { - if (debugExpr != null) - { - if (mHoverWatch.mEvalString != debugExpr) - { - mHoverWatch.Close(); - mHoverWatch = null; - } - else - triedShow = true; - } - } - - if (((mHoverWatch == null) && (mouseoverFired)) || (debugExpr == null) || (hasClangHoverErrorData)) - { - float x; - float y; - editWidgetContent.GetTextCoordAtLineChar(line, lineChar, out x, out y); - - bool hasHoverWatchOpen = (mHoverWatch != null) && (mHoverWatch.mListView != null); - if (mHoverWatch == null) - mHoverWatch = new HoverWatch(); - - if (debugExpr != null) - triedShow = true; - - bool didShow = false; - //if ((debugExpr == "var") || (debugExpr == "let")) - - String origDebugExpr = null; - - if ((debugExpr != null) || (isOverMessage)) - { - let resolveParams = scope ResolveParams(); - resolveParams.mOverrideCursorPos = (int32)textIdx; - Classify(ResolveType.GetResultString, resolveParams); - if (!String.IsNullOrEmpty(resolveParams.mResultString)) - { - origDebugExpr = scope:: String(); - origDebugExpr.Set(debugExpr); - - debugExpr.Set(resolveParams.mResultString); - } - - if (!triedShow) - { - mHoverWatch.Show(this, x, y, debugExpr, debugExpr); - triedShow = true; - } - } - - if ((!didShow) && - ((debugExpr == null) || (isOverMessage) || (!mHoverWatch.Show(this, x, y, origDebugExpr ?? debugExpr, debugExpr)))) - { -#if IDE_C_SUPPORT - if ((mIsClang) && (textIdx != -1)) - { - bool hasErrorFlag = (mEditWidget.Content.mData.mText[textIdx].mDisplayFlags != 0); - - if (hasErrorFlag) - { - if (!compiler.IsPerformingBackgroundOperation()) - { - bool hadValidError = false; - if (mClangHoverErrorData != null) - { - String[] stringParts = String.StackSplit!(mClangHoverErrorData, '\t'); - int startIdx = (int32)int32.Parse(stringParts[0]); - int endIdx = (int32)int32.Parse(stringParts[1]); - if ((textIdx >= startIdx) && (textIdx < endIdx)) - { - hadValidError = true; - triedShow = true; - mHoverWatch.Show(this, x, y, scope String(":", stringParts[2])); - if (debugExpr != null) - mHoverWatch.mEvalString.Set(debugExpr); // Set to old debugStr for comparison - else - mHoverWatch.mEvalString.Clear(); - } - - } - - if (!hadValidError) - { - mErrorLookupTextIdx = (int32)textIdx; - Classify(ResolveType.Classify); - triedShow = false; - } - } - } - else - { - triedShow = false; - delete mClangHoverErrorData; - mClangHoverErrorData = null; - } - } -#endif - - if ((parser != null) && (mIsBeefSource)) - ErrorScope: - { - //TODO: Needed this? - /*var resolvePassData = parser.CreateResolvePassData(); - defer (scope) delete resolvePassData; - bfSystem.NotifyWillRequestLock(1); - bfSystem.Lock(1); - parser.BuildDefs(passInstance, resolvePassData, false); - BfResolveCompiler.ClassifySource(passInstance, parser, resolvePassData, null);*/ - - BfPassInstance.BfError bestError = scope BfPassInstance.BfError(); - - for (var bfError in mErrorList) - { - if (bfError.mIsWhileSpecializing) - continue; - - if ((textIdx >= bfError.mSrcStart) && (textIdx < bfError.mSrcEnd)) - { - if ((bestError.mError == null) || (bestError.mIsWarning) || (bestError.mIsPersistent)) - bestError = bfError; - } - } - - String showMouseoverString = null; - if (bestError.mError != null) - { - showMouseoverString = scope:: String(":", bestError.mError); - - if (bestError.mMoreInfo != null) - { - for (var moreInfo in bestError.mMoreInfo) - { - showMouseoverString.AppendF("\n@{0}\t{1}\t{2}", moreInfo.mFilePath, moreInfo.mSrcStart, moreInfo.mError); - } - } - } - else - { - var flags = (SourceElementFlags)editWidgetContent.mData.mText[textIdx].mDisplayFlags; - if ((flags.HasFlag(.Error)) || (flags.HasFlag(.Warning))) - { - mWantsFullRefresh = true; - mRefireMouseOverAfterRefresh = true; - //Debug.WriteLine("Full refresh..."); - } - } - - if (showMouseoverString != null) - { - triedShow = true; - mHoverWatch.Show(this, x, y, showMouseoverString, showMouseoverString); - if (debugExpr != null) - mHoverWatch.mEvalString.Set(debugExpr); // Set to old debugStr for comparison - } - else - triedShow = false; - } - } - if (!hasHoverWatchOpen) - mHoverWatch.mOpenMousePos = DarkTooltipManager.sLastRelMousePos; - } - - // Not used? - if ((mHoverWatch != null) && (mHoverWatch.mTextPanel != this)) - { - mHoverWatch.Close(); - mHoverWatch = null; - } - - if (mHoverWatch != null) - { - if ((!triedShow) && (!IDEApp.sApp.HasPopupMenus())) - { - if (mHoverWatch.mCloseDelay > 0) - { - //Debug.WriteLine("mHoverWatch.mCloseCountdown = 20"); - mHoverWatch.mCloseDelay--; - mHoverWatch.mCloseCountdown = 20; - } - else - { - mHoverWatch.Close(); - mHoverWatch = null; -#if IDE_C_SUPPORT - delete mClangHoverErrorData; - mClangHoverErrorData = null; -#endif - } - } - else - { - //Debug.WriteLine("mCloseCountdown = 0"); - mHoverWatch.mCloseCountdown = 0; - } - } - - if (passInstance != null) - delete passInstance; - if (parser != null) - { - delete parser; - mWantsParserCleanup = true; - } - } - -#if IDE_C_SUPPORT - delete mClangHoverErrorData; - mClangHoverErrorData = null; -#endif - - /*if ((mIsClang) && (!compiler.IsPerformingBackgroundOperation())) - { - bool hadValidError = false; - if (mClangHoverErrorData != null) - { - int textIdx = -1; - int line; - int lineChar; - if (editWidgetContent.GetLineCharAtCoord(mousePos.x, mousePos.y, out line, out lineChar)) - textIdx = editWidgetContent.GetTextIdx(line, lineChar); - - string[] stringParts = mClangHoverErrorData.Split('\t'); - int startIdx = int.Parse(stringParts[0]); - int endIdx = int.Parse(stringParts[1]); - if ((textIdx >= startIdx) && (textIdx < endIdx)) - { - hadValidError = true; - mHoverWatch.Show(this, x, y, ":" + stringParts[2]); - mHoverWatch.mEvalString.Set(debugExpr); // Set to old debugStr for comparison - } - } - }*/ - } - void DuplicateEditState(out EditWidgetContent.CharData[] char8Data, out IdSpan char8IdData) { var srcCharData = mEditWidget.Content.mData.mText; @@ -5840,6 +5450,13 @@ namespace IDE.ui checkIdx++; continue; } + + if (!resolveResult.mWaitEvent.WaitFor(0)) + { + if (waitTime != 0) + ResolveCompiler.RequestFastFinish(); + } + if (!resolveResult.mWaitEvent.WaitFor(waitTime)) { checkIdx++; @@ -5847,6 +5464,9 @@ namespace IDE.ui } mDeferredResolveResults.RemoveAt(checkIdx); } + + //Debug.WriteLine($"HandleResolveResult {resolveResult}"); + HandleResolveResult(resolveResult.mResolveType, resolveResult.mAutocompleteInfo, resolveResult); //Debug.WriteLine("ProcessDeferredResolveResults finished {0}", resolveResult.mResolveType); @@ -5887,12 +5507,15 @@ namespace IDE.ui { MarkDirty(); if (resolveResult.mPassInstance.HadSignatureChanges()) + { mWantsFullRefresh = true; + } } } /*if (checkIt) Debug.Assert(data.mDisplayTypeId == 8);*/ + //Debug.WriteLine($"Deleting {resolveResult}"); delete resolveResult; } } @@ -6368,6 +5991,9 @@ namespace IDE.ui mLockFlashPct = 0; MarkDirty(); } + + if ((mEmitRevision >= 0) && ((mUpdateCnt % 30) == 0)) + CheckEmitRevision(); } void InjectErrors(BfPassInstance processingPassInstance, EditWidgetContent.CharData[] processResolveCharData, IdSpan processCharIdSpan, bool keepPersistentErrors) @@ -6396,10 +6022,14 @@ namespace IDE.ui int32 errorCount = processingPassInstance.GetErrorCount(); mErrorList.Capacity = mErrorList.Count + errorCount; + bool hadNonDeferredErrors = false; + for (int32 errorIdx = 0; errorIdx < errorCount; errorIdx++) { BfPassInstance.BfError bfError = new BfPassInstance.BfError(); processingPassInstance.GetErrorData(errorIdx, bfError); + if (!bfError.mIsDeferred) + hadNonDeferredErrors = true; for (int32 moreInfoIdx < bfError.mMoreInfoCount) { @@ -6425,6 +6055,9 @@ namespace IDE.ui if (bfError.mIsWhileSpecializing) continue; + if ((bfError.mIsDeferred) && (hadNonDeferredErrors)) + continue; + if (bfError.mIsPersistent) { if (bfError.mIdSpan.IsEmpty) @@ -6823,5 +6456,27 @@ namespace IDE.ui return false; } + + public void CheckEmitRevision() + { + if (mEmitRevision != -1) + { + BfCompiler compiler = null; + if (mFilePath.Contains("$EmitR$")) + compiler = gApp.mBfResolveCompiler; + else if (mFilePath.Contains("$Emit$")) + compiler = gApp.mBfBuildCompiler; + + if (compiler != null) + { + int32 version = compiler.GetEmitVersion(mFilePath); + if ((version >= 0) && (version != mEmitRevision)) + { + mEmitRevision = version; + Reload(); + } + } + } + } } } diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index 3190a2e8..f4284bf4 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -880,6 +880,21 @@ void BeIRCodeGen::Read(BeValue*& beValue) beValue = mBeModule->CreateUndefValue(type); return; } + else if (constType == BfConstType_TypeOf) + { + CMD_PARAM(BeType*, type); + beValue = mReflectDataMap[type]; + BF_ASSERT(beValue != NULL); + return; + } + else if (constType == BfConstType_TypeOf_WithData) + { + CMD_PARAM(BeType*, type); + CMD_PARAM(BeValue*, value); + mReflectDataMap[type] = value; + beValue = value; + return; + } bool isSigned = false; BeType* llvmConstType = GetBeType(typeCode, isSigned); @@ -1969,6 +1984,13 @@ void BeIRCodeGen::HandleNextCmd() //SetResult(curId, globalVariable); } break; + case BfIRCmd_SetReflectTypeData: + { + CMD_PARAM(BeType*, type); + CMD_PARAM(BeValue*, value); + mReflectDataMap[type] = value; + } + break; case BfIRCmd_CreateBlock: { CMD_PARAM(String, name); diff --git a/IDEHelper/Backend/BeIRCodeGen.h b/IDEHelper/Backend/BeIRCodeGen.h index d3ae1e25..debf8ee6 100644 --- a/IDEHelper/Backend/BeIRCodeGen.h +++ b/IDEHelper/Backend/BeIRCodeGen.h @@ -89,6 +89,7 @@ public: Dictionary mTypes; Dictionary mOnDemandTypeMap; + Dictionary mReflectDataMap; Array mConfigConsts; public: diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index 2511fc3d..d4032ad2 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -946,6 +946,14 @@ BfParser* BfAstNode::GetParser() return sourceData->ToParser(); } +bool BfAstNode::IsEmitted() +{ + auto parser = GetParser(); + if (parser == NULL) + return false; + return parser->mIsEmitted; +} + bool BfAstNode::IsFromParser(BfParser* parser) { if (parser == NULL) diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index 7ef1426a..57d590c0 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -1088,6 +1088,7 @@ public: BfSourceData* GetSourceData(); BfParserData* GetParserData(); BfParser* GetParser(); + bool IsEmitted(); bool IsFromParser(BfParser* parser); String ToString(); StringView ToStringView(); diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 7f1c74a6..8a120b13 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -346,6 +346,8 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) memset(&mStats, 0, sizeof(mStats)); mCompletionPct = 0; mCanceling = false; + mFastFinish = false; + mHasQueuedTypeRebuilds = false; mIsResolveOnly = isResolveOnly; mResolvePassData = NULL; mPassInstance = NULL; @@ -397,6 +399,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mActionTypeDef = NULL; mEnumTypeDef = NULL; mFriendAttributeTypeDef = NULL; + mComptimeAttributeTypeDef = NULL; mConstEvalAttributeTypeDef = NULL; mNoExtensionAttributeTypeDef = NULL; mCheckedAttributeTypeDef = NULL; @@ -408,11 +411,14 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mGenericIRefEnumeratorTypeDef = NULL; mInlineAttributeTypeDef = NULL; mThreadTypeDef = NULL; - mInternalTypeDef = NULL; + mInternalTypeDef = NULL; + mCompilerTypeDef = NULL; mDiagnosticsDebugTypeDef = NULL; mIDisposableTypeDef = NULL; mIPrintableTypeDef = NULL; mIHashableTypeDef = NULL; + mIComptimeTypeApply = NULL; + mIComptimeMethodApply = NULL; mLinkNameAttributeTypeDef = NULL; mCallingConventionAttributeTypeDef = NULL; mMethodRefTypeDef = NULL; @@ -447,6 +453,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mWarnAttributeTypeDef = NULL; mIgnoreErrorsAttributeTypeDef = NULL; mReflectAttributeTypeDef = NULL; + mOnCompileAttributeTypeDef = NULL; mLastAutocompleteModule = NULL; @@ -3919,6 +3926,8 @@ void BfCompiler::ProcessAutocompleteTempType() return; } + mFastFinish = false; + SetAndRestoreValue prevMethodState(module->mCurMethodState, NULL); SetAndRestoreValue prevTypeInstance(module->mCurTypeInstance, NULL); SetAndRestoreValue prevMethodInstance(module->mCurMethodInstance, NULL); @@ -6522,13 +6531,15 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) if (IsHotCompile()) - { + { mContext->EnsureHotMangledVirtualMethodNames(); } mOutputDirectory = outputDirectory; mSystem->StartYieldSection(); + mFastFinish = false; + mHasQueuedTypeRebuilds = false; mCanceling = false; mSystem->CheckLockYield(); @@ -6611,6 +6622,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mActionTypeDef = _GetRequiredType("System.Action"); mEnumTypeDef = _GetRequiredType("System.Enum"); mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute"); + mComptimeAttributeTypeDef = _GetRequiredType("System.ComptimeAttribute"); mConstEvalAttributeTypeDef = _GetRequiredType("System.ConstEvalAttribute"); mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute"); mCheckedAttributeTypeDef = _GetRequiredType("System.CheckedAttribute"); @@ -6624,10 +6636,13 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mInlineAttributeTypeDef = _GetRequiredType("System.InlineAttribute"); mThreadTypeDef = _GetRequiredType("System.Threading.Thread"); mInternalTypeDef = _GetRequiredType("System.Internal"); + mCompilerTypeDef = _GetRequiredType("System.Compiler"); mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug"); mIDisposableTypeDef = _GetRequiredType("System.IDisposable"); mIPrintableTypeDef = _GetRequiredType("System.IPrintable"); mIHashableTypeDef = _GetRequiredType("System.IHashable"); + mIComptimeTypeApply = _GetRequiredType("System.IComptimeTypeApply"); + mIComptimeMethodApply = _GetRequiredType("System.IComptimeMethodApply"); mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute"); mCallingConventionAttributeTypeDef = _GetRequiredType("System.CallingConventionAttribute"); mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1); @@ -6662,6 +6677,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute"); mIgnoreErrorsAttributeTypeDef = _GetRequiredType("System.IgnoreErrorsAttribute"); mReflectAttributeTypeDef = _GetRequiredType("System.ReflectAttribute"); + mOnCompileAttributeTypeDef = _GetRequiredType("System.OnCompileAttribute"); for (int i = 0; i < BfTypeCode_Length; i++) mContext->mPrimitiveStructTypes[i] = NULL; @@ -7213,6 +7229,8 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) } mCodeGen.ProcessErrors(mPassInstance, mCanceling); + mCEMachine->CompileDone(); + // This has to happen after codegen because we may delete modules that are referenced in codegen mContext->Cleanup(); if ((!IsHotCompile()) && (!mIsResolveOnly) && (!mCanceling)) @@ -7346,7 +7364,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mContext->ValidateDependencies(); - return !didCancel; + return !didCancel && !mHasQueuedTypeRebuilds; } bool BfCompiler::Compile(const StringImpl& outputDirectory) @@ -7380,11 +7398,19 @@ void BfCompiler::ClearResults() void BfCompiler::Cancel() { mCanceling = true; + mFastFinish = true; mHadCancel = true; BfLogSysM("BfCompiler::Cancel\n"); BpEvent("BfCompiler::Cancel", ""); } +void BfCompiler::RequestFastFinish() +{ + mFastFinish = true; + BfLogSysM("BfCompiler::RequestFastFinish\n"); + BpEvent("BfCompiler::RequestFastFinish", ""); +} + //#define WANT_COMPILE_LOG void BfCompiler::CompileLog(const char* fmt ...) @@ -8538,6 +8564,38 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName) return result; } +int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer) +{ + int lastDollarPos = (int)fileName.LastIndexOf('$'); + if (lastDollarPos == -1) + return -1; + int dotPos = (int)fileName.LastIndexOf('.'); + if (dotPos == -1) + return -1; + + String typeIdStr = fileName.Substring(lastDollarPos + 1, dotPos - lastDollarPos - 1); + + int revisionId = (int)atoi(typeIdStr.c_str()); + int typeId = (int)atoi(typeIdStr.c_str()); + if ((typeId <= 0) || (typeId >= mContext->mTypes.mSize)) + return -1; + + auto type = mContext->mTypes[typeId]; + if (type == NULL) + return -1; + auto typeInst = type->ToTypeInstance(); + if (typeInst == NULL) + return -1; + + auto typeDef = typeInst->mTypeDef; + + if (typeDef->mEmitParser == NULL) + return -1; + if (outBuffer != NULL) + outBuffer->Append(typeDef->mEmitParser->mSrc, typeDef->mEmitParser->mSrcLength); + return typeInst->mRevision; +} + ////////////////////////////////////////////////////////////////////////// PerfManager* BfGetPerfManager(BfParser* bfParser); @@ -8738,6 +8796,11 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_Cancel(BfCompiler* bfCompiler) bfCompiler->Cancel(); } +BF_EXPORT void BF_CALLTYPE BfCompiler_RequestFastFinish(BfCompiler* bfCompiler) +{ + bfCompiler->RequestFastFinish(); +} + BF_EXPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(BfCompiler* bfCompiler) { bfCompiler->ClearBuildCache(); @@ -9251,3 +9314,17 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_ForceRebuild(BfCompiler* bfCompiler) bfCompiler->mOptions.mForceRebuildIdx++; } +BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetEmitSource(BfCompiler* bfCompiler, char* fileName) +{ + String& outString = *gTLStrReturn.Get(); + outString.clear(); + bfCompiler->GetEmitSource(fileName, &outString); + if (outString.IsEmpty()) + return NULL; + return outString.c_str(); +} + +BF_EXPORT int32 BF_CALLTYPE BfCompiler_GetEmitSourceVersion(BfCompiler* bfCompiler, char* fileName) +{ + return bfCompiler->GetEmitSource(fileName, NULL); +} diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index ccec118e..6864590a 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -323,6 +323,8 @@ public: BfCodeGen mCodeGen; String mOutputDirectory; bool mCanceling; + bool mFastFinish; + bool mHasQueuedTypeRebuilds; // Infers we had a fast finish that requires a type rebuild bool mHadCancel; bool mWantsDeferMethodDecls; bool mInInvalidState; @@ -362,10 +364,13 @@ public: BfTypeDef* mThreadTypeDef; BfTypeDef* mInternalTypeDef; + BfTypeDef* mCompilerTypeDef; BfTypeDef* mDiagnosticsDebugTypeDef; BfTypeDef* mIDisposableTypeDef; BfTypeDef* mIPrintableTypeDef; BfTypeDef* mIHashableTypeDef; + BfTypeDef* mIComptimeTypeApply; + BfTypeDef* mIComptimeMethodApply; BfTypeDef* mMethodRefTypeDef; BfTypeDef* mNullableTypeDef; @@ -403,6 +408,7 @@ public: BfTypeDef* mDisableChecksAttributeTypeDef; BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef; BfTypeDef* mFriendAttributeTypeDef; + BfTypeDef* mComptimeAttributeTypeDef; BfTypeDef* mConstEvalAttributeTypeDef; BfTypeDef* mNoExtensionAttributeTypeDef; BfTypeDef* mCheckedAttributeTypeDef; @@ -417,6 +423,7 @@ public: BfTypeDef* mWarnAttributeTypeDef; BfTypeDef* mIgnoreErrorsAttributeTypeDef; BfTypeDef* mReflectAttributeTypeDef; + BfTypeDef* mOnCompileAttributeTypeDef; int mCurTypeId; int mTypeInitCount; @@ -493,9 +500,11 @@ public: void ProcessAutocompleteTempType(); void GetSymbolReferences(); void Cancel(); + void RequestFastFinish(); String GetTypeDefList(); String GetTypeDefMatches(const StringImpl& searchSrc); String GetTypeDefInfo(const StringImpl& typeName); + int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer); void CompileLog(const char* fmt ...); void ReportMemory(MemReporter* memReporter); diff --git a/IDEHelper/Compiler/BfConstResolver.cpp b/IDEHelper/Compiler/BfConstResolver.cpp index 82a506d1..dc761d42 100644 --- a/IDEHelper/Compiler/BfConstResolver.cpp +++ b/IDEHelper/Compiler/BfConstResolver.cpp @@ -36,7 +36,7 @@ BfConstResolver::BfConstResolver(BfModule* bfModule) : BfExprEvaluator(bfModule) BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfConstResolveFlags flags) { - mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_ConstEval); + mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime); // Handle the 'int[?] val = .(1, 2, 3)' case if ((flags & BfConstResolveFlag_ArrayInitSize) != 0) diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 667099b8..ae4fc0c2 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -737,7 +737,7 @@ void BfContext::HandleChangedTypeDef(BfTypeDef* typeDef, bool isAutoCompleteTemp } } - if (!typeDef->mIsPartial) + if ((!typeDef->mIsPartial) && (!isAutoCompleteTempType)) { if ((typeDef->mDefState == BfTypeDef::DefState_New) || (typeDef->mDefState == BfTypeDef::DefState_Deleted) || @@ -1025,6 +1025,11 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild typeInst->mHasDeclError = false; delete typeInst->mTypeInfoEx; typeInst->mTypeInfoEx = NULL; + + typeInst->mTypeDef->ClearEmitted(); + for (auto localMethod : typeInst->mOwnedLocalMethods) + delete localMethod; + typeInst->mOwnedLocalMethods.Clear(); if (typeInst->IsGenericTypeInstance()) { @@ -2851,7 +2856,24 @@ void BfContext::Cleanup() for (auto localMethod : mLocalMethodGraveyard) { - if ((localMethod->mMethodInstanceGroup != NULL) && (localMethod->mMethodInstanceGroup->mRefCount > 0)) + bool inCEMachine = false; + if (localMethod->mMethodInstanceGroup != NULL) + { + if ((localMethod->mMethodInstanceGroup->mDefault != NULL) && (localMethod->mMethodInstanceGroup->mDefault->mInCEMachine)) + inCEMachine = true; + if (localMethod->mMethodInstanceGroup->mMethodSpecializationMap != NULL) + { + for (auto& kv : *localMethod->mMethodInstanceGroup->mMethodSpecializationMap) + if (kv.mValue->mInCEMachine) + inCEMachine = true; + } + } + + if (inCEMachine) + { + localMethod->mMethodInstanceGroup->mOwner->mOwnedLocalMethods.Add(localMethod); + } + else if ((localMethod->mMethodInstanceGroup != NULL) && (localMethod->mMethodInstanceGroup->mRefCount > 0)) { localMethod->Dispose(); survivingLocalMethods.push_back(localMethod); diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index 3dd96024..39bc1e3c 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -861,8 +861,10 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef methodDef->mIsNoReturn = true; else if (typeRefName == "SkipCall") methodDef->mIsSkipCall = true; - else if (typeRefName == "ConstEval") - methodDef->mIsConstEval = true; + else if (typeRefName == "Comptime") + { + methodDef->mHasComptime = true; + } else if (typeRefName == "NoShow") methodDef->mIsNoShow = true; else if (typeRefName == "NoDiscard") @@ -883,6 +885,10 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfMethodDef methodDef->mCommutableKind = BfCommutableKind_Forward; } } + else if (typeRefName == "OnCompile") + { + mCurTypeDef->mHasCEOnCompile = true; + } } attributes = attributes->mNextAttribute; @@ -900,7 +906,7 @@ void BfDefBuilder::ParseAttributes(BfAttributeDirective* attributes, BfTypeDef* if (typeRefName == "AlwaysInclude") typeDef->mIsAlwaysInclude = true; else if (typeRefName == "NoDiscard") - typeDef->mIsNoDiscard = true; + typeDef->mIsNoDiscard = true; } attributes = attributes->mNextAttribute; @@ -927,7 +933,8 @@ void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration) Fail("Const properties are not allowed", propertyDeclaration->mConstSpecifier); } - HashNode(*mSignatureHashCtx, propertyDeclaration, propertyDeclaration->mDefinitionBlock); + if (mSignatureHashCtx != NULL) + HashNode(*mSignatureHashCtx, propertyDeclaration, propertyDeclaration->mDefinitionBlock); BfPropertyDef* propertyDef = new BfPropertyDef(); mCurTypeDef->mProperties.push_back(propertyDef); @@ -956,7 +963,8 @@ void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration) if (propertyDeclaration->mDefinitionBlock == NULL) // To differentiate between autocompleting partial property if it transitions to a field { //mCurTypeDef->mSignatureHash = HashString("nullprop", mCurTypeDef->mSignatureHash); - mSignatureHashCtx->MixinStr("nullprop"); + if (mSignatureHashCtx != NULL) + mSignatureHashCtx->MixinStr("nullprop"); } auto indexerDeclaration = BfNodeDynCast(propertyDeclaration); @@ -985,10 +993,13 @@ void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration) for (auto methodDeclaration : propertyDeclaration->mMethods) { - HashNode(*mSignatureHashCtx, methodDeclaration->mAttributes); - HashNode(*mSignatureHashCtx, methodDeclaration->mProtectionSpecifier); - HashNode(*mSignatureHashCtx, methodDeclaration->mNameNode); - HashNode(*mSignatureHashCtx, methodDeclaration->mMutSpecifier); + if (mSignatureHashCtx != NULL) + { + HashNode(*mSignatureHashCtx, methodDeclaration->mAttributes); + HashNode(*mSignatureHashCtx, methodDeclaration->mProtectionSpecifier); + HashNode(*mSignatureHashCtx, methodDeclaration->mNameNode); + HashNode(*mSignatureHashCtx, methodDeclaration->mMutSpecifier); + } if (!wantsBody) continue; @@ -1096,7 +1107,7 @@ void BfDefBuilder::Visit(BfPropertyDeclaration* propertyDeclaration) } void BfDefBuilder::Visit(BfFieldDeclaration* fieldDeclaration) -{ +{ mSystem->CheckLockYield(); int endingAdd = 1;// Add '1' for autocompletion of 'new' initializer @@ -1141,7 +1152,8 @@ void BfDefBuilder::Visit(BfFieldDeclaration* fieldDeclaration) fieldDef->mInitializer = fieldDeclaration->mInitializer; //mCurTypeDef->mSignatureHash = HashNode(fieldDeclaration, mCurTypeDef->mSignatureHash); - HashNode(*mSignatureHashCtx, fieldDeclaration); + if (mSignatureHashCtx != NULL) + HashNode(*mSignatureHashCtx, fieldDeclaration); } void BfDefBuilder::Visit(BfEnumCaseDeclaration* enumCaseDeclaration) @@ -1918,26 +1930,35 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) bool hasCtor = false; bool needsDefaultCtor = (mCurTypeDef->mTypeCode != BfTypeCode_Interface) && (!mCurTypeDef->mIsStatic) && (!isAlias); bool hasDefaultCtor = false; - bool hasStaticCtor = false; - bool hasDtor = false; - bool hasStaticDtor = false; - bool hasMarkMethod = false; - bool hasStaticMarkMethod = false; - bool hasDynamicCastMethod = false; - bool hasToStringMethod = false; - bool needsEqualsMethod = ((mCurTypeDef->mTypeCode == BfTypeCode_Struct) || (mCurTypeDef->mTypeCode == BfTypeCode_Enum)) && (!mCurTypeDef->mIsStatic); - bool hasEqualsMethod = false; + BfMethodDef* ctorClear = NULL; + BfMethodDef* staticCtor = NULL; + BfMethodDef* dtor = NULL; + BfMethodDef* staticDtor = NULL; + BfMethodDef* markMethod = NULL; + BfMethodDef* staticMarkMethod = NULL; + BfMethodDef* dynamicCastMethod = NULL; + BfMethodDef* toStringMethod = NULL; + bool needsEqualsMethod = ((mCurTypeDef->mTypeCode == BfTypeCode_Struct) || (mCurTypeDef->mTypeCode == BfTypeCode_Enum)) && (!mCurTypeDef->mIsStatic); + BfMethodDef* equalsMethod = NULL; + BfMethodDef* strictEqualsMethod = NULL; bool needsStaticInit = false; for (int methodIdx = 0; methodIdx < (int)mCurTypeDef->mMethods.size(); methodIdx++) { auto method = mCurTypeDef->mMethods[methodIdx]; + + auto _SetMethod = [&](BfMethodDef*& setMethodDef, BfMethodDef* methodDef) + { + if ((setMethodDef != NULL) && (setMethodDef->mMethodDeclaration == NULL)) + setMethodDef->mProtection = BfProtection_Hidden; + setMethodDef = methodDef; + }; if (method->mMethodType == BfMethodType_Ctor) { if (method->mIsStatic) { - if (hasStaticCtor) + if ((staticCtor != NULL) && (staticCtor->mMethodDeclaration != NULL)) { Fail("Only one static constructor is allowed", method->mMethodDeclaration); method->mIsStatic = false; @@ -1950,9 +1971,9 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) } if (method->mName == BF_METHODNAME_MARKMEMBERS_STATIC) - hasStaticMarkMethod = true; + _SetMethod(staticMarkMethod, method); - hasStaticCtor = true; + _SetMethod(staticCtor, method); } else { @@ -1997,6 +2018,10 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) } } } + if (method->mMethodType == BfMethodType_CtorClear) + { + ctorClear = method; + } else if (method->mMethodType == BfMethodType_Init) { if (method->mIsStatic) @@ -2006,22 +2031,22 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) { if (method->mIsStatic) { - if (hasStaticDtor) + if ((staticDtor != NULL) && (staticDtor->mMethodDeclaration != NULL)) { Fail("Only one static constructor is allowed", method->mMethodDeclaration); method->mIsStatic = false; } - hasStaticDtor = true; + _SetMethod(staticDtor, method); } else { - if (hasDtor) + if ((dtor != NULL) && (dtor->mMethodDeclaration != NULL)) { Fail("Only one destructor is allowed", method->mMethodDeclaration); method->mIsStatic = false; } - hasDtor = true; + _SetMethod(dtor, method); } if (method->mParams.size() != 0) @@ -2032,16 +2057,16 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) if (method->mIsStatic) { if (method->mName == BF_METHODNAME_MARKMEMBERS_STATIC) - hasStaticMarkMethod = true; + _SetMethod(staticMarkMethod, method); } else { if (method->mName == BF_METHODNAME_MARKMEMBERS) - hasMarkMethod = true; + _SetMethod(markMethod, method); if (method->mName == BF_METHODNAME_DYNAMICCAST) - hasDynamicCastMethod = true; + _SetMethod(dynamicCastMethod, method); if (method->mName == BF_METHODNAME_TO_STRING) - hasToStringMethod = true; + _SetMethod(toStringMethod, method); } } else if ((method->mMethodType == BfMethodType_Operator) && @@ -2056,7 +2081,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) if ((method->mParams[0]->mTypeRef->ToString() == mCurTypeDef->mName->ToString()) && (method->mParams[1]->mTypeRef->ToString() == mCurTypeDef->mName->ToString())) { - hasEqualsMethod = true; + _SetMethod(equalsMethod, method); } } } @@ -2121,7 +2146,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) } } - bool needsDynamicCastMethod = !hasDynamicCastMethod; + bool needsDynamicCastMethod = dynamicCastMethod == NULL; if (mCurTypeDef->mIsFunction) { @@ -2131,24 +2156,24 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) needsDynamicCastMethod = false; } - if ((mCurTypeDef->mTypeCode == BfTypeCode_Object) && (!mCurTypeDef->mIsStatic)) + if ((mCurTypeDef->mTypeCode == BfTypeCode_Object) && (!mCurTypeDef->mIsStatic) && (ctorClear == NULL)) { auto methodDef = AddMethod(mCurTypeDef, BfMethodType_CtorClear, BfProtection_Private, false, ""); methodDef->mIsMutating = true; } - if ((needsDtor) && (!hasDtor)) + if ((needsDtor) && (dtor == NULL)) { auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, false, ""); BF_ASSERT(mCurTypeDef->mDtorDef == methodDef); } - if ((needsStaticDtor) && (!hasStaticDtor)) + if ((needsStaticDtor) && (staticDtor == NULL)) { auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Dtor, BfProtection_Public, true, ""); } - if ((needsStaticInit) && (!hasStaticCtor)) + if ((needsStaticInit) && (staticCtor == NULL)) { auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Ctor, BfProtection_Public, true, ""); } @@ -2202,7 +2227,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) if (mCurTypeDef->mTypeCode != BfTypeCode_Interface) { - if ((hasStaticField) && (!hasStaticMarkMethod)) + if ((hasStaticField) && (staticMarkMethod == NULL)) { auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, true, BF_METHODNAME_MARKMEMBERS_STATIC); methodDef->mIsNoReflect = true; @@ -2214,7 +2239,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) methodDef->mIsNoReflect = true; } - if ((hasNonStaticField) && (!hasMarkMethod)) + if ((hasNonStaticField) && (markMethod == NULL)) { auto methodDef = AddMethod(mCurTypeDef, BfMethodType_Normal, BfProtection_Protected, false, BF_METHODNAME_MARKMEMBERS); methodDef->mIsVirtual = true; @@ -2225,7 +2250,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) } } - if (hasToStringMethod) + if (toStringMethod != NULL) wantsToString = false; if ((mCurTypeDef->mTypeCode == BfTypeCode_Enum) && (!isPayloadEnum)) @@ -2292,7 +2317,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) mCurTypeDef->mHasOverrideMethods = true; } - if ((needsEqualsMethod) && (!hasEqualsMethod)) + if ((needsEqualsMethod) && (equalsMethod == NULL)) { auto methodDef = new BfMethodDef(); mCurTypeDef->mMethods.push_back(methodDef); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 93253681..23d9c639 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -799,7 +799,8 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp SET_BETTER_OR_WORSE((!isUnspecializedParam) && (!paramType->IsVar()), (!isPrevUnspecializedParam) && (!prevParamType->IsVar())); - if ((!isBetter) && (!isWorse) && (!isUnspecializedParam) && (!isPrevUnspecializedParam)) + // Why did we have this !isUnspecializedParam check? We need the 'canCast' logic still + if ((!isBetter) && (!isWorse) /*&& (!isUnspecializedParam) && (!isPrevUnspecializedParam)*/) { SET_BETTER_OR_WORSE((paramType != NULL) && (!paramType->IsUnspecializedType()), (prevParamType != NULL) && (!prevParamType->IsUnspecializedType())); @@ -851,7 +852,7 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp } } - if ((!isBetter) & (!isWorse) && (paramsEquivalent)) + if ((!isBetter) && (!isWorse) && (paramsEquivalent)) { if ((origParamType != origPrevParamType) && (paramWasConstExpr) && (!prevParamWasConstExpr)) betterByConstExprParam = true; @@ -2698,21 +2699,21 @@ BfAutoComplete* BfExprEvaluator::GetAutoComplete() return mModule->mCompiler->mResolvePassData->mAutoComplete; } -bool BfExprEvaluator::IsConstEval() +bool BfExprEvaluator::IsComptime() { - return (mModule->mIsConstModule) || ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0); + return (mModule->mIsComptimeModule) || ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0); } -bool BfExprEvaluator::IsConstEvalEntry() +bool BfExprEvaluator::IsComptimeEntry() { - if (mModule->mIsConstModule) + if (mModule->mIsComptimeModule) return false; - return ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0); + return ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0); } int BfExprEvaluator::GetStructRetIdx(BfMethodInstance* methodInstance, bool forceStatic) { - if (IsConstEval()) + if (IsComptime()) return -1; return methodInstance->GetStructRetIdx(forceStatic); } @@ -3333,7 +3334,7 @@ void BfExprEvaluator::Visit(BfLiteralExpression* literalExpr) void BfExprEvaluator::Visit(BfStringInterpolationExpression* stringInterpolationExpression) { - if (IsConstEvalEntry()) + if (IsComptimeEntry()) { mModule->Fail("Const evaluation of string interpolation not allowed", stringInterpolationExpression); } @@ -5075,43 +5076,57 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* if ((mModule->mCompiler->mResolvePassData != NULL) && (mModule->mCompiler->mResolvePassData->mAutoComplete != NULL)) { - // In an autocomplete pass we may have stale method references that need to be resolved - // in the full classify pass, and in the full classify pass while just refreshing internals, we - // may have NULL funcs temporarily. We simply skip generating the method call here. - if (methodInstance->mVirtualTableIdx == -1) - { - if (methodInstance->GetOwner()->IsInterface()) - { - // We're attempting to directly invoke a non-virtual interface method, if we're return an interface then - // it is a concrete interface - if (returnType->IsInterface()) - returnType = mModule->CreateConcreteInterfaceType(returnType->ToTypeInstance()); - } + bool wantQuickEval = true; + + if (IsComptime()) + { + auto autoComplete = mModule->mCompiler->mResolvePassData->mAutoComplete; + wantQuickEval = + ((autoComplete->mResolveType != BfResolveType_Autocomplete) && + (autoComplete->mResolveType != BfResolveType_Autocomplete_HighPri) && + (autoComplete->mResolveType != BfResolveType_GetResultString)); } - if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0) + if (wantQuickEval) { - if (methodInstance->mReturnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)) + // In an autocomplete pass we may have stale method references that need to be resolved + // in the full classify pass, and in the full classify pass while just refreshing internals, we + // may have NULL funcs temporarily. We simply skip generating the method call here. + if (methodInstance->mVirtualTableIdx == -1) { - if ((mExpectingType != NULL) && (mExpectingType->IsSizedArray())) + if (methodInstance->GetOwner()->IsInterface()) { - return BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(mExpectingType)), mExpectingType); + // We're attempting to directly invoke a non-virtual interface method, if we're return an interface then + // it is a concrete interface + if (returnType->IsInterface()) + returnType = mModule->CreateConcreteInterfaceType(returnType->ToTypeInstance()); } } - auto returnType = methodInstance->mReturnType; - if ((returnType->IsVar()) && (mExpectingType != NULL)) - returnType = mExpectingType; - if (methodInstance->mReturnType->IsValuelessType()) - return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), returnType); - return BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(returnType)), returnType); - } - BfTypedValue result; - if (sret != NULL) - result = *sret; - else - result = _GetDefaultReturnValue(); - return result; + if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) + { + if (methodInstance->mReturnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)) + { + if ((mExpectingType != NULL) && (mExpectingType->IsSizedArray())) + { + return BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(mExpectingType)), mExpectingType); + } + } + auto returnType = methodInstance->mReturnType; + if ((returnType->IsVar()) && (mExpectingType != NULL)) + returnType = mExpectingType; + if (methodInstance->mReturnType->IsValuelessType()) + return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), returnType); + return BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(returnType)), returnType); + } + + BfTypedValue result; + if (sret != NULL) + result = *sret; + else + result = _GetDefaultReturnValue(); + return result; + } } bool forceBind = false; @@ -5120,7 +5135,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* { bool doConstReturn = false; - if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0) + if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) { if (mFunctionBindResult != NULL) { @@ -5134,6 +5149,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* { doConstReturn = true; } + else if (((methodInstance->mComptimeFlags & BfComptimeFlag_OnlyFromComptime) != 0) && (!mModule->mIsComptimeModule)) + { + // This either generated an error already or this is just the non-const type check pass for a comptime-only method + doConstReturn = true; + } else { CeEvalFlags evalFlags = CeEvalFlags_None; @@ -5143,9 +5163,20 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* 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; + } } } - else if (mModule->mIsConstModule) + else if (mModule->mIsComptimeModule) { if (methodInstance->mIsUnspecialized) { @@ -5206,7 +5237,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* if (methodInstance->mMethodInstanceGroup->mOwner->IsInterface()) { - if (mModule->mIsConstModule) + if (mModule->mIsComptimeModule) { funcCallInst = mModule->mBfIRBuilder->ConstEval_GetInterfaceFunc(irArgs[0], methodInstance->mMethodInstanceGroup->mOwner->mTypeId, methodInstance->mMethodDef->mIdx, funcPtrType1); } @@ -5226,7 +5257,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* funcCallInst = mModule->mBfIRBuilder->CreateLoad(funcPtr); } } - else if (mModule->mIsConstModule) + else if (mModule->mIsComptimeModule) { funcCallInst = mModule->mBfIRBuilder->ConstEval_GetVirtualFunc(irArgs[0], methodInstance->mVirtualTableIdx, funcPtrType1); } @@ -5323,7 +5354,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* if (irArgs.size() != 0) { auto targetType = methodInstance->mMethodInstanceGroup->mOwner; - if ((targetType->IsValueType()) && (targetType->IsSplattable()) && (!methodDef->HasNoThisSplat()) && (!IsConstEval())) + if ((targetType->IsValueType()) && (targetType->IsSplattable()) && (!methodDef->HasNoThisSplat()) && (!IsComptime())) mFunctionBindResult->mTarget = BfTypedValue(irArgs[0], targetType, BfTypedValueKind_SplatHead); else mFunctionBindResult->mTarget = BfTypedValue(irArgs[0], targetType, targetType->IsComposite() ? BfTypedValueKind_Addr : BfTypedValueKind_Value); @@ -5484,7 +5515,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* mModule->PopulateType(paramType, BfPopulateType_Data); auto typeInst = paramType->ToTypeInstance(); - if ((typeInst != NULL) && (typeInst->mIsCRepr) && (typeInst->IsSplattable()) && (!IsConstEval())) + if ((typeInst != NULL) && (typeInst->mIsCRepr) && (typeInst->IsSplattable()) && (!IsComptime())) { // We're splatting } @@ -5527,7 +5558,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* doingThis = false; continue; } - bool isSplatted = methodInstance->GetParamIsSplat(thisIdx) && (!IsConstEval()); // (resolvedTypeRef->IsSplattable()) && (!methodDef->mIsMutating); + bool isSplatted = methodInstance->GetParamIsSplat(thisIdx) && (!IsComptime()); // (resolvedTypeRef->IsSplattable()) && (!methodDef->mIsMutating); if (isSplatted) { BfTypeUtils::SplatIterate(_HandleParamType, paramType); @@ -5561,7 +5592,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* continue; } - if ((methodInstance->GetParamIsSplat(paramIdx)) && (!IsConstEval())) + if ((methodInstance->GetParamIsSplat(paramIdx)) && (!IsComptime())) { BfTypeUtils::SplatIterate(_HandleParamType, paramType); paramIdx++; @@ -5614,7 +5645,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* { BfTypeCode loweredRetType = BfTypeCode_None; BfTypeCode loweredRetType2 = BfTypeCode_None; - if ((!IsConstEval()) && (methodInstance->GetLoweredReturnType(&loweredRetType, &loweredRetType2))) + if ((!IsComptime()) && (methodInstance->GetLoweredReturnType(&loweredRetType, &loweredRetType2))) { auto retVal = mModule->CreateAlloca(methodInstance->mReturnType); BfIRType loweredIRType = mModule->GetIRLoweredType(loweredRetType, loweredRetType2); @@ -5780,7 +5811,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl& ir return; bool wantSplat = false; - if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsConstEval())) + if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsComptime())) { disableLowering = true; auto argTypeInstance = argVal.mType->ToTypeInstance(); @@ -5801,7 +5832,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl& ir { if (argVal.mType->IsComposite()) { - if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0) + if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) { // Const eval entry - we want any incoming consts as they are } @@ -5812,7 +5843,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl& ir else argVal = mModule->MakeAddressable(argVal); - if ((!IsConstEval()) && (!disableLowering) && (!isIntrinsic)) + if ((!IsComptime()) && (!disableLowering) && (!isIntrinsic)) { BfTypeCode loweredTypeCode = BfTypeCode_None; BfTypeCode loweredTypeCode2 = BfTypeCode_None; @@ -5906,7 +5937,7 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth auto owner = methodInstance->GetOwner(); bool allowThisSplatting; - if (mModule->mIsConstModule) + if (mModule->mIsComptimeModule) allowThisSplatting = owner->IsTypedPrimitive() || owner->IsValuelessType(); else allowThisSplatting = methodInstance->AllowsSplatting(-1); @@ -6210,7 +6241,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu } else { - wantsSplat = methodInstance->GetParamIsSplat(paramIdx) && (!IsConstEval()); + wantsSplat = methodInstance->GetParamIsSplat(paramIdx) && (!IsComptime()); if (methodInstance->IsImplicitCapture(paramIdx)) { auto paramType = methodInstance->GetParamType(paramIdx); @@ -6275,7 +6306,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu if (methodDef->mMethodType == BfMethodType_Extension) numElements++; - if (IsConstEvalEntry()) + if (IsComptimeEntry()) { if ((wantType->IsArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))) { @@ -6694,7 +6725,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu else { // We need to make a temp and get the addr of that - if ((!wantsSplat) && (!argValue.IsValuelessType()) && (!argValue.IsAddr()) && (!IsConstEvalEntry())) + if ((!wantsSplat) && (!argValue.IsValuelessType()) && (!argValue.IsAddr()) && (!IsComptimeEntry())) { argValue = mModule->MakeAddressable(argValue); } @@ -6714,7 +6745,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu { if (argValue) { - if (IsConstEvalEntry()) + if (IsComptimeEntry()) { auto constant = mModule->mBfIRBuilder->GetConstant(expandedParamsArray.mValue); BF_ASSERT(constant->mConstType == BfConstType_Agg); @@ -8588,15 +8619,28 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp // { SetAndRestoreValue prevEvalExprFlag(mBfEvalExprFlags); - + if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) && (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mConstEvalAttributeTypeDef))) { mModule->mAttributeState->mUsed = true; - mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_ConstEval); + mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime); } - else if (moduleMethodInstance.mMethodInstance->mMethodDef->mIsConstEval) + else if ((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) { - mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_ConstEval); + mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime); + } + else if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_Comptime) != 0) && (!mModule->mIsComptimeModule)) + { + mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime); + } + + if (((moduleMethodInstance.mMethodInstance->mComptimeFlags & BfComptimeFlag_OnlyFromComptime) != 0) && + ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && + (mModule->mCurMethodInstance->mComptimeFlags == BfComptimeFlag_None) && + (!mModule->mIsComptimeModule)) + { + mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags &~ BfEvalExprFlags_Comptime); + mModule->Fail(StrFormat("Method '%s' can only be invoked at comptime. Consider adding [Comptime] to the current method.", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc); } result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, bypassVirtual, argValues.mResolvedArgs, &argCascade, skipThis); @@ -11314,7 +11358,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr) for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++) { auto paramType = methodInstance->GetParamType(paramIdx); - if ((paramType->IsSplattable()) && (!IsConstEval())) + if ((paramType->IsSplattable()) && (!IsComptime())) { BfTypeUtils::SplatIterate([&](BfType* checkType) { irArgs.push_back(mModule->mBfIRBuilder->GetArgument(argIdx++)); }, paramType); } @@ -13180,7 +13224,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs // Actually leave it alone? if ((isUninit) && - ((mModule->IsOptimized()) || (mModule->mIsConstModule) || (mModule->mBfIRBuilder->mIgnoreWrites))) + ((mModule->IsOptimized()) || (mModule->mIsComptimeModule) || (mModule->mBfIRBuilder->mIgnoreWrites))) return; bool doClear = true; @@ -13564,7 +13608,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs { allocValue = mModule->AllocFromType(resolvedTypeRef, allocTarget, appendSizeValue, BfIRValue(), 0, BfAllocFlags_None, allocAlign); } - if (((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0) && (mModule->mCompiler->mCEMachine != NULL)) + if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCEMachine != NULL)) { mModule->mCompiler->mCEMachine->SetAppendAllocInfo(mModule, allocValue, appendSizeValue); } @@ -13615,7 +13659,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs { mModule->AssertErrorState(); } - else if ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) == 0) + else if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) == 0) { SizedArray irArgs; irArgs.push_back(mResult.mValue); @@ -13623,7 +13667,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs } } - if ((!mModule->mIsConstModule) && (isStackAlloc) && (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck)) + if ((!mModule->mIsComptimeModule) && (isStackAlloc) && (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck)) { BfMethodInstance* markMethod = mModule->GetRawMethodByName(mModule->mContext->mBfObjectType, "GCMarkMembers"); BF_ASSERT(markMethod != NULL); @@ -13693,7 +13737,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs } } - if (((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0) && (mModule->mCompiler->mCEMachine != NULL)) + if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCEMachine != NULL)) { mModule->mCompiler->mCEMachine->ClearAppendAllocInfo(); } @@ -13887,7 +13931,7 @@ BfTypedValue BfExprEvaluator::MakeCallableTarget(BfAstNode* targetSrc, BfTypedVa if ((target.mType->IsStruct()) && (!target.IsAddr())) { - if (IsConstEvalEntry()) + if (IsComptimeEntry()) return target; target = mModule->MakeAddressable(target); } @@ -13923,7 +13967,7 @@ BfTypedValue BfExprEvaluator::MakeCallableTarget(BfAstNode* targetSrc, BfTypedVa auto ptrType = mModule->CreatePointerType(primStructType); target = BfTypedValue(mModule->mBfIRBuilder->CreateBitCast(target.mValue, mModule->mBfIRBuilder->MapType(ptrType)), primStructType, true); } - else if ((primStructType->IsSplattable()) && (target.IsSplat()) && (!IsConstEval())) + else if ((primStructType->IsSplattable()) && (target.IsSplat()) && (!IsComptime())) { target.mType = primStructType; target.mKind = BfTypedValueKind_SplatHead; @@ -15739,7 +15783,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m int methodCount = 0; bool mayBeSkipCall = false; - bool mayBeConstEvalCall = false; + bool mayBeComptimeCall = false; if (thisValue.mType != NULL) { if (thisValue.mType->IsAllocType()) @@ -15757,8 +15801,8 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m { if (methodDef->mIsSkipCall) mayBeSkipCall = true; - if (methodDef->mIsConstEval) - mayBeConstEvalCall = true; + if (methodDef->mHasComptime) + mayBeComptimeCall = true; methodDef = methodDef->mNextWithSameName; } } @@ -15784,7 +15828,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m BfResolveArgsFlags resolveArgsFlags = (BfResolveArgsFlags)(BfResolveArgsFlag_DeferFixits | BfResolveArgsFlag_AllowUnresolvedTypes); resolveArgsFlags = (BfResolveArgsFlags)(resolveArgsFlags | BfResolveArgsFlag_DeferParamEval); - if ((mayBeSkipCall) || (mayBeConstEvalCall)) + if ((mayBeSkipCall) || (mayBeComptimeCall)) resolveArgsFlags = (BfResolveArgsFlags)(resolveArgsFlags | BfResolveArgsFlag_DeferParamValues); static int sCallIdx = 0; @@ -15810,7 +15854,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m } } - if ((isCascade) && (cascadeOperatorToken != NULL) && ((mBfEvalExprFlags & BfEvalExprFlags_ConstEval) != 0)) + if ((isCascade) && (cascadeOperatorToken != NULL) && ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0)) mModule->Fail("Cascade operator cannot be used in const evaluation", cascadeOperatorToken); SetAndRestoreValue prevUsedAsStatement(mUsedAsStatement, mUsedAsStatement || isCascade); @@ -16061,7 +16105,7 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m } } } - + if ((mOrigPropTarget) && (mOrigPropTarget.mType != mPropTarget.mType) && ((!mOrigPropTarget.mType->IsGenericParam()) && (mPropTarget.mType->IsInterface()))) { @@ -16080,6 +16124,10 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m while (checkTypeInst != NULL) { mModule->PopulateType(checkTypeInst, BfPopulateType_DataAndMethods); + BF_ASSERT((checkTypeInst->mDefineState >= BfTypeDefineState_DefinedAndMethodsSlotted) || (mModule->mCompiler->IsAutocomplete())); + + if (checkTypeInst->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotted) + break; for (auto& iface : checkTypeInst->mInterfaces) { @@ -16132,7 +16180,7 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m } if (bestIFaceEntry != NULL) - { + { auto ifaceMethodEntry = checkTypeInst->mInterfaceMethodTable[bestIFaceEntry->mStartInterfaceTableIdx + methodDef->mIdx]; BfMethodInstance* bestMethodInstance = ifaceMethodEntry.mMethodRef; if (bestMethodInstance != NULL) @@ -18735,7 +18783,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr) } } } - else if (((mModule->HasCompiledOutput()) || (mModule->mIsConstModule)) && + else if (((mModule->HasCompiledOutput()) || (mModule->mIsComptimeModule)) && (wantsChecks)) { if (checkedKind == BfCheckedKind_NotSet) @@ -18767,7 +18815,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr) OutputDebugStrF("-OOB %d %d\n", oobFunc.mFunc.mId, oobFunc.mFunc.mFlags); }*/ - if (mModule->mIsConstModule) + if (mModule->mIsComptimeModule) mModule->mCompiler->mCEMachine->QueueMethod(oobFunc.mMethodInstance, oobFunc.mFunc); SizedArray args; diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index d7deb934..3ba5398b 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -390,8 +390,8 @@ public: void FinishExpressionResult(); virtual bool CheckAllowValue(const BfTypedValue& typedValue, BfAstNode* refNode); BfAutoComplete* GetAutoComplete(); - bool IsConstEval(); - bool IsConstEvalEntry(); + bool IsComptime(); + bool IsComptimeEntry(); int GetStructRetIdx(BfMethodInstance* methodInstance, bool forceStatic = false); BfTypedValue SetupNullConditional(BfTypedValue target, BfTokenNode* dotToken); void Evaluate(BfAstNode* astNode, bool propogateNullConditional = false, bool ignoreNullConditional = false, bool allowSplat = true); diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index ef688514..c778b209 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -634,6 +634,12 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f auto typeOf = (BfTypeOf_Const*)fromConst; return CreateTypeOf(typeOf->mType); } + else if (fromConst->mConstType == BfConstType_TypeOf_WithData) + { + auto typeOf = (BfTypeOf_WithData_Const*)fromConst; + auto dataConstant = fromHolder->GetConstant(typeOf->mTypeData); + return CreateTypeOf(typeOf->mType, CreateConst(dataConstant, fromHolder)); + } else if (fromConst->mConstType == BfConstType_AggZero) { auto aggZero = (BfConstant*)fromConst; @@ -783,7 +789,20 @@ BfIRValue BfIRConstHolder::CreateTypeOf(BfType* type) { BfTypeOf_Const* typeOf = mTempAlloc.Alloc(); typeOf->mConstType = BfConstType_TypeOf; + typeOf->mType = type; + auto irValue = BfIRValue(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(typeOf)); +#ifdef CHECK_CONSTHOLDER + irValue.mHolder = this; +#endif + return irValue; +} + +BfIRValue BfIRConstHolder::CreateTypeOf(BfType* type, BfIRValue typeData) +{ + BfTypeOf_WithData_Const* typeOf = mTempAlloc.Alloc(); + typeOf->mConstType = BfConstType_TypeOf_WithData; typeOf->mType = type; + typeOf->mTypeData = typeData; auto irValue = BfIRValue(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(typeOf)); #ifdef CHECK_CONSTHOLDER irValue.mHolder = this; @@ -1949,11 +1968,18 @@ void BfIRBuilder::Write(const BfIRValue& irValue) { Write(constant->mInt64); } + break; + case (int)BfConstType_TypeOf: + { + auto typeofConst = (BfTypeOf_Const*)constant; + Write(MapType(typeofConst->mType, BfIRPopulateType_Identity)); + } break; - case (int)BfConstType_Undef: - { - auto undefConst = (BfConstantUndef*)constant; - Write(undefConst->mType); + case (int)BfConstType_TypeOf_WithData: + { + auto typeofConst = (BfTypeOf_WithData_Const*)constant; + Write(MapType(typeofConst->mType, BfIRPopulateType_Identity)); + Write(typeofConst->mTypeData); } break; default: @@ -4476,6 +4502,12 @@ BfIRValue BfIRBuilder::CreateGlobalStringPtr(const StringImpl& str) return retVal; } +void BfIRBuilder::SetReflectTypeData(BfIRType type, BfIRValue globalVar) +{ + BfIRValue retVal = WriteCmd(BfIRCmd_SetReflectTypeData, type, globalVar); + NEW_CMD_INSERTED_IRVALUE; +} + BfIRBlock BfIRBuilder::CreateBlock(const StringImpl& name, bool addNow) { if (addNow) diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index c854f663..86acbbae 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -120,6 +120,7 @@ enum BfConstType BfConstType_PtrToInt, BfConstType_IntToPtr, BfConstType_TypeOf, + BfConstType_TypeOf_WithData, BfConstType_AggZero, BfConstType_Agg, BfConstType_ArrayZero, @@ -235,6 +236,7 @@ enum BfIRCmd : uint8 BfIRCmd_GlobalVar_SetAlignment, BfIRCmd_GlobalVar_SetStorageKind, BfIRCmd_GlobalStringPtr, + BfIRCmd_SetReflectTypeData, BfIRCmd_CreateBlock, BfIRCmd_MaybeChainNewBlock, @@ -771,6 +773,14 @@ struct BfTypeOf_Const { BfConstType mConstType; BfType* mType; + BfIRValue mTypeData; +}; + +struct BfTypeOf_WithData_Const +{ + BfConstType mConstType; + BfType* mType; + BfIRValue mTypeData; }; struct BfConstant @@ -906,6 +916,7 @@ public: BfIRValue CreateConstArrayZero(BfIRType type, int count); BfIRValue CreateConstArrayZero(int count); BfIRValue CreateTypeOf(BfType* type); + BfIRValue CreateTypeOf(BfType* type, BfIRValue typeData); BfIRValue GetUndefConstValue(BfIRType type); }; @@ -1199,6 +1210,7 @@ public: void GlobalVar_SetAlignment(BfIRValue globalVar, int alignment); void GlobalVar_SetStorageKind(BfIRValue globalVar, BfIRStorageKind storageKind); BfIRValue CreateGlobalStringPtr(const StringImpl& str); + void SetReflectTypeData(BfIRType type, BfIRValue globalVar); BfIRBlock CreateBlock(const StringImpl& name, bool addNow = false); BfIRBlock MaybeChainNewBlock(const StringImpl& name); // Creates new block if current block isn't empty diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index 74312632..9c2a41a6 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -941,6 +941,21 @@ void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry) llvmValue = llvm::UndefValue::get(type); return; } + else if (constType == BfConstType_TypeOf) + { + CMD_PARAM(llvm::Type*, type); + llvmValue = mReflectDataMap[type]; + BF_ASSERT(llvmValue != NULL); + return; + } + else if (constType == BfConstType_TypeOf_WithData) + { + CMD_PARAM(llvm::Type*, type); + CMD_PARAM(llvm::Value*, value); + mReflectDataMap[type] = value; + llvmValue = value; + return; + } bool isSigned; llvm::Type* llvmConstType = GetLLVMType(typeCode, isSigned); @@ -2266,6 +2281,13 @@ void BfIRCodeGen::HandleNextCmd() SetResult(curId, mIRBuilder->CreateGlobalStringPtr(llvm::StringRef(str.c_str(), str.length()))); } break; + case BfIRCmd_SetReflectTypeData: + { + CMD_PARAM(llvm::Type*, type); + CMD_PARAM(llvm::Value*, value); + mReflectDataMap[type] = value; + } + break; case BfIRCmd_CreateBlock: { CMD_PARAM(String, name); diff --git a/IDEHelper/Compiler/BfIRCodeGen.h b/IDEHelper/Compiler/BfIRCodeGen.h index 3803066b..5b60164c 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.h +++ b/IDEHelper/Compiler/BfIRCodeGen.h @@ -107,7 +107,8 @@ public: Dictionary mIntrinsicMap; Dictionary mIntrinsicReverseMap; Array mConfigConsts32; - Array mConfigConsts64; + Array mConfigConsts64; + Dictionary mReflectDataMap; public: void InitTarget(); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 0b1f06a1..2f7270f7 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -849,7 +849,7 @@ BfModule::BfModule(BfContext* context, const StringImpl& moduleName) mIsReified = true; mReifyQueued = false; mIsSpecialModule = false; - mIsConstModule = false; + mIsComptimeModule = false; mIsScratchModule = false; mIsSpecializedMethodModuleRoot = false; // There may be mNextAltModules extending from this mHadBuildError = false; @@ -1018,11 +1018,11 @@ void BfModule::FinishInit() mHasFullDebugInfo = moduleOptions.mEmitDebugInfo == 1; - if (mIsConstModule) + if (mIsComptimeModule) mHasFullDebugInfo = false; if (((!mCompiler->mIsResolveOnly) && (!mIsScratchModule) && (moduleOptions.mEmitDebugInfo != 0) && (mIsReified)) || - (mIsConstModule)) + (mIsComptimeModule)) { mBfIRBuilder->DbgInit(); } @@ -1955,7 +1955,7 @@ void BfModule::AddStackAlloc(BfTypedValue val, BfIRValue arraySize, BfAstNode* r //TODO: In the future we could be smarter about statically determining that our value hasn't escaped and eliding this if (mayEscape) { - if ((!IsOptimized()) && (!mIsConstModule) && (!val.mType->IsValuelessType()) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly)) + if ((!IsOptimized()) && (!mIsComptimeModule) && (!val.mType->IsValuelessType()) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly)) { auto nullPtrType = GetPrimitiveType(BfTypeCode_NullPtr); bool isDyn = mCurMethodState->mCurScope->IsDyn(scopeData); @@ -2058,7 +2058,7 @@ bool BfModule::TryLocalVariableInit(BfLocalVariable* localVar) if (!fieldDef->mDeclaringType->IsExtension()) return false; - if ((fieldInstance.mDataIdx != -1) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly) && (!mIsConstModule)) + if ((fieldInstance.mDataIdx != -1) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly) && (!mIsComptimeModule)) { auto curInsertBlock = mBfIRBuilder->GetInsertBlock(); @@ -2401,7 +2401,7 @@ BfFileInstance* BfModule::GetFileFromNode(BfAstNode* astNode) fileName[i] = DIR_SEP_CHAR; } - bfFileInstance->mDIFile = mBfIRBuilder->DbgCreateFile(fileName.Substring(slashPos + 1), fileName.Substring(0, slashPos), bfParser->mMD5Hash); + bfFileInstance->mDIFile = mBfIRBuilder->DbgCreateFile(fileName.Substring(slashPos + 1), fileName.Substring(0, BF_MAX(slashPos, 0)), bfParser->mMD5Hash); } return bfFileInstance; } @@ -2507,7 +2507,7 @@ void BfModule::UpdateSrcPos(BfAstNode* astNode, BfSrcPosFlags flags, int debugLo if (mCurMethodState->mCrossingMixin) inlineAt = BfIRMDNode(); - if ((!useDIScope) && (mIsConstModule)) + if ((!useDIScope) && (mIsComptimeModule)) useDIScope = wantDIFile; mBfIRBuilder->SetCurrentDebugLocation(mCurFilePosition.mCurLine + 1, column, useDIScope, inlineAt); if ((flags & BfSrcPosFlag_Expression) == 0) @@ -2726,34 +2726,34 @@ void BfModule::SetFail() void BfModule::VerifyOnDemandMethods() { #ifdef _DEBUG -// if (mParentModule != NULL) -// { -// BF_ASSERT(mOnDemandMethodCount == 0); -// mParentModule->VerifyOnDemandMethods(); -// return; -// } -// -// int onDemandCount = 0; -// for (auto type : mOwnedTypeInstances) -// { -// auto typeInst = type->ToTypeInstance(); -// for (auto& methodGroup : typeInst->mMethodInstanceGroups) -// { -// if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) || -// (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) || -// (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) || -// (methodGroup.mOnDemandKind == BfMethodOnDemandKind_InWorkList)) -// onDemandCount++; -// } -// } -// -// BF_ASSERT(mOnDemandMethodCount == onDemandCount); +// if (mParentModule != NULL) +// { +// BF_ASSERT(mOnDemandMethodCount == 0); +// mParentModule->VerifyOnDemandMethods(); +// return; +// } +// +// int onDemandCount = 0; +// for (auto type : mOwnedTypeInstances) +// { +// auto typeInst = type->ToTypeInstance(); +// for (auto& methodGroup : typeInst->mMethodInstanceGroups) +// { +// if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) || +// (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) || +// (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) || +// (methodGroup.mOnDemandKind == BfMethodOnDemandKind_InWorkList)) +// onDemandCount++; +// } +// } +// +// BF_ASSERT(mOnDemandMethodCount == onDemandCount); #endif } bool BfModule::IsSkippingExtraResolveChecks() { - if (mIsConstModule) + if (mIsComptimeModule) return false; return mCompiler->IsSkippingExtraResolveChecks(); } @@ -2781,7 +2781,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers //BF_ASSERT(refNode != NULL); - if (mIsConstModule) + if (mIsComptimeModule) { mHadBuildError = true; return NULL; @@ -3615,9 +3615,21 @@ BfCheckedKind BfModule::GetDefaultCheckedKind() void BfModule::AddFailType(BfTypeInstance* typeInstance) { BF_ASSERT(typeInstance != NULL); + if ((typeInstance->mRebuildFlags & BfTypeRebuildFlag_InFailTypes) != 0) + return; + typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags | BfTypeRebuildFlag_InFailTypes); mContext->mFailTypes.Add(typeInstance); } +void BfModule::DeferRebuildType(BfTypeInstance* typeInstance) +{ + if ((typeInstance->mRebuildFlags & BfTypeRebuildFlag_RebuildQueued) != 0) + return; + mCompiler->mHasQueuedTypeRebuilds = true; + typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags | BfTypeRebuildFlag_RebuildQueued); + AddFailType(typeInstance); +} + void BfModule::CheckAddFailType() { //TODO: We removed this line, because failures in resolve-only generic method can occur in non-owning modules @@ -4745,7 +4757,7 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou BfType* classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef); - if (mIsConstModule) + if (mIsComptimeModule) { auto idVal = mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, typeInstance->mTypeId); return mBfIRBuilder->CreateIntToPtr(idVal, mBfIRBuilder->MapType(CreatePointerType(classVDataType))); @@ -4825,7 +4837,7 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou BfIRValue BfModule::GetClassVDataPtr(BfTypeInstance* typeInstance) { auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef); - if (mIsConstModule) + if (mIsComptimeModule) return mBfIRBuilder->ConstEval_GetBfType(typeInstance->mTypeId, mBfIRBuilder->MapType(CreatePointerType(classVDataType))); return mBfIRBuilder->CreateBitCast(CreateClassVDataGlobal(typeInstance), mBfIRBuilder->MapType(CreatePointerType(classVDataType))); } @@ -4939,7 +4951,7 @@ BfIRValue BfModule::CreateTypeDataRef(BfType* type) return mBfIRBuilder->CreateTypeOf(type); } - if (mIsConstModule) + if (mIsComptimeModule) { auto typeTypeDef = ResolveTypeDef(mCompiler->mTypeTypeDef); auto typeTypeInst = typeTypeDef->ToTypeInstance(); @@ -4951,9 +4963,8 @@ BfIRValue BfModule::CreateTypeDataRef(BfType* type) BfIRValue* globalVariablePtr = NULL; if (mTypeDataRefs.TryGetValue(type, &globalVariablePtr)) { - globalVariable = *globalVariablePtr; - if (globalVariable) - return globalVariable; + if (*globalVariablePtr) + return mBfIRBuilder->CreateTypeOf(type, *globalVariablePtr); } auto typeTypeDef = ResolveTypeDef(mCompiler->mTypeTypeDef); @@ -4974,9 +4985,10 @@ BfIRValue BfModule::CreateTypeDataRef(BfType* type) BfLogSysM("Creating TypeData %s\n", typeDataName.c_str()); globalVariable = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(typeTypeInst, BfIRPopulateType_Full), true, BfIRLinkageType_External, BfIRValue(), typeDataName); + mBfIRBuilder->SetReflectTypeData(mBfIRBuilder->MapType(type), globalVariable); - mTypeDataRefs[type] = globalVariable; - return globalVariable; + mTypeDataRefs[type] = globalVariable; + return mBfIRBuilder->CreateTypeOf(type, globalVariable); } BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStringIdMap, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData) @@ -5084,9 +5096,10 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } int typeCode = BfTypeCode_None; - + if (typeInstance != NULL) { + BF_ASSERT((type->mDefineState >= BfTypeDefineState_DefinedAndMethodsSlotted) || mIsComptimeModule); typeCode = typeInstance->mTypeDef->mTypeCode; } else if (type->IsPrimitiveType()) @@ -5107,10 +5120,13 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (type->IsObject()) { - typeFlags |= BfTypeFlags_Object; - BfMethodInstance* methodInstance = typeInstance->mVirtualMethodTable[mCompiler->GetVTableMethodOffset() + 0].mImplementingMethod; - if (methodInstance->GetOwner() != mContext->mBfObjectType) - typeFlags |= BfTypeFlags_HasDestructor; + typeFlags |= BfTypeFlags_Object; + if (typeInstance->mDefineState >= BfTypeDefineState_DefinedAndMethodsSlotted) + { + BfMethodInstance* methodInstance = typeInstance->mVirtualMethodTable[mCompiler->GetVTableMethodOffset() + 0].mImplementingMethod; + if (methodInstance->GetOwner() != mContext->mBfObjectType) + typeFlags |= BfTypeFlags_HasDestructor; + } } if (type->IsStruct()) typeFlags |= BfTypeFlags_Struct; @@ -5256,14 +5272,14 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin // Reserve position mTypeDataRefs[typeInstance] = BfIRValue(); - if (typeInstance->IsReified()) + if ((typeInstance->IsReified()) && (!mIsComptimeModule)) PopulateType(typeInstance, BfPopulateType_DataAndMethods); BfTypeDef* typeDef = typeInstance->mTypeDef; StringT<128> mangledName; BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), typeInstance, typeInstance->mModule); - if (!mIsConstModule) + if (!mIsComptimeModule) { for (int methodIdx = 0; methodIdx < (int)typeDef->mMethods.size(); methodIdx++) { @@ -5417,7 +5433,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin { highestIFaceVirtIdx = BF_MAX(highestIFaceVirtIdx, interfaceEntry.mStartVirtualIdx + interfaceEntry.mInterfaceType->mVirtualMethodTableSize); - if ((!mIsConstModule) && (!typeInstance->IsTypeMemberAccessible(interfaceEntry.mDeclaringType, mProject))) + if ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(interfaceEntry.mDeclaringType, mProject))) continue; _InterfaceMatchEntry* matchEntry = NULL; @@ -5492,7 +5508,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } } - if ((!mIsConstModule) && (!typeInstance->IsInterface()) && (typeInstance->mVirtualMethodTableSize > 0) && (needsVData)) + if ((!mIsComptimeModule) && (!typeInstance->IsInterface()) && (typeInstance->mVirtualMethodTableSize > 0) && (needsVData)) { int startTabIdx = (int)vData.size(); @@ -5517,13 +5533,13 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin continue; BfMethodInstance* methodInstance = (BfMethodInstance*)entry.mImplementingMethod; if ((methodInstance == NULL) || - ((!mIsConstModule) && (!typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject)))) + ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject)))) { if (origVTable.empty()) origVTable = typeInstance->mVirtualMethodTable; BfMethodInstance* declMethodInstance = entry.mDeclaringMethod; - if ((mIsConstModule) || (typeInstance->IsTypeMemberAccessible(declMethodInstance->mMethodDef->mDeclaringType, mProject))) + if ((mIsComptimeModule) || (typeInstance->IsTypeMemberAccessible(declMethodInstance->mMethodDef->mDeclaringType, mProject))) { // Prepare to reslot... entry.mImplementingMethod = entry.mDeclaringMethod; @@ -5555,7 +5571,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (!reslotNames.Contains(methodInstance->mMethodDef->mName)) continue; - if ((!mIsConstModule) && (!typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject))) + if ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject))) continue; if ((methodInstance->mChainType != BfMethodChainType_None) && (methodInstance->mChainType != BfMethodChainType_ChainHead)) continue; @@ -5591,7 +5607,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin BfMethodInstance* methodInstance = (BfMethodInstance*)entry.mImplementingMethod; if ((methodInstance != NULL) && (!methodInstance->mMethodDef->mIsAbstract)) { - BF_ASSERT((mIsConstModule) || typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject)); + BF_ASSERT((mIsComptimeModule) || typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject)); moduleMethodInst = GetMethodInstanceAtIdx(methodInstance->mMethodInstanceGroup->mOwner, methodInstance->mMethodInstanceGroup->mMethodIdx, NULL, BfGetMethodInstanceFlag_NoInline); auto funcPtr = mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, voidPtrIRType); vValue = funcPtr; @@ -5656,8 +5672,14 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin { auto interfaceEntry = interfacePair.mValue.mEntry; + if (typeInstance->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted) + { + BF_ASSERT(mIsComptimeModule); + break; + } + bool makeEmpty = false; - if ((!mIsConstModule) && (!typeInstance->IsTypeMemberAccessible(interfaceEntry->mDeclaringType, mProject))) + if ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(interfaceEntry->mDeclaringType, mProject))) makeEmpty = true; int endVirtualIdx = interfaceEntry->mStartVirtualIdx + interfaceEntry->mInterfaceType->mVirtualMethodTableSize; @@ -5753,10 +5775,10 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } } - if ((needsVData) && (!typeInstance->mTypeDef->mIsStatic) && (!mIsConstModule)) + if ((needsVData) && (!typeInstance->mTypeDef->mIsStatic) && (!mIsComptimeModule)) { BfIRValue ifaceMethodExtVar; - if ((!ifaceMethodExtData.IsEmpty()) && (!mIsConstModule)) + if ((!ifaceMethodExtData.IsEmpty()) && (!mIsComptimeModule)) { StringT<128> classVDataName; BfMangler::MangleStaticFieldName(classVDataName, mCompiler->GetMangleKind(), typeInstance, "bf_hs_replace_IFaceExt"); @@ -6355,7 +6377,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin break; // Disable const method reflection info for now - if (mIsConstModule) + if (mIsComptimeModule) break; auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodIdx]; @@ -6400,7 +6422,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } } - if ((!mIsConstModule) && (!typeInstance->IsTypeMemberAccessible(methodDef->mDeclaringType, mProject))) + if ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(methodDef->mDeclaringType, mProject))) continue; // @@ -6838,7 +6860,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin mTypeDataRefs[typeInstance] = typeDataVar; - if ((!mIsConstModule) && (classVDataVar)) + if ((!mIsComptimeModule) && (classVDataVar)) { BF_ASSERT(!classVDataName.IsEmpty()); @@ -6868,7 +6890,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin BfIRValue BfModule::FixClassVData(BfIRValue value) { - if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsConstModule)) + if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsComptimeModule)) return value; auto intptrValue = mBfIRBuilder->CreatePtrToInt(value, BfTypeCode_IntPtr); auto maskedValue = mBfIRBuilder->CreateAnd(intptrValue, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)~0xFFULL)); @@ -6880,7 +6902,7 @@ void BfModule::CheckStaticAccess(BfTypeInstance* typeInstance) // Note: this is not just for perf, it fixes a field var-type resolution issue if (mBfIRBuilder->mIgnoreWrites) return; - if (mIsConstModule) + if (mIsComptimeModule) return; PopulateType(typeInstance, BfPopulateType_DataAndMethods); @@ -7022,7 +7044,7 @@ BfIRFunction BfModule::GetBuiltInFunc(BfBuiltInFuncType funcTypeId) break; case BfBuiltInFuncType_Malloc: { - if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule)) + if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule)) { func = GetInternalMethod("Dbg_RawAlloc", 1).mFunc; } @@ -7045,7 +7067,7 @@ BfIRFunction BfModule::GetBuiltInFunc(BfBuiltInFuncType funcTypeId) break; case BfBuiltInFuncType_Free: { - if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule)) + if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule)) { func = GetInternalMethod("Dbg_RawFree").mFunc; } @@ -8167,7 +8189,7 @@ void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, boo auto destAddr = mBfIRBuilder->CreateBitCast(vObjectAddr, mBfIRBuilder->MapType(ptrPtrType)); if (!isAutocomplete) { - if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) + if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule)) { auto objectPtr = mBfIRBuilder->CreateBitCast(destAddr, mBfIRBuilder->MapType(mContext->mBfObjectType)); @@ -8273,7 +8295,7 @@ BfIRValue BfModule::AllocBytes(BfAstNode* refNode, const BfAllocTarget& allocTar if ((allocFlags & BfAllocFlags_NoDefaultToMalloc) != 0) return result; - if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule)) + if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule)) { BfIRValue allocData = GetDbgRawAllocData(type); BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_RawAlloc", 2); @@ -8592,7 +8614,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget BfIRBlock clearBlock; BfIRBlock contBlock; - bool wantsDeinit = ((!IsOptimized()) && (!mIsConstModule) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly)); + bool wantsDeinit = ((!IsOptimized()) && (!mIsComptimeModule) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly)); if (wantsDeinit) { @@ -8852,7 +8874,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget auto typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx); stackCount = BfTypeOptions::Apply(stackCount, typeOptions->mAllocStackTraceDepth); } - if (mIsConstModule) + if (mIsComptimeModule) stackCount = 0; if (!sizeValue) @@ -8924,7 +8946,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget { if (hasCustomAllocator) result = AllocBytes(allocTarget.mRefNode, allocTarget, typeInstance, sizeValue, GetConstValue(typeInstance->mInstAlign), (BfAllocFlags)(BfAllocFlags_ZeroMemory | BfAllocFlags_NoDefaultToMalloc)); - else if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule)) + else if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule)) { SizedArray llvmArgs; llvmArgs.push_back(sizeValue); @@ -8937,7 +8959,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget if (result) { - if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) + if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule)) { auto objectPtr = mBfIRBuilder->CreateBitCast(result, mBfIRBuilder->MapTypeInstPtr(mContext->mBfObjectType)); SizedArray llvmArgs; @@ -8970,13 +8992,13 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget else { if ((mBfIRBuilder->mIgnoreWrites) || - ((mCompiler->mIsResolveOnly) && (!mIsConstModule))) + ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule))) return GetDefaultValue(typeInstance); auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef); auto vData = mBfIRBuilder->CreateBitCast(vDataRef, mBfIRBuilder->MapTypeInstPtr(classVDataType->ToTypeInstance())); - if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) + if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule)) { SizedArray llvmArgs; llvmArgs.push_back(vData); @@ -8992,7 +9014,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget SizedArray llvmArgs; llvmArgs.push_back(sizeValue); BfIRFunction irFunc; - if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule)) + if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule)) { auto moduleMethodInstance = GetInternalMethod("Dbg_RawObjectAlloc", 1); irFunc = moduleMethodInstance.mFunc; @@ -9003,7 +9025,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget auto objResult = mBfIRBuilder->CreateBitCast(objectVal, mBfIRBuilder->MapType(mContext->mBfObjectType, BfIRPopulateType_Full)); auto vdataPtr = mBfIRBuilder->CreateInBoundsGEP(objResult, 0, 0); - if (mIsConstModule) + if (mIsComptimeModule) { vdataPtr = mBfIRBuilder->CreateBitCast(vdataPtr, mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapTypeInstPtr(classVDataType->ToTypeInstance()))); } @@ -9216,7 +9238,7 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue, auto curThis = GetThis(); BfIRValue newFlags; - if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) + if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule)) { auto thisFlagsPtr = mBfIRBuilder->CreateBitCast(curThis.mValue, ptrType); auto thisFlags = mBfIRBuilder->CreateLoad(thisFlagsPtr); @@ -9232,7 +9254,7 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue, auto srcVal = mBfIRBuilder->CreateBitCast(vDataRef, ptrType); mBfIRBuilder->CreateStore(srcVal, destAddr); - if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) + if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule)) { auto flagsPtr = mBfIRBuilder->CreateBitCast(destAddr, ptrType); mBfIRBuilder->CreateStore(newFlags, flagsPtr); @@ -9274,7 +9296,7 @@ bool BfModule::WantsLifetimes() bool BfModule::HasCompiledOutput() { - return (!mSystem->mIsResolveOnly) && (mIsReified) && (!mIsConstModule); + return (!mSystem->mIsResolveOnly) && (mIsReified) && (!mIsComptimeModule); } // We will skip the object access check for any occurances of this value @@ -9283,7 +9305,7 @@ void BfModule::SkipObjectAccessCheck(BfTypedValue typedVal) if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck)) return; - if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsConstModule)) + if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsComptimeModule)) return; if ((typedVal.mValue.mFlags & BfIRValueFlags_Value) == 0) @@ -9297,7 +9319,7 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal) if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck)) return; - if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsConstModule)) + if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsComptimeModule)) return; if (typedVal.mValue.IsConst()) @@ -9346,7 +9368,7 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar auto irb = mBfIRBuilder; - if (mIsConstModule) + if (mIsComptimeModule) { auto callResult = mBfIRBuilder->ConstEval_DynamicCastCheck(targetValue.mValue, targetType->mTypeId, mBfIRBuilder->MapType(mContext->mBfObjectType)); auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult, GetDefaultValue(mContext->mBfObjectType)); @@ -9385,7 +9407,7 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar AddBasicBlock(checkBB); BfIRValue vDataPtr = irb->CreateBitCast(targetValue.mValue, irb->MapType(intPtrType)); vDataPtr = irb->CreateLoad(vDataPtr); - if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) + if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule)) vDataPtr = irb->CreateAnd(vDataPtr, irb->CreateConst(BfTypeCode_IntPtr, (uint64)~0xFFULL)); if (targetType->IsInterface()) @@ -9681,7 +9703,7 @@ BfMethodInstance* BfModule::GetRawMethodInstanceAtIdx(BfTypeInstance* typeInstan { if (!typeInstance->mResolvingVarField) { - if (typeInstance->mDefineState < BfTypeDefineState_HasInterfaces) + if (!typeInstance->DefineStateAllowsStaticMethods()) PopulateType(typeInstance, BfPopulateType_AllowStaticMethods); } else @@ -11479,7 +11501,7 @@ BfTypedValue BfModule::AggregateSplat(BfTypedValue typedValue, BfIRValue* valueA { if (!typedValue.IsSplat()) return typedValue; - BF_ASSERT(!mIsConstModule); + BF_ASSERT(!mIsComptimeModule); if (typedValue.mType->IsValuelessType()) return typedValue; @@ -11576,7 +11598,7 @@ void BfModule::AggregateSplatIntoAddr(BfTypedValue typedValue, BfIRValue addrVal if (typedValue.mType->IsValuelessType()) return; - BF_ASSERT(!mIsConstModule); + BF_ASSERT(!mIsComptimeModule); /*static int sCallIdx = 0; if (!mCompiler->mIsResolveOnly) @@ -11702,7 +11724,7 @@ BfTypedValue BfModule::RemoveReadOnly(BfTypedValue typedValue) BfIRValue BfModule::ExtractSplatValue(BfTypedValue typedValue, int componentIdx, BfType* wantType, bool* isAddr) { - BF_ASSERT(!mIsConstModule); + BF_ASSERT(!mIsComptimeModule); BfIRValue val; if (typedValue.mValue.IsArg()) @@ -12435,9 +12457,9 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM { // For autocomplete, we still may not actually generate methods. This shouldn't matter, and on-demand works differently // for resolve-only because we don't differentiate between reified/unreified there - if ((methodDef->mIsStatic) /*&& (mIsConstModule)*/) + if ((methodDef->mIsStatic) /*&& (mIsComptimeModule)*/) { - if (typeInst->mDefineState < BfTypeDefineState_HasInterfaces) + if (!typeInst->DefineStateAllowsStaticMethods()) PopulateType(typeInst, BfPopulateType_AllowStaticMethods); } else @@ -12472,7 +12494,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodInfoEx != NULL) && (mCurMethodInstance->mMethodInfoEx->mMinDependDepth >= 32)) flags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_DepthExceeded); - if ((!mIsConstModule) && (!mIsReified) && (instModule->mIsReified)) + if ((!mIsComptimeModule) && (!mIsReified) && (instModule->mIsReified)) { BF_ASSERT(!mCompiler->mIsResolveOnly); // A resolve-only module is specializing a method from a type in a reified module, @@ -12485,7 +12507,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM } else { - if ((!mIsConstModule) && (mIsReified) && (!instModule->mIsReified)) + if ((!mIsComptimeModule) && (mIsReified) && (!instModule->mIsReified)) { if (!typeInst->IsUnspecializedTypeVariation()) { @@ -12514,7 +12536,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM defFlags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_NoReference); - if (mIsConstModule) + if (mIsComptimeModule) { defFlags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_MethodInstanceOnly); if (!mCompiler->mIsResolveOnly) @@ -13304,9 +13326,9 @@ void BfModule::HadSlotCountDependency() BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str) { - if (str == "#IsConstEval") + if (str == "#IsComptime") { - return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Boolean, mIsConstModule ? 1 : 0), GetPrimitiveType(BfTypeCode_Boolean)); + return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Boolean, mIsComptimeModule ? 1 : 0), GetPrimitiveType(BfTypeCode_Boolean)); } if (str == "#IsBuilding") { @@ -13390,7 +13412,7 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) typeType = typeType->GetUnderlyingType(); } - if (mIsConstModule) + if (mIsComptimeModule) { mCompiler->mCEMachine->QueueStaticField(fieldInstance, staticVarName); } @@ -13854,13 +13876,13 @@ BfLocalVariable* BfModule::AddLocalVariableDef(BfLocalVariable* localVarDef, boo BF_ASSERT(rootMethodState->mCurLocalVarId >= 0); localVarDef->mLocalVarId = rootMethodState->mCurLocalVarId++; } - if ((localVarDef->mNameNode != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) && (!mIsConstModule)) + if ((localVarDef->mNameNode != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) && (!mIsComptimeModule)) mCompiler->mResolvePassData->mAutoComplete->CheckLocalDef(localVarDef->mNameNode, localVarDef); if ((localVarDef->mNameNode != NULL) && (mCurMethodInstance != NULL)) { bool isClosureProcessing = (mCurMethodState->mClosureState != NULL) && (!mCurMethodState->mClosureState->mCapturing); - if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL) && (!mIsConstModule)) + if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL) && (!mIsComptimeModule)) mCompiler->mResolvePassData->HandleLocalReference(localVarDef->mNameNode, rootMethodState->mMethodInstance->GetOwner()->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVarDef->mLocalVarId); } @@ -13882,7 +13904,7 @@ void BfModule::CreateDIRetVal() { BfType* dbgType = mCurMethodInstance->mReturnType; BfIRValue dbgValue = mCurMethodState->mRetVal.mValue; - if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) + if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) { BF_ASSERT(mCurMethodState->mRetValAddr); dbgType = CreatePointerType(dbgType); @@ -14521,7 +14543,7 @@ void BfModule::MarkScopeLeft(BfScopeData* scopeData) void BfModule::CreateReturn(BfIRValue val) { - if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) + if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) { // Store to sret BF_ASSERT(val); @@ -14540,7 +14562,7 @@ void BfModule::CreateReturn(BfIRValue val) { BfTypeCode loweredReturnType = BfTypeCode_None; BfTypeCode loweredReturnType2 = BfTypeCode_None; - if (!mIsConstModule) + if (!mIsComptimeModule) mCurMethodInstance->GetLoweredReturnType(&loweredReturnType, &loweredReturnType2); if (loweredReturnType != BfTypeCode_None) @@ -14577,7 +14599,7 @@ void BfModule::EmitReturn(const BfTypedValue& val) mBfIRBuilder->CreateStore(val.mValue, retVal); } - else if (mIsConstModule) + else if (mIsComptimeModule) { mBfIRBuilder->CreateSetRet(val.mValue, val.mType->mTypeId); } @@ -14620,7 +14642,7 @@ void BfModule::EmitDefaultReturn() { if (mCurMethodInstance->mReturnType->IsVoid()) mBfIRBuilder->CreateRetVoid(); - else if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() == -1)) + else if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() == -1)) mBfIRBuilder->CreateRet(GetDefaultValue(mCurMethodInstance->mReturnType)); } @@ -14729,18 +14751,18 @@ void BfModule::CreateDelegateInvokeMethod() if (mCurMethodInstance->mReturnType->IsValueType()) mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType, BfIRPopulateType_Full); - if ((mIsConstModule) || (mCurMethodInstance->GetStructRetIdx() != 0)) + if ((mIsComptimeModule) || (mCurMethodInstance->GetStructRetIdx() != 0)) memberFuncArgs.push_back(BfIRValue()); // Push 'target' int thisIdx = 0; - if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) + if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) { thisIdx = mCurMethodInstance->GetStructRetIdx() ^ 1; staticFuncArgs.push_back(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx())); memberFuncArgs.push_back(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx())); } - if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() == 0)) + if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() == 0)) memberFuncArgs.push_back(BfIRValue()); // Push 'target' mCurMethodInstance->GetIRFunctionInfo(this, origReturnType, staticParamTypes, true); @@ -14779,7 +14801,7 @@ void BfModule::CreateDelegateInvokeMethod() auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, memberFuncPtrPtr); auto funcPtr = mBfIRBuilder->CreateLoad(funcPtrPtr); nonStaticResult = mBfIRBuilder->CreateCall(funcPtr, memberFuncArgs); - if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) + if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) mBfIRBuilder->Call_AddAttribute(nonStaticResult, mCurMethodInstance->GetStructRetIdx() + 1, BfIRAttribute_StructRet); if (callingConv != BfIRCallingConv_CDecl) mBfIRBuilder->SetCallCallingConv(nonStaticResult, callingConv); @@ -14797,7 +14819,7 @@ void BfModule::CreateDelegateInvokeMethod() auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, staticFuncPtrPtr); auto funcPtr = mBfIRBuilder->CreateLoad(funcPtrPtr); staticResult = mBfIRBuilder->CreateCall(funcPtr, staticFuncArgs); - if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) + if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) { // Note: since this is a forced static invocation, we know the sret will be the first parameter mBfIRBuilder->Call_AddAttribute(staticResult, 0 + 1, BfIRAttribute_StructRet); @@ -14815,7 +14837,7 @@ void BfModule::CreateDelegateInvokeMethod() mBfIRBuilder->AddBlock(doneBB); mBfIRBuilder->SetInsertPoint(doneBB); if ((mCurMethodInstance->mReturnType->IsValuelessType()) || - ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))) + ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1))) { mBfIRBuilder->CreateRetVoid(); } @@ -14824,7 +14846,7 @@ void BfModule::CreateDelegateInvokeMethod() BfIRType loweredIRReturnType; BfTypeCode loweredTypeCode = BfTypeCode_None; BfTypeCode loweredTypeCode2 = BfTypeCode_None; - if ((!mIsConstModule) && (mCurMethodInstance->GetLoweredReturnType(&loweredTypeCode, &loweredTypeCode2))) + if ((!mIsComptimeModule) && (mCurMethodInstance->GetLoweredReturnType(&loweredTypeCode, &loweredTypeCode2))) loweredIRReturnType = GetIRLoweredType(loweredTypeCode, loweredTypeCode2); else loweredIRReturnType = mBfIRBuilder->MapType(mCurMethodInstance->mReturnType); @@ -14875,7 +14897,7 @@ BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArr BF_ASSERT(methodInst->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend); - if ((mCompiler->mIsResolveOnly) && (!mIsConstModule)) + if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule)) return BfTypedValue(); // We want to regenerate all ctor calls when the method internals change @@ -14906,7 +14928,7 @@ BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArr int argCount = 0; if (!paramType->IsValuelessType()) { - if ((!mIsConstModule) && (methodInst->GetParamIsSplat(paramIdx))) + if ((!mIsComptimeModule) && (methodInst->GetParamIsSplat(paramIdx))) argCount = paramType->GetSplatCount(); else argCount = 1; @@ -15164,7 +15186,7 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly) // This method never throws errors - it relies on the proper ctor actually throwing the errors void BfModule::EmitCtorCalcAppend() { - if ((mCompiler->mIsResolveOnly) && (!mIsConstModule)) + if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule)) return; auto methodDef = mCurMethodInstance->mMethodDef; @@ -15310,7 +15332,7 @@ void BfModule::EmitDtorBody() // Fall through to Object::~this call auto dtorFunc = GetMethodByName(mContext->mBfObjectType, "~this"); - if (mIsConstModule) + if (mIsComptimeModule) mCompiler->mCEMachine->QueueMethod(dtorFunc.mMethodInstance, dtorFunc.mFunc); auto basePtr = mBfIRBuilder->CreateBitCast(thisVal.mValue, mBfIRBuilder->MapTypeInstPtr(mContext->mBfObjectType)); SizedArray vals = { basePtr }; @@ -15488,7 +15510,7 @@ void BfModule::EmitDtorBody() auto basePtr = mBfIRBuilder->CreateBitCast(mCurMethodState->mLocals[0]->mValue, mBfIRBuilder->MapTypeInstPtr(checkBaseType)); SizedArray vals = { basePtr }; auto callInst = mBfIRBuilder->CreateCall(dtorMethodInstance.mFunc, vals); - if (mIsConstModule) + if (mIsComptimeModule) mCompiler->mCEMachine->QueueMethod(dtorMethodInstance.mMethodInstance, dtorMethodInstance.mFunc); mBfIRBuilder->SetCallCallingConv(callInst, GetIRCallingConvention(dtorMethodInstance.mMethodInstance)); } @@ -15747,7 +15769,7 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func while (argIdx < argCount) { - if ((!mIsConstModule) && (argIdx == methodInstance->GetStructRetIdx())) + if ((!mIsComptimeModule) && (argIdx == methodInstance->GetStructRetIdx())) { mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_NoAlias); mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_StructRet); @@ -15763,7 +15785,7 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func BfType* resolvedTypeRef2 = NULL; String paramName; bool isSplattable = false; - bool tryLowering = !mIsConstModule; + bool tryLowering = !mIsComptimeModule; if (isThis) { paramName = "this"; @@ -15771,8 +15793,8 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func resolvedTypeRef = mCurMethodState->mClosureState->mClosureType; else resolvedTypeRef = methodInstance->GetThisType(); - isSplattable = (!mIsConstModule) && (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsSplatting(-1)); - tryLowering = (!mIsConstModule) && (methodInstance->AllowsSplatting(-1)); + isSplattable = (!mIsComptimeModule) && (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsSplatting(-1)); + tryLowering = (!mIsComptimeModule) && (methodInstance->AllowsSplatting(-1)); } else { @@ -15780,7 +15802,7 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func resolvedTypeRef = methodInstance->GetParamType(paramIdx); if (resolvedTypeRef->IsMethodRef()) isSplattable = true; - else if ((!mIsConstModule) && (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsSplatting(paramIdx))) + else if ((!mIsComptimeModule) && (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsSplatting(paramIdx))) { auto resolvedTypeInst = resolvedTypeRef->ToTypeInstance(); if ((resolvedTypeInst != NULL) && (resolvedTypeInst->mIsCRepr)) @@ -16069,7 +16091,7 @@ void BfModule::EmitCtorBody(bool& skipBody) SizedArray irArgs; exprEvaluator.PushThis(NULL, GetThis(), moduleMethodInstance.mMethodInstance, irArgs); exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs); - if (mIsConstModule) + if (mIsComptimeModule) mCompiler->mCEMachine->QueueMethod(moduleMethodInstance); calledCtorNoBody = true; @@ -16412,7 +16434,7 @@ void BfModule::EmitCtorBody(bool& skipBody) auto callingConv = GetIRCallingConvention(ctorBodyMethodInstance.mMethodInstance); if (callingConv != BfIRCallingConv_CDecl) mBfIRBuilder->SetCallCallingConv(callInst, callingConv); - if (mIsConstModule) + if (mIsComptimeModule) mCompiler->mCEMachine->QueueMethod(ctorBodyMethodInstance); } @@ -16962,7 +16984,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp int argIdx = 0; - if ((!mIsConstModule) && (argIdx == methodInstance->GetStructRetIdx())) + if ((!mIsComptimeModule) && (argIdx == methodInstance->GetStructRetIdx())) argIdx++; if (!methodDef->mIsStatic) @@ -16978,12 +17000,12 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp else paramVar->mValue = mBfIRBuilder->GetFakeVal(); - if ((!mIsConstModule) && (thisType->IsSplattable()) && (methodInstance->AllowsSplatting(-1))) + if ((!mIsComptimeModule) && (thisType->IsSplattable()) && (methodInstance->AllowsSplatting(-1))) { if (!thisType->IsTypedPrimitive()) paramVar->mIsSplat = true; } - else if ((!mIsConstModule) && (!methodDef->mIsMutating) && (methodInstance->mCallingConvention == BfCallingConvention_Unspecified)) + else if ((!mIsComptimeModule) && (!methodDef->mIsMutating) && (methodInstance->mCallingConvention == BfCallingConvention_Unspecified)) paramVar->mIsLowered = thisType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2) != BfTypeCode_None; auto thisTypeInst = thisType->ToTypeInstance(); @@ -17032,7 +17054,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp } } - if ((!mIsConstModule) && (argIdx == methodInstance->GetStructRetIdx())) + if ((!mIsComptimeModule) && (argIdx == methodInstance->GetStructRetIdx())) argIdx++; bool hadParams = false; @@ -17070,7 +17092,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp { paramVar->mIsSplat = true; } - else if ((!mIsConstModule) && (resolvedType->IsComposite()) && (resolvedType->IsSplattable())) + else if ((!mIsComptimeModule) && (resolvedType->IsComposite()) && (resolvedType->IsSplattable())) { if (methodInstance->AllowsSplatting(paramIdx)) { @@ -17092,7 +17114,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp paramVar->mValue = mBfIRBuilder->GetFakeVal(); } - paramVar->mIsLowered = (!mIsConstModule) && resolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2) != BfTypeCode_None; + paramVar->mIsLowered = (!mIsComptimeModule) && resolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2) != BfTypeCode_None; paramVar->mIsStruct = resolvedType->IsComposite() && !resolvedType->IsTypedPrimitive(); paramVar->mParamIdx = paramIdx; paramVar->mIsImplicitParam = methodInstance->IsImplicitCapture(paramIdx); @@ -17641,7 +17663,7 @@ void BfModule::EmitGCMarkMembers() auto baseValue = Cast(NULL, thisValue, methodBaseType, BfCastFlags_Explicit); SizedArray args; - if ((!mIsConstModule) && (moduleMethodInst.mMethodInstance->GetParamIsSplat(-1))) + if ((!mIsComptimeModule) && (moduleMethodInst.mMethodInstance->GetParamIsSplat(-1))) { BfExprEvaluator exprEvaluator(this); exprEvaluator.SplatArgs(baseValue, args); @@ -17839,7 +17861,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) BfMethodInstance* defaultMethodInstance = methodInstance->mMethodInstanceGroup->mDefault; - if (!mIsConstModule) + if (!mIsComptimeModule) { BF_ASSERT(methodInstance->mMethodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_NotSet); @@ -17890,7 +17912,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) SetAndRestoreValue prevFilePos(mCurFilePosition); SetAndRestoreValue prevHadBuildError(mHadBuildError, false); SetAndRestoreValue prevHadWarning(mHadBuildWarning, false); - SetAndRestoreValue prevIgnoreWarnings(mIgnoreWarnings, mIsConstModule); + SetAndRestoreValue prevIgnoreWarnings(mIgnoreWarnings, mIsComptimeModule); if ((methodInstance->mIsReified) && ((methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_CtorNoBody))) @@ -17905,7 +17927,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) if ((methodDeclaration == NULL) && (mCurMethodState == NULL)) UseDefaultSrcPos(); - if ((mIsConstModule) && (methodDef->mIsStatic)) + if ((mIsComptimeModule) && (methodDef->mIsStatic)) { PopulateType(mCurTypeInstance, BfPopulateType_AllowStaticMethods); } @@ -18048,7 +18070,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) if (mCurMethodState == NULL) // Only do initial classify for the 'outer' method state, not any local methods or lambdas { - if ((mCompiler->mIsResolveOnly) && (!mIsConstModule) && (methodDef->mBody != NULL) && (!mCurTypeInstance->IsBoxed()) && + if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (methodDef->mBody != NULL) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mBody->IsFromParser(mCompiler->mResolvePassData->mParser)) && (mCompiler->mResolvePassData->mSourceClassifier != NULL)) { mCompiler->mResolvePassData->mSourceClassifier->VisitChildNoRef(methodDef->mBody); @@ -18098,27 +18120,27 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } else if ((((methodInstance->mMethodInfoEx != NULL) && ((int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size() > dependentGenericStartIdx)) || ((mCurTypeInstance->IsGenericTypeInstance()) && (!isGenericVariation) && (!methodInstance->mMethodDef->mIsLocalMethod)))) - { + { unspecializedMethodInstance = GetUnspecializedMethodInstance(methodInstance, !methodInstance->mMethodDef->mIsLocalMethod); - - BF_ASSERT(unspecializedMethodInstance != methodInstance); - if (!unspecializedMethodInstance->mHasBeenProcessed) + + if ((mIsComptimeModule) && (!unspecializedMethodInstance->mHasBeenProcessed)) { - if (mIsConstModule) + // This will have already been populated by CeMachine + methodState.mGenericTypeBindings = &methodInstance->GetMethodInfoEx()->mGenericTypeBindings; + } + else + { + BF_ASSERT(unspecializedMethodInstance != methodInstance); + if (!unspecializedMethodInstance->mHasBeenProcessed) { - // This will have already been populated by CeMachine - methodState.mGenericTypeBindings = &methodInstance->GetMethodInfoEx()->mGenericTypeBindings; - } - else - { // Make sure the unspecialized method is processed so we can take its bindings // Clear mCurMethodState so we don't think we're in a local method SetAndRestoreValue prevMethodState_Unspec(mCurMethodState, prevMethodState.mPrevVal); mContext->ProcessMethod(unspecializedMethodInstance); } + methodState.mGenericTypeBindings = &unspecializedMethodInstance->GetMethodInfoEx()->mGenericTypeBindings; } - methodState.mGenericTypeBindings = &unspecializedMethodInstance->GetMethodInfoEx()->mGenericTypeBindings; } if (methodDef->mMethodType == BfMethodType_Operator) @@ -18315,7 +18337,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) else { if ((mCurTypeInstance->IsValuelessType()) || - ((!mIsConstModule) && (mCurTypeInstance->IsSplattable()))) + ((!mIsComptimeModule) && (mCurTypeInstance->IsSplattable()))) flags |= llvm::DINode::FlagStaticMember; } flags |= llvm::DINode::FlagPrototyped; @@ -18465,7 +18487,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) if ((isThis) && (thisType->IsValuelessType())) isThis = false; - if ((!mIsConstModule) && (methodInstance->GetStructRetIdx() == argIdx)) + if ((!mIsComptimeModule) && (methodInstance->GetStructRetIdx() == argIdx)) { argIdx++; if (argIdx == irParamCount) @@ -18489,7 +18511,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } bool wantsAddr = (wantsDIVariables) || (!paramVar->mIsReadOnly) || - ((!mIsConstModule) && (paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter))); + ((!mIsComptimeModule) && (paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter))); if (paramVar->mResolvedType->IsMethodRef()) wantsAddr = false; @@ -18630,7 +18652,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) int splatAddrIdx = 0; while (localIdx < (int)methodState.mLocals.size()) { - if ((!mIsConstModule) && (argIdx == methodInstance->GetStructRetIdx())) + if ((!mIsComptimeModule) && (argIdx == methodInstance->GetStructRetIdx())) argIdx++; int curLocalIdx = localIdx++; @@ -19007,7 +19029,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) skipBody = true; skipEndChecks = true; - if ((HasCompiledOutput()) || (mIsConstModule)) + if ((HasCompiledOutput()) || (mIsComptimeModule)) { // Clear out DebugLoc - to mark the ".addr" code as part of prologue mBfIRBuilder->ClearDebugLocation(); @@ -19066,7 +19088,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) { BF_ASSERT(innerType->IsUnspecializedType()); } - else if ((!mIsConstModule) && (methodInstance->GetStructRetIdx() != -1)) + else if ((!mIsComptimeModule) && (methodInstance->GetStructRetIdx() != -1)) { mBfIRBuilder->PopulateType(methodInstance->mReturnType); auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()), methodInstance->mReturnType, true); @@ -19133,7 +19155,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) if (customAttributes->Contains(mCompiler->mDisableObjectAccessChecksAttributeTypeDef)) mCurMethodState->mIgnoreObjectAccessCheck = true; if (customAttributes->Contains(mCompiler->mDisableChecksAttributeTypeDef)) - mCurMethodState->mDisableChecks = true; + mCurMethodState->mDisableChecks = true; } if ((methodDef->mMethodType == BfMethodType_CtorNoBody) && (!methodDef->mIsStatic) && @@ -19275,7 +19297,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) else if ((mCurTypeInstance->IsEnum()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING)) { auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef); - if ((HasCompiledOutput()) || (mIsConstModule)) + if ((HasCompiledOutput()) || (mIsComptimeModule)) { EmitEnumToStringBody(); } @@ -19288,7 +19310,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) else if ((mCurTypeInstance->IsTuple()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING)) { auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef); - if ((HasCompiledOutput()) || (mIsConstModule)) + if ((HasCompiledOutput()) || (mIsComptimeModule)) { EmitTupleToStringBody(); } @@ -19330,7 +19352,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) { mBfIRBuilder->CreateRetVoid(); } - else if ((HasCompiledOutput()) || (mIsConstModule)) + else if ((HasCompiledOutput()) || (mIsComptimeModule)) { String autoPropName = typeDef->GetAutoPropertyName(propertyDeclaration); BfFieldInstance* fieldInstance = GetFieldByName(mCurTypeInstance, autoPropName); @@ -19439,7 +19461,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) bool isEmptyBodied = BfNodeDynCast(methodDef->mBody) != NULL; bool wantsRetVal = true; - if ((mIsConstModule) && (methodDef->mMethodType != BfMethodType_CtorCalcAppend)) + if ((mIsComptimeModule) && (methodDef->mMethodType != BfMethodType_CtorCalcAppend)) wantsRetVal = false; else if (mCurMethodInstance->mReturnType->IsVar()) wantsRetVal = false; @@ -19448,7 +19470,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) { mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType); - if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) + if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) { auto ptrType = CreatePointerType(mCurMethodInstance->mReturnType); auto allocaInst = AllocLocalVariable(ptrType, "__return.addr", false); @@ -19646,7 +19668,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) if (mCurMethodState->mIRExitBlock) { if ((mCurMethodState->mRetVal) && - ((mIsConstModule) || (mCurMethodInstance->GetStructRetIdx() == -1))) + ((mIsComptimeModule) || (mCurMethodInstance->GetStructRetIdx() == -1))) { auto loadedVal = mBfIRBuilder->CreateLoad(mCurMethodState->mRetVal.mValue); @@ -19685,7 +19707,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) { if ((!mCurMethodState->mHadReturn) && (!mCurMethodState->mIRExitBlock)) { - if ((!mIsConstModule) && (irParamCount == 0) && (!IsTargetingBeefBackend()) && (mCompiler->mOptions.mAllowHotSwapping)) + if ((!mIsComptimeModule) && (irParamCount == 0) && (!IsTargetingBeefBackend()) && (mCompiler->mOptions.mAllowHotSwapping)) { // This may be a case where we only emit 4 bytes, whereas we need 5 for a hot replace jump mBfIRBuilder->EnsureFunctionPatchable(); @@ -20750,7 +20772,7 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance) methodInstance->mCallingConvention = methodDef->mCallingConvention; if (customAttributes != NULL) { - auto linkNameAttr = customAttributes->Get(typeInstance->mModule->mCompiler->mCallingConventionAttributeTypeDef); + auto linkNameAttr = customAttributes->Get(mCompiler->mCallingConventionAttributeTypeDef); if (linkNameAttr != NULL) { if (linkNameAttr->mCtorArgs.size() == 1) @@ -20760,6 +20782,30 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance) methodInstance->mCallingConvention = (BfCallingConvention)constant->mInt32; } } + + if (methodDef->mHasComptime) + methodInstance->mComptimeFlags = BfComptimeFlag_Comptime; + + auto comptimeAttr = customAttributes->Get(mCompiler->mComptimeAttributeTypeDef); + if (comptimeAttr != NULL) + { + for (auto setProp : comptimeAttr->mSetProperties) + { + BfPropertyDef* propertyDef = setProp.mPropertyRef; + if (propertyDef->mName == "OnlyFromComptime") + { + auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue); + if ((constant != NULL) && (constant->mBool)) + methodInstance->mComptimeFlags = (BfComptimeFlags)(methodInstance->mComptimeFlags | BfComptimeFlag_OnlyFromComptime); + } + else if (propertyDef->mName == "ConstEval") + { + auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue); + if ((constant != NULL) && (constant->mBool)) + methodInstance->mComptimeFlags = (BfComptimeFlags)(methodInstance->mComptimeFlags | BfComptimeFlag_ConstEval); + } + } + } } } @@ -20843,7 +20889,7 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man if (!mCurMethodInstance->mIRFunction) { BfLogSysM("Function collision from inner override erased prevFunc %p: %d\n", methodInstance, prevFunc.mId); - if (!mIsConstModule) + if (!mIsComptimeModule) mBfIRBuilder->Func_SafeRename(prevFunc); } } @@ -20857,7 +20903,7 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man // We can have a collision of names when we have generic methods that differ only in // their constraints, but they should only collide in their unspecialized form // since only one will be chosen for a given concrete type - if (!mIsConstModule) + if (!mIsComptimeModule) mCurMethodInstance->mMangleWithIdx = true; mangledName.Clear(); BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), mCurMethodInstance); @@ -20868,7 +20914,7 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man else { BfLogSysM("Function collision erased prevFunc %p: %d\n", methodInstance, prevFunc.mId); - if (!mIsConstModule) + if (!mIsComptimeModule) mBfIRBuilder->Func_SafeRename(prevFunc); } } @@ -21383,7 +21429,7 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric); - if ((methodDef->mIsConstEval) && (methodDef->mReturnTypeRef->IsA())) + if (((methodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) && (methodDef->mReturnTypeRef->IsA())) resolvedReturnType = GetPrimitiveType(BfTypeCode_Var); else resolvedReturnType = ResolveTypeRef(methodDef->mReturnTypeRef, BfPopulateType_Declaration, flags); @@ -21794,7 +21840,7 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); { BfTypeCode loweredTypeCode = BfTypeCode_None; BfTypeCode loweredTypeCode2 = BfTypeCode_None; - if ((!mIsConstModule) && (!methodDef->mIsMutating)) + if ((!mIsComptimeModule) && (!methodDef->mIsMutating)) thisType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2); argIdx++; if (loweredTypeCode2 != BfTypeCode_None) @@ -21802,7 +21848,7 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); } } - if ((!mIsConstModule) && (methodInstance->GetStructRetIdx() != -1)) + if ((!mIsComptimeModule) && (methodInstance->GetStructRetIdx() != -1)) argIdx++; for (int paramIdx = 0; paramIdx < mCurMethodInstance->mParams.size(); paramIdx++) @@ -21844,7 +21890,7 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); { BfTypeCode loweredTypeCode = BfTypeCode_None; BfTypeCode loweredTypeCode2 = BfTypeCode_None; - if (!mIsConstModule) + if (!mIsComptimeModule) checkType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2); argIdx++; if (loweredTypeCode2 != BfTypeCode_None) @@ -22981,7 +23027,7 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo if ((iMethodPtr->mKind != BfMethodRefKind_AmbiguousRef) && (iMethodPtr->mTypeInstance != NULL)) { auto prevMethod = (BfMethodInstance*)*iMethodPtr; - if ((mCompiler->mIsResolveOnly) && (prevMethod == methodInstance) && (!mIsConstModule)) + if ((mCompiler->mIsResolveOnly) && (prevMethod == methodInstance) && (!mIsComptimeModule)) { // When autocompletion regenerates a single method body but not the whole type then // we will see ourselves in the vtable already diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index a7308a44..ba092707 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -32,6 +32,7 @@ NS_BF_BEGIN class BfType; class BfResolvedType; class BfExprEvaluator; +class CeEmitContext; enum BfPopulateType { @@ -71,7 +72,7 @@ enum BfEvalExprFlags BfEvalExprFlags_AllowNonConst = 0x10000, BfEvalExprFlags_StringInterpolateFormat = 0x20000, BfEvalExprFlags_NoLookupError = 0x40000, - BfEvalExprFlags_ConstEval = 0x80000, + BfEvalExprFlags_Comptime = 0x80000, BfEvalExprFlags_InCascade = 0x100000, }; @@ -1450,7 +1451,7 @@ public: bool mWantsIRIgnoreWrites; bool mHasGenericMethods; bool mIsSpecialModule; // vdata, unspecialized, external - bool mIsConstModule; + bool mIsComptimeModule; bool mIsScratchModule; bool mIsSpecializedMethodModuleRoot; bool mIsModuleMutable; // Set to false after writing module to disk, can be set back to true after doing extension module @@ -1686,6 +1687,7 @@ public: BfInternalAccessSet* GetInternalAccessSet(); bool CheckInternalProtection(BfTypeDef* usingTypeDef); void AddFailType(BfTypeInstance* typeInstance); + void DeferRebuildType(BfTypeInstance* typeInstance); void MarkDerivedDirty(BfTypeInstance* typeInst); void CheckAddFailType(); void PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data); @@ -1695,6 +1697,9 @@ public: void SetTypeOptions(BfTypeInstance* typeInstance); BfModuleOptions GetModuleOptions(); BfCheckedKind GetDefaultCheckedKind(); + void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& ctxString, BfAstNode* refNode); + void ExecuteCEOnCompile(BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, CeEmitContext* ceEmitContext); + void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers); void DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data); static BfModule* GetModuleFor(BfType* type); void DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 02ebd335..05613369 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -3,6 +3,7 @@ #include "BfCompiler.h" #include "BfSystem.h" #include "BfParser.h" +#include "BfReducer.h" #include "BfCodeGen.h" #include "BfExprEvaluator.h" #include @@ -17,6 +18,7 @@ #include "BfFixits.h" #include "BfIRCodeGen.h" #include "BfDefBuilder.h" +#include "CeMachine.h" ////////////////////////////////////////////////////////////////////////// @@ -1931,6 +1933,177 @@ void BfModule::SetTypeOptions(BfTypeInstance* typeInstance) typeInstance->mTypeOptionsIdx = GenerateTypeOptions(typeInstance->mCustomAttributes, typeInstance, true); } +void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* activeTypeDef, const StringImpl& ctxString, BfAstNode* refNode) +{ + if (ceEmitContext->mEmitData.IsEmpty()) + return; + + int prevFailIdx = mCompiler->mPassInstance->mFailedIdx; + int prevWarnIdx = mCompiler->mPassInstance->mWarnIdx; + + String src; + + if (activeTypeDef->mEmitParser != NULL) + src += "\n\n"; + + src += "// Code emission in "; + src += ctxString; + src += "\n\n"; + src += ceEmitContext->mEmitData; + ceEmitContext->mEmitData.Clear(); + + int startSrcIdx = 0; + if (activeTypeDef->mEmitParser == NULL) + { + BfParser* parser = new BfParser(mSystem, typeInstance->mTypeDef->mProject); + parser->mIsEmitted = true; + parser->mFileName = typeInstance->mTypeDef->mName->ToString(); + + BfLogSys(mSystem, "CreateParser (emit): %p\n", parser); + + if (mCompiler->mIsResolveOnly) + parser->mFileName += "$EmitR$"; + else + parser->mFileName += "$Emit$"; + + parser->mFileName += StrFormat("%d", typeInstance->mTypeId); + if (activeTypeDef->mPartialIdx != -1) + parser->mFileName + StrFormat(":%d", activeTypeDef->mPartialIdx); + + parser->mFileName += StrFormat(".bf|%d", typeInstance->mRevision); + activeTypeDef->mEmitParser = parser; + parser->mRefCount++; + parser->SetSource(src.c_str(), src.mLength); + } + else + { + int idx = activeTypeDef->mEmitParser->AllocChars(src.mLength + 1); + memcpy((uint8*)activeTypeDef->mEmitParser->mSrc + idx, src.c_str(), src.mLength + 1); + activeTypeDef->mEmitParser->mSrcIdx = idx; + activeTypeDef->mEmitParser->mSrcLength = idx + src.mLength; + activeTypeDef->mEmitParser->mParserData->mSrcLength = activeTypeDef->mEmitParser->mSrcLength; + } + + activeTypeDef->mEmitParser->Parse(mCompiler->mPassInstance); + activeTypeDef->mEmitParser->FinishSideNodes(); + + auto typeDeclaration = activeTypeDef->mEmitParser->mAlloc->Alloc(); + + BfReducer bfReducer; + bfReducer.mSource = activeTypeDef->mEmitParser; + bfReducer.mPassInstance = mCompiler->mPassInstance; + bfReducer.mAlloc = activeTypeDef->mEmitParser->mAlloc; + bfReducer.mSystem = mSystem; + bfReducer.mCurTypeDecl = typeDeclaration; + typeDeclaration->mDefineNode = activeTypeDef->mEmitParser->mRootNode; + bfReducer.HandleTypeDeclaration(typeDeclaration, NULL); + + BfDefBuilder defBuilder(mSystem); + defBuilder.mCurTypeDef = typeInstance->mTypeDef; + defBuilder.DoVisitChild(typeDeclaration->mDefineNode); + defBuilder.FinishTypeDef(typeInstance->mTypeDef->mTypeCode == BfTypeCode_Enum); + + // + { + AutoCrit crit(mSystem->mDataLock); + mSystem->mParsers.Add(activeTypeDef->mEmitParser); + } + + if ((prevFailIdx != mCompiler->mPassInstance->mFailedIdx) && (refNode != NULL)) + Fail("Emitted code had errors", refNode); + else if ((prevWarnIdx != mCompiler->mPassInstance->mWarnIdx) && (refNode != NULL)) + Warn(0, "Emitted code had warnings", refNode); + else if ((prevFailIdx != mCompiler->mPassInstance->mFailedIdx) || + (prevWarnIdx != mCompiler->mPassInstance->mWarnIdx)) + { + AddFailType(typeInstance); + } +} + +void BfModule::ExecuteCEOnCompile(BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind, CeEmitContext* ceEmitContext) +{ + if (!typeInstance->mTypeDef->mHasCEOnCompile) + return; + + int methodCount = (int)typeInstance->mTypeDef->mMethods.size(); + for (int methodIdx = 0; methodIdx < methodCount; methodIdx++) + { + auto methodDef = typeInstance->mTypeDef->mMethods[methodIdx]; + auto methodDeclaration = BfNodeDynCast(methodDef->mMethodDeclaration); + if (methodDeclaration == NULL) + continue; + if (methodDeclaration->mAttributes == NULL) + continue; + auto customAttributes = GetCustomAttributes(methodDeclaration->mAttributes, BfAttributeTargets_Method); + defer({ delete customAttributes; }); + + auto onCompileAttribute = customAttributes->Get(mCompiler->mOnCompileAttributeTypeDef); + if (onCompileAttribute == NULL) + continue; + + if (onCompileAttribute->mCtorArgs.size() < 1) + continue; + auto constant = typeInstance->mConstHolder->GetConstant(onCompileAttribute->mCtorArgs[0]); + if (constant == NULL) + continue; + if (onCompileKind != (BfCEOnCompileKind)constant->mInt32) + continue; + + if (!methodDef->mIsStatic) + { + Fail("OnCompile methods must be static", methodDeclaration); + continue; + } + + if (!methodDef->mParams.IsEmpty()) + { + Fail("OnCompile methods cannot declare parameters", methodDeclaration); + continue; + } + + SetAndRestoreValue prevEmitContext(mCompiler->mCEMachine->mCurEmitContext); + + if (onCompileKind == BfCEOnCompileKind_TypeInit) + { + mCompiler->mCEMachine->mCurEmitContext = ceEmitContext; + } + + auto methodInstance = GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx); + auto result = mCompiler->mCEMachine->Call(methodDef->GetRefNode(), this, methodInstance, {}, (CeEvalFlags)(CeEvalFlags_PersistantError | CeEvalFlags_DeferIfNotOnlyError), NULL); + + if (!ceEmitContext->mEmitData.IsEmpty()) + { + String ctxStr = "OnCompile execution of "; + ctxStr += MethodToString(methodInstance); + UpdateCEEmit(ceEmitContext, typeInstance, methodInstance->mMethodDef->mDeclaringType, ctxStr, methodInstance->mMethodDef->GetRefNode()); + } + + if (mCompiler->mCanceling) + { + DeferRebuildType(typeInstance); + } + } +} + +void BfModule::DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers) +{ + typeInstance->mTypeDef->ClearEmitted(); + + int startMethodCount = typeInstance->mTypeDef->mMethods.mSize; + int startFieldCount = typeInstance->mTypeDef->mFields.mSize; + + CeEmitContext emitContext; + emitContext.mType = typeInstance; + ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeInit, &emitContext); + + if ((startMethodCount != typeInstance->mTypeDef->mMethods.mSize) || + (startFieldCount != typeInstance->mTypeDef->mFields.mSize)) + { + typeInstance->mTypeDef->ClearMemberSets(); + hadNewMembers = true; + } +} + void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType) { auto typeInstance = resolvedTypeRef->ToTypeInstance(); @@ -1991,7 +2164,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy resolvedTypeRef->mSize = typeInstance->mAlign = mSystem->mPtrSize; } - BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size())); + BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size()) || (typeInstance->mTypeDef->mHasEmitMembers)); typeInstance->mMethodInstanceGroups.Resize(typeDef->mMethods.size()); for (int i = 0; i < (int)typeInstance->mMethodInstanceGroups.size(); i++) { @@ -2807,9 +2980,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy BF_ASSERT(!typeInstance->mNeedsMethodProcessing); if (typeInstance->mDefineState < BfTypeDefineState_HasInterfaces) typeInstance->mDefineState = BfTypeDefineState_HasInterfaces; - + for (auto& validateEntry : deferredTypeValidateList) - { + { SetAndRestoreValue ignoreErrors(mIgnoreErrors, mIgnoreErrors | validateEntry.mIgnoreErrors); ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false); } @@ -2858,7 +3031,28 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (typeInstance->mTypeOptionsIdx == -2) SetTypeOptions(typeInstance); - + +// if (typeInstance->mDefineState == BfTypeDefineState_CETypeInit) +// { +// if (populateType <= BfPopulateType_AllowStaticMethods) +// return; +// +// auto refNode = typeDef->GetRefNode(); +// Fail("OnCompile const evaluation creates a data dependency during TypeInit", refNode); +// mCompiler->mCEMachine->Fail("OnCompile const evaluation creates a data dependency during TypeInit"); +// } +// else if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) +// { +// typeInstance->mDefineState = BfTypeDefineState_CETypeInit; +// ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeInit); +// +// if (_CheckTypeDone()) +// return; +// +// if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) +// typeInstance->mDefineState = BfTypeDefineState_CEPostTypeInit; +// } + if (populateType <= BfPopulateType_AllowStaticMethods) return; @@ -3156,6 +3350,44 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy } } } + + if (typeInstance->mDefineState == BfTypeDefineState_CETypeInit) + { + if (populateType <= BfPopulateType_AllowStaticMethods) + return; + + String error = "OnCompile const evaluation creates a data dependency during TypeInit"; + if (mCompiler->mCEMachine->mCurBuilder != NULL) + { + error += StrFormat(" during const-eval generation of '%s'", MethodToString(mCompiler->mCEMachine->mCurBuilder->mCeFunction->mMethodInstance).c_str()); + } + + auto refNode = typeDef->GetRefNode(); + Fail(error, refNode); + if (mCompiler->mCEMachine->mCurFrame != NULL) + mCompiler->mCEMachine->Fail(*mCompiler->mCEMachine->mCurFrame, error); + else + mCompiler->mCEMachine->Fail(error); + } + else if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) + { + typeInstance->mDefineState = BfTypeDefineState_CETypeInit; + bool hadNewMembers = false; + DoCEEmit(typeInstance, hadNewMembers); + + if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) + typeInstance->mDefineState = BfTypeDefineState_CEPostTypeInit; + + if (hadNewMembers) + { + typeInstance->mTypeDef->mHasEmitMembers = true; + DoPopulateType(resolvedTypeRef, populateType); + return; + } + + if (_CheckTypeDone()) + return; + } } if (_CheckTypeDone()) @@ -3670,7 +3902,12 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy member->mRefCount++; } - typeInstance->mDefineState = BfTypeDefineState_Defined; + if (typeInstance->mDefineState < BfTypeDefineState_Defined) + { + typeInstance->mDefineState = BfTypeDefineState_Defined; + if (!typeInstance->IsBoxed()) + ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeDone, NULL); + } if (typeInstance->mTypeFailed) mHadBuildError = true; @@ -3832,7 +4069,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy int64 min = 0; int64 max = 0; - bool isFirst = false; + bool isFirst = true; if (typeInstance->mTypeInfoEx == NULL) typeInstance->mTypeInfoEx = new BfTypeInfoEx(); @@ -4310,20 +4547,19 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) continue; if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_InWorkList) - continue; - if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) - continue; + continue; if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Referenced) continue; - + if (isFailedType) { // We don't want method decls from failed generic types to clog up our type system continue; } - - // This should still be set to the default value - BF_ASSERT((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) || (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl)); + + BF_ASSERT((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) || + (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) || + (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference)); if ((isBoxed) && (!methodDef->mIsVirtual)) { @@ -4351,12 +4587,11 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) if ((methodDef->mName == BF_METHODNAME_DYNAMICCAST) && (typeInstance->IsValueType())) continue; // This is just a placeholder for boxed types - - if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) - methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude; + bool doAlwaysInclude = false; + if (wantsOnDemandMethods) - { + { bool implRequired = false; bool declRequired = false; @@ -4452,9 +4687,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) } if (!implRequired) - { - BF_ASSERT(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_NotSet); - if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) + { + if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) { if (!mIsScratchModule) mOnDemandMethodCount++; @@ -4462,19 +4696,41 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) if (!declRequired) { - if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) + if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_NoDecl_AwaitingReference; continue; } else { - if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) + if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl; } VerifyOnDemandMethods(); } + else + { + doAlwaysInclude = true; + } } + else + doAlwaysInclude = true; + + if (doAlwaysInclude) + { + bool wasDeclared = (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) || + (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference); + + methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude; + + if (wasDeclared) + { + if (!mIsScratchModule) + mOnDemandMethodCount--; + if (methodInstanceGroup->mDefault != NULL) + AddMethodToWorkList(methodInstanceGroup->mDefault); + } + } } BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount); @@ -5480,7 +5736,7 @@ BfPrimitiveType* BfModule::GetPrimitiveType(BfTypeCode typeCode) BfIRType BfModule::GetIRLoweredType(BfTypeCode loweredTypeCode, BfTypeCode loweredTypeCode2) { - BF_ASSERT(!mIsConstModule); + BF_ASSERT(!mIsComptimeModule); BF_ASSERT(loweredTypeCode != BfTypeCode_None); if (loweredTypeCode2 == BfTypeCode_None) diff --git a/IDEHelper/Compiler/BfParser.cpp b/IDEHelper/Compiler/BfParser.cpp index 50a496bc..58ce3c32 100644 --- a/IDEHelper/Compiler/BfParser.cpp +++ b/IDEHelper/Compiler/BfParser.cpp @@ -341,6 +341,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem mAwaitingDelete = false; mScanOnly = false; mCompleteParse = false; + mIsEmitted = false; mJumpTable = NULL; mProject = bfProject; mPassInstance = NULL; @@ -525,6 +526,8 @@ void BfParser::SetSource(const char* data, int length) canCache = false; if (mProject == NULL) canCache = false; + if (mIsEmitted) + canCache = false; uint64 cacheHash = 0; if (canCache) @@ -3447,8 +3450,11 @@ void BfParser::Parse(BfPassInstance* passInstance) { BP_ZONE_F("BfParser::Parse %s", mFileName.c_str()); + mSyntaxToken = BfSyntaxToken_None; mPassInstance = passInstance; + int startIdx = mSrcIdx; + if (mUsingCache) { mRootNode = mParserData->mRootNode; @@ -3476,7 +3482,7 @@ void BfParser::Parse(BfPassInstance* passInstance) mPassInstance->Warn(0, "No matching #endif found", mPreprocessorNodeStack.back().first); } - for (int i = 1; i < mJumpTableSize; i++) + for (int i = (startIdx / PARSER_JUMPTABLE_DIVIDE)+1; i < mJumpTableSize; i++) if (mJumpTable[i].mCharIdx == 0) mJumpTable[i] = mJumpTable[i - 1]; @@ -3523,6 +3529,26 @@ void BfParser::Close() } } +void BfParser::HadSrcRealloc() +{ + int jumpTableSize = ((mSrcAllocSize + 1) + PARSER_JUMPTABLE_DIVIDE - 1) / PARSER_JUMPTABLE_DIVIDE; + if (jumpTableSize > mJumpTableSize) + { + auto jumpTable = new BfLineStartEntry[jumpTableSize]; + memset(jumpTable, 0, jumpTableSize * sizeof(BfLineStartEntry)); + memcpy(jumpTable, mJumpTable, mJumpTableSize * sizeof(BfLineStartEntry)); + + delete mJumpTable; + + mJumpTable = jumpTable; + mJumpTableSize = jumpTableSize; + + mParserData->mJumpTable = mJumpTable; + mParserData->mJumpTableSize = mJumpTableSize; + } + +} + void BfParser::GenerateAutoCompleteFrom(int srcPosition) { BfSourcePositionFinder posFinder(this, srcPosition); diff --git a/IDEHelper/Compiler/BfParser.h b/IDEHelper/Compiler/BfParser.h index 2d5b0797..cc9a27ed 100644 --- a/IDEHelper/Compiler/BfParser.h +++ b/IDEHelper/Compiler/BfParser.h @@ -81,7 +81,7 @@ public: Dictionary mWarningEnabledChanges; std::set mUnwarns; bool mFailed; // Don't cache if there's a warning or an error - bool mDidReduce; + bool mDidReduce; public: BfParserData(); @@ -157,6 +157,7 @@ public: bool mQuickCompatMode; bool mScanOnly; bool mCompleteParse; + bool mIsEmitted; BfLineStartEntry* mJumpTable; int mJumpTableSize; int mOrigSrcLength; @@ -231,6 +232,7 @@ public: void Parse(BfPassInstance* passInstance); int GetCharIdAtIndex(int findIndex); virtual void Close() override; + virtual void HadSrcRealloc() override; void GenerateAutoCompleteFrom(int srcPosition); diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 76c0e4fd..db451f42 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -1143,7 +1143,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, BfTypeCode loweredReturnTypeCode = BfTypeCode_None; BfTypeCode loweredReturnTypeCode2 = BfTypeCode_None; - if ((!module->mIsConstModule) && (GetLoweredReturnType(&loweredReturnTypeCode, &loweredReturnTypeCode2))) + if ((!module->mIsComptimeModule) && (GetLoweredReturnType(&loweredReturnTypeCode, &loweredReturnTypeCode2))) { auto irReturnType = module->GetIRLoweredType(loweredReturnTypeCode, loweredReturnTypeCode2); returnType = irReturnType; @@ -1153,7 +1153,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, auto voidType = module->GetPrimitiveType(BfTypeCode_None); returnType = module->mBfIRBuilder->MapType(voidType); } - else if ((!module->mIsConstModule) && (GetStructRetIdx(forceStatic) != -1)) + else if ((!module->mIsComptimeModule) && (GetStructRetIdx(forceStatic) != -1)) { auto voidType = module->GetPrimitiveType(BfTypeCode_None); returnType = module->mBfIRBuilder->MapType(voidType); @@ -1210,11 +1210,11 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, { checkType = checkType->GetUnderlyingType(); } - else if ((!module->mIsConstModule) && (checkType->IsSplattable()) && (AllowsSplatting(-1))) + else if ((!module->mIsComptimeModule) && (checkType->IsSplattable()) && (AllowsSplatting(-1))) { doSplat = true; } - else if ((!module->mIsConstModule) && (!mMethodDef->mIsMutating) && (mCallingConvention == BfCallingConvention_Unspecified)) + else if ((!module->mIsComptimeModule) && (!mMethodDef->mIsMutating) && (mCallingConvention == BfCallingConvention_Unspecified)) checkLowered = true; } else @@ -1227,11 +1227,11 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, { checkType = checkType->GetUnderlyingType(); } - else if ((!module->mIsConstModule) && (checkType->IsSplattable()) && (AllowsSplatting(paramIdx))) + else if ((!module->mIsComptimeModule) && (checkType->IsSplattable()) && (AllowsSplatting(paramIdx))) { doSplat = true; } - else if (!module->mIsConstModule) + else if (!module->mIsComptimeModule) checkLowered = true; } @@ -1311,7 +1311,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, paramIdx++; // Skip over the explicit 'this' } - if ((!module->mIsConstModule) && (GetStructRetIdx(forceStatic) == 1)) + if ((!module->mIsComptimeModule) && (GetStructRetIdx(forceStatic) == 1)) { BF_SWAP(paramTypes[0], paramTypes[1]); } @@ -1509,6 +1509,8 @@ BfTypeInstance::~BfTypeInstance() delete methodInst; for (auto operatorInfo : mOperatorInfo) delete operatorInfo; + for (auto localMethod : mOwnedLocalMethods) + delete localMethod; delete mHotTypeData; delete mConstHolder; } diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 911cc143..3e34bb5e 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -416,7 +416,9 @@ enum BfTypeRebuildFlags BfTypeRebuildFlag_UnderlyingTypeDeferred = 0x1000, BfTypeRebuildFlag_TypeDataSaved = 0x2000, BfTypeRebuildFlag_InTempPool = 0x4000, - BfTypeRebuildFlag_ResolvingBase = 0x8000 + BfTypeRebuildFlag_ResolvingBase = 0x8000, + BfTypeRebuildFlag_InFailTypes = 0x10000, + BfTypeRebuildFlag_RebuildQueued = 0x20000, }; class BfTypeDIReplaceCallback; @@ -425,9 +427,12 @@ enum BfTypeDefineState : uint8 { BfTypeDefineState_Undefined, BfTypeDefineState_Declared, - BfTypeDefineState_ResolvingBaseType, + BfTypeDefineState_ResolvingBaseType, BfTypeDefineState_HasInterfaces, + BfTypeDefineState_CETypeInit, + BfTypeDefineState_CEPostTypeInit, BfTypeDefineState_Defined, + BfTypeDefineState_CEAfterFields, BfTypeDefineState_DefinedAndMethodsSlotted, }; @@ -830,6 +835,7 @@ public: bool mInCEMachine:1; bool mIsDisposed:1; BfMethodChainType mChainType; + BfComptimeFlags mComptimeFlags; BfCallingConvention mCallingConvention; BfMethodInstanceGroup* mMethodInstanceGroup; BfMethodDef* mMethodDef; @@ -868,6 +874,7 @@ public: mInCEMachine = false; mIsDisposed = false; mChainType = BfMethodChainType_None; + mComptimeFlags = BfComptimeFlag_None; mCallingConvention = BfCallingConvention_Unspecified; mMethodInstanceGroup = NULL; mMethodDef = NULL; @@ -1792,6 +1799,7 @@ public: Array mInternalMethods; Dictionary mStaticSearchMap; Dictionary mInternalAccessMap; + Array mOwnedLocalMethods; // Local methods in CEMachine bool mHasStaticInitMethod; bool mHasStaticDtorMethod; bool mHasStaticMarkMethod; @@ -1969,7 +1977,7 @@ public: bool IsAlwaysInclude(); bool HasBeenInstantiated() { return mHasBeenInstantiated || ((mAlwaysIncludeFlags & BfAlwaysIncludeFlag_AssumeInstantiated) != 0); } bool IncludeAllMethods() { return ((mAlwaysIncludeFlags & BfAlwaysIncludeFlag_IncludeAllMethods) != 0); } - + bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces; } virtual void ReportMemory(MemReporter* memReporter) override; }; diff --git a/IDEHelper/Compiler/BfSource.cpp b/IDEHelper/Compiler/BfSource.cpp index 7ed3294f..648637ee 100644 --- a/IDEHelper/Compiler/BfSource.cpp +++ b/IDEHelper/Compiler/BfSource.cpp @@ -91,7 +91,9 @@ int BfSource::AllocChars(int charCount) BF_ASSERT(mSourceData->ToParser() != NULL); mSourceData->mSrc = mSrc; - } + + HadSrcRealloc(); + } int retVal = mSrcLength; mSrcLength += charCount; diff --git a/IDEHelper/Compiler/BfSource.h b/IDEHelper/Compiler/BfSource.h index c0ea6b46..b88fac39 100644 --- a/IDEHelper/Compiler/BfSource.h +++ b/IDEHelper/Compiler/BfSource.h @@ -101,6 +101,7 @@ public: virtual ~BfSource(); virtual BfParser* ToParser() { return NULL; } + virtual void HadSrcRealloc() {} BfErrorNode* CreateErrorNode(BfAstNode* astNode); void AddErrorNode(BfAstNode* astNode); diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 5228210c..acdb1641 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -42,7 +42,7 @@ USING_NS_BF; bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfScopeData* scopeData) { - if ((((mCompiler->mIsResolveOnly) && (!mIsConstModule)) || + if ((((mCompiler->mIsResolveOnly) && (!mIsComptimeModule)) || (mBfIRBuilder->mIgnoreWrites)) && (deferredCallEntry->mDeferredBlock == NULL)) { // For resolve entries, we only keep deferred blocks because we need to process them later so we can @@ -783,7 +783,7 @@ void BfModule::EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, Siz void BfModule::EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry, bool moveBlocks) { - if ((mCompiler->mIsResolveOnly) && (!mIsConstModule) && (deferredCallEntry.mHandlerCount > 0)) + if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (deferredCallEntry.mHandlerCount > 0)) { // We only want to process deferred blocks once, otherwise it could significantly slow down autocompletion return; @@ -1770,7 +1770,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD initValue = LoadValue(initValue); if (initValue.IsSplat()) { - BF_ASSERT(!mIsConstModule); + BF_ASSERT(!mIsComptimeModule); if (!localDef->mAddr) localDef->mAddr = AllocLocalVariable(resolvedType, localDef->mName); AggregateSplatIntoAddr(initValue, localDef->mAddr); @@ -3944,7 +3944,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt) allowPrivate = false; } - if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) + if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule)) { auto preDelete = GetInternalMethod((deleteStmt->mTargetTypeToken != NULL) ? "Dbg_ObjectPreCustomDelete" : "Dbg_ObjectPreDelete"); SizedArray llvmArgs; @@ -4001,7 +4001,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt) } else { - if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsConstModule)) + if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsComptimeModule)) { SizedArray llvmArgs; llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(objectType))); @@ -4958,12 +4958,12 @@ void BfModule::Visit(BfReturnStatement* returnStmt) BfType* origType; BfExprEvaluator exprEvaluator(this); bool alreadyWritten = false; - if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) + if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) exprEvaluator.mReceivingValue = &mCurMethodState->mRetVal; if (mCurMethodInstance->mMethodDef->mIsReadOnly) exprEvaluator.mAllowReadOnlyReference = true; auto retValue = CreateValueFromExpression(exprEvaluator, returnStmt->mExpression, expectingReturnType, BfEvalExprFlags_AllowRefExpr, &origType); - if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) + if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1)) alreadyWritten = exprEvaluator.mReceivingValue == NULL; MarkScopeLeft(&mCurMethodState->mHeadScope); @@ -6453,7 +6453,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) auto retVal = exprEvaluator.CreateCall(&methodMatcher, itr); if (exprEvaluator.mReceivingValue != NULL) { - if (mIsConstModule) + if (mIsComptimeModule) { mBfIRBuilder->CreateStore(retVal.mValue, nextResult.mValue); } @@ -6802,7 +6802,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt) if (!customAllocator) { - if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsConstModule)) + if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsComptimeModule)) { auto moduleMethodInstance = GetInternalMethod("Dbg_MarkObjectDeleted"); AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true); @@ -6819,7 +6819,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt) auto moduleMethodInstance = GetMethodInstance(objectType, methodInstance->mMethodDef, BfTypeVector()); AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true); - if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) + if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule)) { auto moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), (deleteStmt->mTargetTypeToken != NULL) ? "Dbg_ObjectPreCustomDelete" : "Dbg_ObjectPreDelete"); AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true); @@ -6831,7 +6831,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt) { val = LoadValue(val); BfModuleMethodInstance moduleMethodInstance; - if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule)) + if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule)) moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), "Dbg_RawFree"); else moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), "Free"); diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 2c0000af..2f0c9465 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -679,6 +679,42 @@ void BfTypeDef::FreeMembers() mIsNextRevision = false; } +void BfTypeDef::ClearEmitted() +{ + for (auto& partial : mPartials) + partial->ClearEmitted(); + + if (mEmitParser != NULL) + { + mEmitParser->mRefCount--; + BF_ASSERT(mEmitParser->mRefCount >= 0); + mEmitParser = NULL; + } + + if (mHasEmitMembers) + { + for (int methodIdx = (int)mMethods.size() - 1; methodIdx >= 0; methodIdx--) + { + auto methodDef = mMethods[methodIdx]; + if ((methodDef->mMethodDeclaration != NULL) && (methodDef->mMethodDeclaration->IsEmitted())) + { + delete methodDef; + mMethods.RemoveAt(methodIdx); + } + } + + for (int fieldIdx = (int)mFields.size() - 1; fieldIdx >= 0; fieldIdx--) + { + auto fieldDef = mFields[fieldIdx]; + if ((fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->IsEmitted())) + { + delete fieldDef; + mFields.RemoveAt(fieldIdx); + } + } + } +} + void BfTypeDef::PopulateMemberSets() { if ((!mMethodSet.IsEmpty()) || (!mFieldSet.IsEmpty()) || (!mPropertySet.IsEmpty())) @@ -721,6 +757,13 @@ void BfTypeDef::PopulateMemberSets() } } +void BfTypeDef::ClearMemberSets() +{ + mMethodSet.Clear(); + mFieldSet.Clear(); + mPropertySet.Clear(); +} + BfTypeDef::~BfTypeDef() { BfLogSysM("BfTypeDef::~BfTypeDef %08X\n", this); @@ -732,6 +775,12 @@ BfTypeDef::~BfTypeDef() mSource->mRefCount--; BF_ASSERT(mSource->mRefCount >= 0); } + + if (mEmitParser != NULL) + { + mEmitParser->mRefCount--; + BF_ASSERT(mEmitParser->mRefCount >= 0); + } } BfSource* BfTypeDef::GetLastSource() @@ -1533,6 +1582,8 @@ BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, Bf if (!WantsRangeRecorded(bfParser, srcIdx, srcLen, true)) return NULL; + mWarnIdx++; + TrimSourceRange(bfSource, srcIdx, srcLen); BfError* errorVal = new BfError(); @@ -1564,6 +1615,7 @@ BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, Bf BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning) { + mWarnIdx++; mLastWasAdded = false; mLastWasDisplayed = (int)mErrors.size() <= sMaxDisplayErrors; if (!mLastWasDisplayed) @@ -1577,6 +1629,7 @@ BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning, BfAs { BP_ZONE("BfPassInstance::Warn"); + mWarnIdx++; mLastWasAdded = false; mLastWasDisplayed = (int)mErrors.size() <= sMaxErrors; if (!mLastWasDisplayed) @@ -1638,9 +1691,9 @@ BfMoreInfo* BfPassInstance::MoreInfoAt(const StringImpl& info, BfSourceData* bfS return NULL; } -BfMoreInfo* BfPassInstance::MoreInfo(const StringImpl& info) +BfMoreInfo* BfPassInstance::MoreInfo(const StringImpl& info, bool forceQueue) { - if (!mLastWasDisplayed) + if ((!mLastWasDisplayed) || (forceQueue)) { if (mLastWasAdded) { @@ -2534,6 +2587,8 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef) { BfLogSys(this, "InjectNewRevision from %p (decl:%p) into %p (decl:%p)\n", typeDef->mNextRevision, typeDef->mNextRevision->mTypeDeclaration, typeDef, typeDef->mTypeDeclaration); + typeDef->ClearEmitted(); + bool setDeclaringType = !typeDef->mIsCombinedPartial; auto nextTypeDef = typeDef->mNextRevision; @@ -2651,7 +2706,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef) typeDef->mTypeCode = nextTypeDef->mTypeCode; typeDef->mIsAlwaysInclude = nextTypeDef->mIsAlwaysInclude; - typeDef->mIsNoDiscard = nextTypeDef->mIsNoDiscard; + typeDef->mIsNoDiscard = nextTypeDef->mIsNoDiscard; typeDef->mIsPartial = nextTypeDef->mIsPartial; typeDef->mIsExplicitPartial = nextTypeDef->mIsExplicitPartial; //mPartialUsed @@ -2663,6 +2718,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef) typeDef->mIsConcrete = nextTypeDef->mIsConcrete; typeDef->mIsStatic = nextTypeDef->mIsStatic; typeDef->mHasAppendCtor = nextTypeDef->mHasAppendCtor; + typeDef->mHasCEOnCompile = nextTypeDef->mHasCEOnCompile; typeDef->mHasCtorNoBody = nextTypeDef->mHasCtorNoBody; typeDef->mHasOverrideMethods = nextTypeDef->mHasOverrideMethods; typeDef->mHasExtensionMethods = nextTypeDef->mHasExtensionMethods; @@ -2722,7 +2778,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef) delete nextTypeDef; typeDef->mNextRevision = NULL; - typeDef->mDefState = BfTypeDef::DefState_Defined; + typeDef->mDefState = BfTypeDef::DefState_Defined; VerifyTypeDef(typeDef); } @@ -2771,6 +2827,8 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co typeDef->mHasCtorNoBody = partialTypeDef->mHasCtorNoBody; typeDef->mHasExtensionMethods = partialTypeDef->mHasExtensionMethods; typeDef->mHasOverrideMethods = partialTypeDef->mHasOverrideMethods; + typeDef->mIsAlwaysInclude = partialTypeDef->mIsAlwaysInclude; + typeDef->mHasCEOnCompile = partialTypeDef->mHasCEOnCompile; for (auto generic : partialTypeDef->mGenericParamDefs) { @@ -2806,6 +2864,7 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co typeDef->mIsConcrete |= partialTypeDef->mIsConcrete; typeDef->mIsStatic |= partialTypeDef->mIsStatic; typeDef->mHasAppendCtor |= partialTypeDef->mHasAppendCtor; + typeDef->mHasCEOnCompile |= partialTypeDef->mHasCEOnCompile; typeDef->mHasExtensionMethods |= partialTypeDef->mHasExtensionMethods; typeDef->mHasOverrideMethods |= partialTypeDef->mHasOverrideMethods; typeDef->mProtection = BF_MIN(typeDef->mProtection, partialTypeDef->mProtection); @@ -3237,12 +3296,12 @@ void BfSystem::RemoveOldParsers() BfLogSys(this, "Deleting Old Parser: %p New Parser: %p\n", bfParser, bfParser->mNextRevision); + mParsers.RemoveAt(i); + i--; + mDataLock.Unlock(); delete bfParser; - mDataLock.Lock(); - - mParsers.erase(mParsers.begin() + i); - i--; + mDataLock.Lock(); } } } diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 9ecb2b82..bb4ebd55 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -218,6 +218,13 @@ enum BfAlwaysIncludeFlags : uint8 BfAlwaysIncludeFlag_All = BfAlwaysIncludeFlag_Type | BfAlwaysIncludeFlag_IncludeAllMethods | BfAlwaysIncludeFlag_AssumeInstantiated }; +enum BfCEOnCompileKind : uint8 +{ + BfCEOnCompileKind_None, + BfCEOnCompileKind_TypeInit, + BfCEOnCompileKind_TypeDone +}; + enum BfPlatformType { BfPlatformType_Unknown, @@ -740,6 +747,14 @@ enum BfCommutableKind : int8 BfCommutableKind_Reverse, }; +enum BfComptimeFlags : int8 +{ + BfComptimeFlag_None, + BfComptimeFlag_Comptime = 1, + BfComptimeFlag_OnlyFromComptime = 2, + BfComptimeFlag_ConstEval = 4 +}; + class BfMethodDef : public BfMemberDef { public: @@ -774,7 +789,7 @@ public: bool mIsNoSplat; bool mIsNoReflect; bool mIsSkipCall; - bool mIsConstEval; + bool mHasComptime; bool mIsOperator; bool mIsExtern; bool mIsNoDiscard; @@ -803,7 +818,7 @@ public: mIsNoSplat = false; mIsNoReflect = false; mIsSkipCall = false; - mIsConstEval = false; + mHasComptime = false; mIsOperator = false; mIsExtern = false; mIsNoDiscard = false; @@ -914,11 +929,12 @@ public: public: BfTypeDef* mNextRevision; - + BfSystem* mSystem; BfProject* mProject; BfTypeDeclaration* mTypeDeclaration; BfSource* mSource; + BfParser* mEmitParser; DefState mDefState; Val128 mSignatureHash; // Data, methods, etc Val128 mFullHash; @@ -953,7 +969,7 @@ public: int mPartialIdx; int mNestDepth; int mDupDetectedRevision; // Error state - BfTypeCode mTypeCode; + BfTypeCode mTypeCode; bool mIsAlwaysInclude; bool mIsNoDiscard; bool mIsPartial; @@ -966,6 +982,7 @@ public: bool mIsAbstract; bool mIsConcrete; bool mIsStatic; + bool mHasCEOnCompile; bool mHasAppendCtor; bool mHasCtorNoBody; bool mHasExtensionMethods; @@ -973,6 +990,7 @@ public: bool mIsOpaque; bool mIsNextRevision; bool mInDeleteQueue; + bool mHasEmitMembers; public: BfTypeDef() @@ -988,7 +1006,7 @@ public: mNameEx = NULL; mSystem = NULL; mProject = NULL; - mTypeCode = BfTypeCode_None; + mTypeCode = BfTypeCode_None; mIsAlwaysInclude = false; mIsNoDiscard = false; mIsExplicitPartial = false; @@ -996,6 +1014,7 @@ public: mIsCombinedPartial = false; mTypeDeclaration = NULL; mSource = NULL; + mEmitParser = NULL; mDefState = DefState_New; mHash = 0; mPartialIdx = -1; @@ -1005,6 +1024,7 @@ public: mIsFunction = false; mIsClosure = false; mIsStatic = false; + mHasCEOnCompile = false; mHasAppendCtor = false; mHasCtorNoBody = false; mHasExtensionMethods = false; @@ -1013,12 +1033,13 @@ public: mPartialUsed = false; mIsNextRevision = false; mInDeleteQueue = false; + mHasEmitMembers = false; mDupDetectedRevision = -1; mNestDepth = 0; mOuterType = NULL; mTypeDeclaration = NULL; mDtorDef = NULL; - mNextRevision = NULL; + mNextRevision = NULL; mProtection = BfProtection_Public; } @@ -1026,7 +1047,9 @@ public: bool IsGlobalsContainer(); void Reset(); void FreeMembers(); + void ClearEmitted(); void PopulateMemberSets(); + void ClearMemberSets(); void RemoveGenericParamDef(BfGenericParamDef* genericParamDef); int GetSelfGenericParamCount(); String ToString(); @@ -1284,12 +1307,13 @@ public: BfSystem* mSystem; bool mTrimMessagesToCursor; int mFailedIdx; + int mWarnIdx; Dictionary mSourceFileNameMap; HashSet mErrorSet; Array mErrors; int mIgnoreCount; - int mWarningCount; + int mWarningCount; int mDeferredErrorCount; Deque mOutStream; bool mLastWasDisplayed; @@ -1303,11 +1327,12 @@ public: { mTrimMessagesToCursor = false; mFailedIdx = 0; + mWarnIdx = 0; mSystem = bfSystem; mLastWasDisplayed = false; mLastWasAdded = false; mClassifierPassId = 0; - mWarningCount = 0; + mWarningCount = 0; mDeferredErrorCount = 0; mIgnoreCount = 0; mFilterErrorsTo = NULL; @@ -1336,7 +1361,7 @@ public: BfError* WarnAfter(int warningNumber, const StringImpl& warning, BfAstNode* refNode); BfMoreInfo* MoreInfoAt(const StringImpl& info, BfSourceData* bfSource, int srcIdx, int srcLen, BfFailFlags flags = BfFailFlag_None); - BfMoreInfo* MoreInfo(const StringImpl& info); + BfMoreInfo* MoreInfo(const StringImpl& info, bool forceQueue = false); BfMoreInfo* MoreInfo(const StringImpl& info, BfAstNode* refNode); BfMoreInfo* MoreInfoAfter(const StringImpl& info, BfAstNode* refNode); diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index 12c0c82e..ae376146 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -728,8 +728,7 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme CeStaticFieldInfo* staticFieldInfoPtr = NULL; if (mCeMachine->mStaticFieldMap.TryGetValue(globalVar->mName, &staticFieldInfoPtr)) { - CeStaticFieldInfo* staticFieldInfo = staticFieldInfoPtr; - + CeStaticFieldInfo* staticFieldInfo = staticFieldInfoPtr; int* staticFieldTableIdxPtr = NULL; if (mStaticFieldMap.TryAdd(globalVar, NULL, &staticFieldTableIdxPtr)) { @@ -1190,8 +1189,6 @@ void CeBuilder::Build() bool isGenericVariation = (methodInstance->mIsUnspecializedVariation) || (methodInstance->GetOwner()->IsUnspecializedTypeVariation()); int dependentGenericStartIdx = 0; - if (methodInstance->mMethodInfoEx != NULL) - dependentGenericStartIdx = (int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size(); if ((((methodInstance->mMethodInfoEx != NULL) && ((int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size() > dependentGenericStartIdx)) || ((methodInstance->GetOwner()->IsGenericTypeInstance()) && (!isGenericVariation) && (!methodInstance->mMethodDef->mIsLocalMethod)))) { @@ -2646,13 +2643,17 @@ CeMachine::CeMachine(BfCompiler* compiler) mCurFunctionId = 0; mRevisionExecuteTime = 0; mCurTargetSrc = NULL; + mCurBuilder = NULL; mPreparingFunction = NULL; + mCurEvalFlags = CeEvalFlags_None; + mCurFrame = NULL; mCurModule = NULL; mCurMethodInstance = NULL; mCurExpectingType = NULL; + mCurEmitContext = NULL; mHeap = NULL; mStringCharsOffset = -1; - mAppendAllocInfo = NULL; + mAppendAllocInfo = NULL; } CeMachine::~CeMachine() @@ -2689,19 +2690,25 @@ CeMachine::~CeMachine() BfError* CeMachine::Fail(const StringImpl& error) { - auto bfError = mCurModule->Fail(StrFormat("Unable to const-evaluate %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc); + auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0); if (bfError == NULL) return NULL; - mCompiler->mPassInstance->MoreInfo(error); + mCompiler->mPassInstance->MoreInfo(error, mCeModule->mCompiler->GetAutoComplete() != NULL); return bfError; } BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str) { - auto bfError = mCurModule->Fail(StrFormat("Unable to const-evaluate %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc); + auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0); if (bfError == NULL) return NULL; + if ((mCurEvalFlags & CeEvalFlags_DeferIfNotOnlyError) != 0) + { + if (mCurModule->mHadBuildError) + bfError->mIsDeferred = true; + } + auto passInstance = mCompiler->mPassInstance; for (int stackIdx = mCallStack.size(); stackIdx >= 0; stackIdx--) @@ -2748,7 +2755,7 @@ BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str) contextMethodInstance = func->mCeFunctionInfo->mMethodInstance; } - err += StrFormat("in const evaluation of "); + err += StrFormat("in comptime "); // { @@ -2766,7 +2773,7 @@ BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str) if (emitEntry != NULL) err += StrFormat(" at line% d:%d in %s", emitEntry->mLine + 1, emitEntry->mColumn + 1, ceFunction->mFiles[emitEntry->mFile].c_str()); - auto moreInfo = passInstance->MoreInfo(err); + auto moreInfo = passInstance->MoreInfo(err, mCeModule->mCompiler->GetAutoComplete() != NULL); if ((moreInfo != NULL) && (emitEntry != NULL)) { BfErrorLocation* location = new BfErrorLocation(); @@ -2785,7 +2792,7 @@ void CeMachine::Init() mCeModule = new BfModule(mCompiler->mContext, "__constEval"); mCeModule->mIsSpecialModule = true; //mCeModule->mIsScratchModule = true; - mCeModule->mIsConstModule = true; + mCeModule->mIsComptimeModule = true; //mCeModule->mIsReified = true; if (mCompiler->mIsResolveOnly) mCeModule->mIsReified = true; @@ -2882,7 +2889,8 @@ addr_ce CeMachine::GetReflectType(int typeId) if (bfType == NULL) return 0; - mCeModule->PopulateType(bfType, BfPopulateType_DataAndMethods); + if (bfType->mDefineState != BfTypeDefineState_CETypeInit) + mCeModule->PopulateType(bfType, BfPopulateType_DataAndMethods); Dictionary usedStringMap; auto irData = mCeModule->CreateTypeData(bfType, usedStringMap, true, true, true, false); @@ -2991,6 +2999,30 @@ void CeMachine::PrepareConstStructEntry(CeConstStructData& constEntry) constEntry.mBindExecuteId = mExecuteId; } +bool CeMachine::CheckMemory(addr_ce addr, int32 size) +{ + if (((addr)-0x10000) + (size) > (mMemory.mSize - 0x10000)) + return false; + return true; +} + +bool CeMachine::GetStringFromStringView(addr_ce addr, StringImpl& str) +{ + int ptrSize = mCeModule->mSystem->mPtrSize; + if (!CheckMemory(addr, ptrSize * 2)) + return false; + + addr_ce charsPtr = *(addr_ce*)(mMemory.mVals + addr); + int32 len = *(int32*)(mMemory.mVals + addr + ptrSize); + + if (!CheckMemory(charsPtr, len)) + return false; + + str.Append((const char*)(mMemory.mVals + charsPtr), len); + + return true; +} + BeContext* CeMachine::GetBeContext() { if (mCeModule == NULL) @@ -3016,6 +3048,12 @@ void CeMachine::CompileStarted() } } +void CeMachine::CompileDone() +{ + // So things like delted local methods get recheckeds + mRevision++; +} + void CeMachine::DerefMethodInfo(CeFunctionInfo* ceFunctionInfo) { ceFunctionInfo->mRefCount--; @@ -3257,6 +3295,13 @@ bool CeMachine::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta } } + if ((constant->mConstType == BfConstType_TypeOf) || (constant->mConstType == BfConstType_TypeOf_WithData)) + { + auto constTypeOf = (BfTypeOf_Const*)constant; + CE_GETC(addr_ce) = GetReflectType(constTypeOf->mType->mTypeId); + return true; + } + return false; } @@ -3489,7 +3534,6 @@ CeErrorKind CeMachine::WriteConstant(CeConstStructData& data, BeConstant* constV return CeErrorKind_None; } - #define CE_CREATECONST_CHECKPTR(PTR, SIZE) \ if ((((uint8*)(PTR) - memStart) - 0x10000) + (SIZE) > (memSize - 0x10000)) \ { \ @@ -3829,8 +3873,10 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* uint8* stackPtr = startStackPtr; uint8* framePtr = startFramePtr; bool needsFunctionIds = mCeModule->mSystem->mPtrSize != 8; - - volatile bool* cancelPtr = &mCompiler->mCanceling; + int32 ptrSize = mCeModule->mSystem->mPtrSize; + + volatile bool* fastFinishPtr = &mCompiler->mFastFinish; + volatile bool* cancelingPtr = &mCompiler->mCanceling; auto _GetCurFrame = [&]() { @@ -3973,12 +4019,30 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* handled = true; return true; } + else if (checkFunction->mFunctionKind == CeFunctionKind_EmitDefinition) + { + int32 typeId = *(int32*)((uint8*)stackPtr); + addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + sizeof(int32)); + if ((mCurEmitContext == NULL) || (mCurEmitContext->mType->mTypeId != typeId)) + { + _Fail("Missing emit context"); + return false; + } + if (!GetStringFromStringView(strViewPtr, mCurEmitContext->mEmitData)) + { + _Fail("Invalid StringView"); + return false; + } + + handled = true; + return true; + } else if (checkFunction->mFunctionKind == CeFunctionKind_Sleep) { int32 sleepMS = *(int32*)((uint8*)stackPtr); while (sleepMS > 0) { - if (*cancelPtr) + if (*fastFinishPtr) break; if (sleepMS > 200) @@ -4104,9 +4168,9 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* if (!checkFunction->mFailed) return true; - auto error = Fail(_GetCurFrame(), "Method call failed"); + auto error = Fail(_GetCurFrame(), StrFormat("Method call '%s' failed", mCeModule->MethodToString(checkFunction->mMethodInstance).c_str())); if ((error != NULL) && (!checkFunction->mGenError.IsEmpty())) - mCompiler->mPassInstance->MoreInfo("Const Method Generation Error: " + checkFunction->mGenError); + mCompiler->mPassInstance->MoreInfo("Comptime method generation error: " + checkFunction->mGenError); return false; }; @@ -4124,9 +4188,10 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* while (true) { - if (*cancelPtr) + if (*fastFinishPtr) { - _Fail("Compilation cancelled"); + if (*cancelingPtr) + _Fail("Comptime evaluation canceled"); return false; } @@ -4576,10 +4641,14 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* if (staticFieldInfo->mAddr == 0) { + if (ceStaticFieldEntry.mSize < 0) + _Fail(StrFormat("Reference to unsized global variable '%s'", ceStaticFieldEntry.mName.c_str())); + CE_CHECKALLOC(ceStaticFieldEntry.mSize); uint8* ptr = CeMalloc(ceStaticFieldEntry.mSize); _FixVariables(); - memset(ptr, 0, ceStaticFieldEntry.mSize); + if (ceStaticFieldEntry.mSize > 0) + memset(ptr, 0, ceStaticFieldEntry.mSize); staticFieldInfo->mAddr = (addr_ce)(ptr - memStart); } @@ -4641,14 +4710,22 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* callEntry.mFunction = callEntry.mFunctionInfo->mCeFunction; if (!callEntry.mFunction->mInitialized) { + auto curFrame = _GetCurFrame(); + SetAndRestoreValue prevFrame(mCurFrame, &curFrame); PrepareFunction(callEntry.mFunction, NULL); } callEntry.mBindRevision = mRevision; } - + BF_ASSERT(memStart == mMemory.mVals); auto callFunction = callEntry.mFunction; + + if (callFunction->mMethodInstance->mMethodDef->mIsLocalMethod) + { + NOP; + } + if (needsFunctionIds) *(int32*)(framePtr + resultFrameIdx) = callFunction->mId; else @@ -4678,7 +4755,14 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* CE_CHECKADDR(valueAddr, sizeof(int32)); int32 objTypeId = *(int32*)(memStart + valueAddr); - auto valueType = mCeModule->mContext->mTypes[objTypeId]->ToTypeInstance(); + BfType* bfType = GetBfType(objTypeId); + if ((bfType == NULL) || (!bfType->IsObject())) + { + _Fail("Invalid virtual method target"); + return false; + } + + auto valueType = bfType->ToTypeInstance(); if (valueType->mVirtualMethodTable.IsEmpty()) mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods); auto methodInstance = (BfMethodInstance*)valueType->mVirtualMethodTable[virtualIdx].mImplementingMethod; @@ -4702,23 +4786,26 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* CE_CHECKADDR(valueAddr, sizeof(int32)); int32 objTypeId = *(int32*)(memStart + valueAddr); auto valueType = mCeModule->mContext->mTypes[objTypeId]->ToTypeInstance(); - if (valueType->mVirtualMethodTable.IsEmpty()) - mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods); - BfMethodInstance* methodInstance = NULL; - auto checkType = valueType; - while (checkType != NULL) + if (valueType != NULL) { - for (auto& iface : checkType->mInterfaces) + if (valueType->mVirtualMethodTable.IsEmpty()) + mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods); + + auto checkType = valueType; + while (checkType != NULL) { - if (iface.mInterfaceType == ifaceType) + for (auto& iface : checkType->mInterfaces) { - methodInstance = valueType->mInterfaceMethodTable[iface.mStartInterfaceTableIdx + methodIdx].mMethodRef; - break; + if (iface.mInterfaceType == ifaceType) + { + methodInstance = valueType->mInterfaceMethodTable[iface.mStartInterfaceTableIdx + methodIdx].mMethodRef; + break; + } } + checkType = checkType->mBaseType; } - checkType = checkType->mBaseType; } if (methodInstance == NULL) @@ -5305,18 +5392,25 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder auto owner = ceFunction->mMethodInstance->GetOwner(); if (owner == mCeModule->mContext->mBfObjectType) { - if (methodDef->mName == "ConstEval_GetType") + if (methodDef->mName == "Comptime_GetType") { ceFunction->mFunctionKind = CeFunctionKind_GetReflectType; } } else if (owner->IsInstanceOf(mCeModule->mCompiler->mTypeTypeDef)) { - if (methodDef->mName == "ConstEval_GetTypeById") + if (methodDef->mName == "Comptime_GetTypeById") { ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeById; } } + else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef)) + { + if (methodDef->mName == "Comptime_EmitDefinition") + { + ceFunction->mFunctionKind = CeFunctionKind_EmitDefinition; + } + } else if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef)) { if (methodDef->mName == "Write") @@ -5373,6 +5467,7 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder ceFunction->mGenerating = true; CeBuilder ceBuilder; + SetAndRestoreValue prevBuilder(mCurBuilder, &ceBuilder); ceBuilder.mParentBuilder = parentBuilder; ceBuilder.mPtrSize = mCeModule->mCompiler->mSystem->mPtrSize; ceBuilder.mCeMachine = this; @@ -5534,6 +5629,7 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns // DISABLED //return BfTypedValue(); + SetAndRestoreValue prevEvalFlags(mCurEvalFlags, flags); SetAndRestoreValue prevTargetSrc(mCurTargetSrc, targetSrc); SetAndRestoreValue prevModule(mCurModule, module); SetAndRestoreValue prevMethodInstance(mCurMethodInstance, methodInstance); diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index 7b14956e..0b148d5b 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -251,6 +251,7 @@ enum CeFunctionKind CeFunctionKind_DebugWrite_Int, CeFunctionKind_GetReflectType, CeFunctionKind_GetReflectTypeById, + CeFunctionKind_EmitDefinition, CeFunctionKind_Sleep, CeFunctionKind_Char32_ToLower, CeFunctionKind_Char32_ToUpper, @@ -372,7 +373,9 @@ public: enum CeEvalFlags { CeEvalFlags_None = 0, - CeEvalFlags_Cascade = 1 + CeEvalFlags_Cascade = 1, + CeEvalFlags_PersistantError = 2, + CeEvalFlags_DeferIfNotOnlyError = 4, }; enum CeOperandKind @@ -602,6 +605,18 @@ public: BfIRValue mAppendSizeValue; }; +class CeEmitContext +{ +public: + BfType* mType; + String mEmitData; + + CeEmitContext() + { + mType = NULL; + } +}; + class CeMachine { public: @@ -628,7 +643,11 @@ public: HashSet mStaticCtorExecSet; CeAppendAllocInfo* mAppendAllocInfo; + CeEmitContext* mCurEmitContext; + CeEvalFlags mCurEvalFlags; + CeBuilder* mCurBuilder; CeFunction* mPreparingFunction; + CeFrame* mCurFrame; BfAstNode* mCurTargetSrc; BfMethodInstance* mCurMethodInstance; BfModule* mCurModule; @@ -650,6 +669,8 @@ public: addr_ce GetConstantData(BeConstant* constant); BfType* GetBfType(int typeId); void PrepareConstStructEntry(CeConstStructData& constStructData); + bool CheckMemory(addr_ce addr, int32 size); + bool GetStringFromStringView(addr_ce addr, StringImpl& str); BeContext* GetBeContext(); BeModule* GetBeModule(); @@ -659,7 +680,7 @@ public: CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal); BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL); void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction); - bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType); + bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType); void PrepareFunction(CeFunction* methodInstance, CeBuilder* parentBuilder); void MapFunctionId(CeFunction* ceFunction); @@ -670,6 +691,7 @@ public: public: void CompileStarted(); + void CompileDone(); void QueueMethod(BfMethodInstance* methodInstance, BfIRValue func); void QueueMethod(BfModuleMethodInstance moduleMethodInstance); void QueueStaticField(BfFieldInstance* fieldInstance, const StringImpl& mangledFieldName); diff --git a/IDEHelper/Tests/src/ConstEval.bf b/IDEHelper/Tests/src/ConstEval.bf index abe0e03f..68bd1bb4 100644 --- a/IDEHelper/Tests/src/ConstEval.bf +++ b/IDEHelper/Tests/src/ConstEval.bf @@ -23,8 +23,8 @@ namespace Tests const String cStrA = "Abc"; const String cStrB = GetStringA(cStrA, 12, 23); - // ConstEval attribute means this method will always be const-evaluated - [ConstEval] + // Comptime attribute means this method will always be const-evaluated + [Comptime] static String GetStringA(String str, int a, int b) { // Const-eval functions can return scope-allocated data @@ -101,7 +101,7 @@ namespace Tests } // This method can only be const evaluated - [ConstEval] + [Comptime] public static int32 ConstSum(params int32[] vals) { int32 sum = 0; @@ -112,8 +112,8 @@ namespace Tests public static int32 MethodB() { - // Returns different results depending on whether we are const-evaluating - return Compiler.IsConstEval ? 1 : 0; + // Returns different results depending on whether we are comptime + return Compiler.IsComptime ? 1 : 0; } public static int32 MethodC(StructA sa = .(1, 2), (int32, int32) tup = (20, 30), int32[2] arr = .(300, 400)) @@ -121,7 +121,7 @@ namespace Tests return sa.mA + sa.mB + tup.0 + tup.1 + arr[0] + arr[1]; } - [ConstEval] + [Comptime(ConstEval=true)] static var StrToValue(String str) { if (str.Contains('.')) @@ -164,7 +164,7 @@ namespace Tests //Compiler.Assert(val1 == 24); Test.Assert(val1 == 70); - // This method is marked as ConstEval so it always evaluates as const + // This method is marked as Comptime so it always evaluates as const let val2 = ConstSum(3, 20, 100); Compiler.Assert(val2 == 123); diff --git a/IDEHelper/Tests/src/Generics.bf b/IDEHelper/Tests/src/Generics.bf index f5193c30..e6bf648d 100644 --- a/IDEHelper/Tests/src/Generics.bf +++ b/IDEHelper/Tests/src/Generics.bf @@ -195,6 +195,22 @@ namespace Tests TI iface = val as TI; } + public void MethodA(List list) + { + + } + + public void MethodA(Span list) + { + + } + + public void MethodB() + { + List list = null; + MethodA(list); + } + [Test] public static void TestBasics() {