From ce4b6e04de2b68d4692be6487f8f00f3440bffb9 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 20 Dec 2021 09:39:39 -0500 Subject: [PATCH] Support for comptime file IO and process creation --- BeefLibs/corlib/src/Compiler.bf | 17 + BeefLibs/corlib/src/Diagnostics/Debug.bf | 19 + BeefLibs/corlib/src/OperatingSystem.bf | 3 + BeefySysLib/platform/win/Platform.cpp | 6 + BeefySysLib/util/String.h | 12 +- IDE/src/Compiler/BfSystem.bf | 8 +- IDE/src/IDEApp.bf | 13 + IDEHelper/Compiler/BfCompiler.cpp | 2 +- IDEHelper/Compiler/BfContext.cpp | 73 +++- IDEHelper/Compiler/BfExprEvaluator.cpp | 6 +- IDEHelper/Compiler/BfModule.cpp | 2 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 17 +- IDEHelper/Compiler/BfResolvedTypeUtils.h | 18 +- IDEHelper/Compiler/BfSystem.cpp | 3 +- IDEHelper/Compiler/BfSystem.h | 1 + IDEHelper/Compiler/CeMachine.cpp | 489 +++++++++++++++++++++-- IDEHelper/Compiler/CeMachine.h | 119 +++++- IDEHelper/Tests/Test0.txt | 2 + IDEHelper/Tests/src/Comptime.bf | 5 + 19 files changed, 726 insertions(+), 89 deletions(-) create mode 100644 IDEHelper/Tests/Test0.txt diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf index 3be28ff7..290c821a 100644 --- a/BeefLibs/corlib/src/Compiler.bf +++ b/BeefLibs/corlib/src/Compiler.bf @@ -2,6 +2,7 @@ using System.Reflection; using System.Diagnostics; using System.Collections; using System.Security.Cryptography; +using System.IO; namespace System { @@ -306,5 +307,21 @@ namespace System if (Compiler.IsComptime) Comptime_EmitMixin(text); } + + [Comptime] + public static Span ReadBinary(StringView path) + { + List data = scope .(); + File.ReadAll(path, data); + return data; + } + + [Comptime] + public static String ReadText(StringView path) + { + String data = scope .(); + File.ReadAllText(path, data); + return data; + } } } diff --git a/BeefLibs/corlib/src/Diagnostics/Debug.bf b/BeefLibs/corlib/src/Diagnostics/Debug.bf index e7a2a554..7ab33151 100644 --- a/BeefLibs/corlib/src/Diagnostics/Debug.bf +++ b/BeefLibs/corlib/src/Diagnostics/Debug.bf @@ -106,5 +106,24 @@ namespace System.Diagnostics if (gIsDebuggerPresent) Break(); } + + public static void WriteMemory(Span mem) + { + String str = scope .(); + for (int i < mem.Length) + { + if ((i != 0) && (i % 16 == 0)) + str.Append('\n'); + str.AppendF($" {mem.[Friend]mPtr[i]:X2}"); + } + str.Append('\n'); + Write(str); + } + + public static void WriteMemory(T result) + { +#unwarn + WriteMemory(.((.)&result, sizeof(T))); + } } } diff --git a/BeefLibs/corlib/src/OperatingSystem.bf b/BeefLibs/corlib/src/OperatingSystem.bf index eb1d578b..117c6819 100644 --- a/BeefLibs/corlib/src/OperatingSystem.bf +++ b/BeefLibs/corlib/src/OperatingSystem.bf @@ -118,6 +118,9 @@ namespace System public this() { + if (Compiler.IsComptime) + return; + #if BF_PLATFORM_WINDOWS bool isWinSrv() { diff --git a/BeefySysLib/platform/win/Platform.cpp b/BeefySysLib/platform/win/Platform.cpp index e8a91d1e..9ba9e69b 100644 --- a/BeefySysLib/platform/win/Platform.cpp +++ b/BeefySysLib/platform/win/Platform.cpp @@ -2909,6 +2909,12 @@ BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Read(BfpFile* file, void* buffer, intptr //TODO: this doesn't set file stream location. It only works for streams like pipes, sockets, etc if (::ReadFileEx(file->mHandle, buffer, (uint32)size, &overlapped, OverlappedReadComplete)) { + if (file->mAsyncData == NULL) + { + OUTRESULT(BfpFileResult_InvalidParameter); + return 0; + } + if (!file->mAsyncData->WaitAndResetEvent(timeoutMS)) { ::CancelIoEx(file->mHandle, &overlapped); diff --git a/BeefySysLib/util/String.h b/BeefySysLib/util/String.h index 3d7d8299..e30d9679 100644 --- a/BeefySysLib/util/String.h +++ b/BeefySysLib/util/String.h @@ -622,7 +622,17 @@ public: str.mLength = (int_strsize)strlen(charPtr); str.mAllocSizeAndFlags = str.mLength | StrPtrFlag; return str; - } + } + + static StringImpl MakeRef(const char* charPtr, intptr length) + { + StringImpl str; + // This is just a ref - called when we pass a literal to a method (for example) + str.mPtr = (char*)charPtr; + str.mLength = (int_strsize)length; + str.mAllocSizeAndFlags = str.mLength | StrPtrFlag; + return str; + } static StringImpl MakeRef(const StringView& strView) { diff --git a/IDE/src/Compiler/BfSystem.bf b/IDE/src/Compiler/BfSystem.bf index 0d7b93ee..cd1b057e 100644 --- a/IDE/src/Compiler/BfSystem.bf +++ b/IDE/src/Compiler/BfSystem.bf @@ -51,7 +51,7 @@ namespace IDE.Compiler static extern char8* BfSystem_GetNamespaceSearch(void* bfSystem, char8* typeName, void* project); [CallingConvention(.Stdcall), CLink] - static extern void* BfSystem_CreateProject(void* bfSystem, char8* projectName); + static extern void* BfSystem_CreateProject(void* bfSystem, char8* projectName, char8* projectDir); [CallingConvention(.Stdcall), CLink] static extern void BfSystem_ClearTypeOptions(void* bfSystem); @@ -142,7 +142,7 @@ namespace IDE.Compiler { using (mMonitor.Enter()) { - var bfProject = CreateProject(project.mProjectName); + var bfProject = CreateProject(project.mProjectName, project.mProjectDir); mProjectMap[project] = bfProject; } } @@ -188,10 +188,10 @@ namespace IDE.Compiler outNamespaceSearch.Append(namespaceSearch); } - public BfProject CreateProject(String projectName) + public BfProject CreateProject(String projectName, String projectDir) { BfProject project = new BfProject(); - project.mNativeBfProject = BfSystem_CreateProject(mNativeBfSystem, projectName); + project.mNativeBfProject = BfSystem_CreateProject(mNativeBfSystem, projectName, projectDir); return project; } diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 0131b705..14271dd5 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -9167,6 +9167,13 @@ namespace IDE bool doCompile = false; if (lastCompileHadMessages) doCompile = true; + + bool needsComptime = true; + for (var project in mWorkspace.mProjects) + { + //Set needsComptime + } + if ((!workspaceOptions.mIncrementalBuild) && (!lastCompileHadMessages)) { tryQueueFiles = false; @@ -9177,6 +9184,9 @@ namespace IDE } } + if (needsComptime) + tryQueueFiles = true; + if (hotProject != null) { mWorkspace.mHadHotCompileSinceLastFullCompile = true; @@ -9210,6 +9220,9 @@ namespace IDE } } + if (needsComptime) + doCompile = true; + if (!success) { bfCompiler.QueueDeletePassInstance(passInstance); diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 9be06ac6..f05743fa 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -2927,7 +2927,7 @@ void BfCompiler::GenerateDynCastData() void BfCompiler::UpdateRevisedTypes() { - BfLogSysM("UpdateRevisedTypes\n"); + BfLogSysM("BfCompiler::UpdateRevisedTypes\n"); BP_ZONE("BfCompiler::UpdateRevisedTypes"); // See if we have any name conflicts and remove those diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index f338c2f1..81bd8c6a 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -26,6 +26,7 @@ #include "BfSourceClassifier.h" #include "BfAutoComplete.h" #include "BfResolvePass.h" +#include "CeMachine.h" #pragma warning(pop) @@ -1850,6 +1851,7 @@ void BfContext::PreUpdateRevisedTypes() void BfContext::UpdateRevisedTypes() { BP_ZONE("BfContext::UpdateRevisedTypes"); + BfLogSysM("BfContext::UpdateRevisedTypes\n"); int wantPtrSize; if ((mCompiler->mOptions.mMachineType == BfMachineType_x86) | @@ -1889,6 +1891,9 @@ void BfContext::UpdateRevisedTypes() bool wantsDebugInfo = (mCompiler->mOptions.mEmitDebugInfo); Array defStateChangedQueue; + Array defEmitParentCheckQueue; + + Dictionary lastWriteTimeMap; // Do primary 'rebuild' scan for (auto type : mResolvedTypes) @@ -1917,20 +1922,8 @@ void BfContext::UpdateRevisedTypes() auto typeDef = typeInst->mTypeDef; - if (typeDef->mEmitParent != NULL) - { - if (typeDef->mDefState == BfTypeDef::DefState_Deleted) - { - typeInst->mTypeDef = typeDef->mEmitParent; - } - else - { - auto emitTypeDef = typeDef; - typeDef = typeDef->mEmitParent; - if (typeDef->mNextRevision != NULL) - emitTypeDef->mDefState = BfTypeDef::DefState_EmittedDirty; - } - } + if (typeDef->mEmitParent != NULL) + defEmitParentCheckQueue.Add(typeInst); if (typeDef->mProject->mDisabled) { @@ -1939,7 +1932,7 @@ void BfContext::UpdateRevisedTypes() } typeInst->mRebuildFlags = BfTypeRebuildFlag_None; - + if (typeDef->mIsPartial) { // This was a type that wasn't marked as partial before but now it is, so it doesn't need its own typedef @@ -1948,6 +1941,31 @@ void BfContext::UpdateRevisedTypes() continue; } + if (typeInst->mCeTypeInfo != NULL) + { + bool changed = false; + + for (auto& kv : typeInst->mCeTypeInfo->mRebuildMap) + { + if (kv.mKey.mKind == CeRebuildKey::Kind_File) + { + String* keyPtr = NULL; + uint64* valuePtr = NULL; + if (lastWriteTimeMap.TryAdd(kv.mKey.mString, &keyPtr, &valuePtr)) + { + *valuePtr = BfpFile_GetTime_LastWrite(kv.mKey.mString.c_str()); + } + if (*valuePtr != kv.mValue.mInt) + changed = true; + } + } + + if (changed) + { + RebuildType(typeInst); + } + } + if ((typeInst->mHotTypeData != NULL) && (!mCompiler->IsHotCompile())) { if (typeInst->mHotTypeData->GetLatestVersion()->mDeclHotCompileIdx != 0) @@ -2042,6 +2060,31 @@ void BfContext::UpdateRevisedTypes() } } + for (auto typeInst : defEmitParentCheckQueue) + { + if (typeInst->IsDeleting()) + continue; + auto typeDef = typeInst->mTypeDef; + if (typeDef->mEmitParent != NULL) + { + if (typeDef->mDefState == BfTypeDef::DefState_Deleted) + { + BfLogSysM("Type %p typeDef %p deleted, setting to emitParent %p\n", typeInst, typeDef, typeDef->mEmitParent); + typeInst->mTypeDef = typeDef->mEmitParent; + } + else + { + auto emitTypeDef = typeDef; + typeDef = typeDef->mEmitParent; + if (typeDef->mNextRevision != NULL) + { + BfLogSysM("Type %p typeDef %p emitparent %p has next revision, setting emittedDirty\n", typeInst, emitTypeDef, typeDef); + emitTypeDef->mDefState = BfTypeDef::DefState_EmittedDirty; + } + } + } + } + // { AutoCrit autoCrit(mSystem->mDataLock); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 5db8dfee..265031d5 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -14543,8 +14543,10 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs { if (typeInstance->IsObject()) { + bool hasRealtimeLeakCheck = (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!IsComptime()); + bool wantsCtorClear = true; - if (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck) + if (hasRealtimeLeakCheck) { // Dbg_ObjectAlloc clears internally so we don't need to call CtorClear for those if ((!isStackAlloc) && (!allocTarget.mCustomAllocator) && (allocTarget.mScopedInvocationTarget == NULL)) @@ -14566,7 +14568,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs } } - if ((!mModule->mIsComptimeModule) && (isStackAlloc) && (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck)) + if ((!mModule->mIsComptimeModule) && (isStackAlloc) && (hasRealtimeLeakCheck)) { BfMethodInstance* markMethod = mModule->GetRawMethodByName(mModule->mContext->mBfObjectType, "GCMarkMembers"); BF_ASSERT(markMethod != NULL); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index c2407a3e..d51544c7 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -4297,7 +4297,7 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance, int ceExecuteId = -1; if (mCompiler->mCEMachine != NULL) ceExecuteId = mCompiler->mCEMachine->mExecuteId; - + BfTypeState typeState; typeState.mType = mCurTypeInstance; typeState.mCurTypeDef = fieldDef->mDeclaringType; diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 70fa7133..73b8459f 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -1189,7 +1189,10 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType } } - BfLogSysM("PopulateType: %p %s populateType:%d ResolveOnly:%d Reified:%d AutoComplete:%d Ctx:%p Mod:%p TypeId:%d\n", resolvedTypeRef, TypeToString(resolvedTypeRef, BfTypeNameFlags_None).c_str(), populateType, mCompiler->mIsResolveOnly, mIsReified, mCompiler->IsAutocomplete(), mContext, this, resolvedTypeRef->mTypeId); + BfTypeDef* typeDef = NULL; + if (typeInstance != NULL) + typeDef = typeInstance->mTypeDef; + BfLogSysM("PopulateType: %p %s populateType:%d ResolveOnly:%d Reified:%d AutoComplete:%d Ctx:%p Mod:%p TypeId:%d TypeDef:%p\n", resolvedTypeRef, TypeToString(resolvedTypeRef, BfTypeNameFlags_None).c_str(), populateType, mCompiler->mIsResolveOnly, mIsReified, mCompiler->IsAutocomplete(), mContext, this, resolvedTypeRef->mTypeId, typeDef); BF_ASSERT(!resolvedTypeRef->IsDeleting()); } @@ -2078,7 +2081,7 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn { for (int ifaceTypeId : ceEmitContext->mInterfaces) typeInstance->mCeTypeInfo->mPendingInterfaces.Add(ifaceTypeId); - + if (ceEmitContext->mEmitData.IsEmpty()) return; @@ -2166,12 +2169,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* if (!attrType->IsValuelessType()) args.Add(attrVal); args.Add(mBfIRBuilder->CreateTypeOf(typeInstance)); - - //TESTING -// mCompiler->mCEMachine->ReleaseContext(ceContext); -// ceContext = mCompiler->mCEMachine->AllocContext(); -// ceContext->mMemory.mSize = ceContext->mMemory.mAllocSize; - + auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL); if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted) @@ -2182,7 +2180,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* // We populated before we could finish AssertErrorState(); } - else + else { auto owner = methodInstance->GetOwner(); int typeId = owner->mTypeId; @@ -3732,6 +3730,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (typeInstance->mTypeDef != innerTypeInst->mTypeDef) { // Rebuild with proper typedef (generally from inner type comptime emission) + BfLogSysM("Boxed type %p overriding typeDef to %p from inner type %p\n", typeInstance, innerTypeInst->mTypeDef, innerType); typeInstance->mTypeDef = innerTypeInst->mTypeDef; DoPopulateType(resolvedTypeRef, populateType); return; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 9b9a1321..f02f097c 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -1823,23 +1823,7 @@ public: String mEmitData; }; -class BfCeTypeInfo -{ -public: - Dictionary mOnCompileMap; - Dictionary mTypeIFaceMap; - Array mPendingInterfaces; - Val128 mHash; - bool mFailed; - BfCeTypeInfo* mNext; - -public: - BfCeTypeInfo() - { - mFailed = false; - mNext = NULL; - } -}; +class BfCeTypeInfo; // Instance of struct or class class BfTypeInstance : public BfDependedType diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index de407542..236f5406 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -4159,11 +4159,12 @@ BF_EXPORT const char* BF_CALLTYPE BfSystem_GetNamespaceSearch(BfSystem* bfSystem return outString.c_str(); } -BF_EXPORT BfProject* BF_CALLTYPE BfSystem_CreateProject(BfSystem* bfSystem, const char* projectName) +BF_EXPORT BfProject* BF_CALLTYPE BfSystem_CreateProject(BfSystem* bfSystem, const char* projectName, const char* projectDir) { AutoCrit autoCrit(bfSystem->mDataLock); BfProject* bfProject = new BfProject(); bfProject->mName = projectName; + bfProject->mDirectory = projectDir; bfProject->mSystem = bfSystem; bfProject->mIdx = (int)bfSystem->mProjects.size(); bfSystem->mProjects.push_back(bfProject); diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 1a4fbd93..4a0184c9 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -1180,6 +1180,7 @@ public: BfSystem* mSystem; String mName; String mSafeName; + String mDirectory; Array mDependencies; BfTargetType mTargetType; BfCodeGenOptions mCodeGenOptions; diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index b8054687..d29d2d40 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -6,6 +6,8 @@ #include "BfReducer.h" #include "BfExprEvaluator.h" #include "../Backend/BeIRCodeGen.h" +#include "BeefySysLib/platform/PlatformHelper.h" + extern "C" { #include "BeefySysLib/third_party/utf8proc/utf8proc.h" @@ -301,6 +303,24 @@ static int DoubleToString(double d, char* outStr) ////////////////////////////////////////////////////////////////////////// +CeInternalData::~CeInternalData() +{ + switch (mKind) + { + case Kind_File: + BfpFile_Release(mFile); + break; + case Kind_FindFileData: + BfpFindFileData_Release(mFindFileData); + break; + case Kind_Spawn: + BfpSpawn_Release(mSpawn); + break; + } +} + +////////////////////////////////////////////////////////////////////////// + CeFunction::~CeFunction() { BF_ASSERT(mId == -1); @@ -1316,6 +1336,11 @@ void CeBuilder::Build() if (mCeFunction->mInitializeState == CeFunction::InitializeState_Initialized) return; + if (methodInstance->mMethodDef->mName == "DecodeToUTF8") + { + NOP; + } + if (!dupMethodInstance.mIRFunction) { mCeFunction->mFailed = true; @@ -2886,6 +2911,7 @@ CeContext::CeContext() CeContext::~CeContext() { delete mHeap; + BF_ASSERT(mInternalDataMap.IsEmpty()); } BfError* CeContext::Fail(const StringImpl& error) @@ -2996,6 +3022,17 @@ BfError* CeContext::Fail(const CeFrame& curFrame, const StringImpl& str) ////////////////////////////////////////////////////////////////////////// +void CeContext::AddRebuild(const CeRebuildKey& key, const CeRebuildValue& value) +{ + if (mCurModule == NULL) + return; + if (mCurModule->mCurTypeInstance == NULL) + return; + if (mCurModule->mCurTypeInstance->mCeTypeInfo == NULL) + mCurModule->mCurTypeInstance->mCeTypeInfo = new BfCeTypeInfo(); + mCurModule->mCurTypeInstance->mCeTypeInfo->mRebuildMap[key] = value; +} + uint8* CeContext::CeMalloc(int size) { #ifdef CE_ENABLE_HEAP @@ -4308,6 +4345,59 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns return false; \ } +#define CE_CHECKADDR_STR(STRNAME, ADDR) \ + { \ + addr_ce checkAddr = ADDR; \ + while (true) \ + { \ + if ((uintptr)checkAddr >= (uintptr)memSize) \ + { \ + break; \ + } \ + if (memStart[checkAddr] == 0) \ + { \ + CE_CHECKADDR(ADDR, checkAddr - ADDR + 1); \ + STRNAME = String::MakeRef((char*)memStart + ADDR, checkAddr - ADDR + 1); \ + break; \ + } \ + checkAddr++; \ + } \ + } + +#define CE_GET_INTERNAL(VAR, ID, KIND) \ + if (!mInternalDataMap.TryGetValue((int)ID, &VAR)) \ + { \ + _Fail("Invalid internal resource id"); \ + return false; \ + } \ + if (VAR->mKind != KIND) \ + { \ + _Fail("Invalid internal resource kind"); \ + return false; \ + } \ + if (VAR->mReleased) \ + { \ + _Fail("Resource already released"); \ + return false; \ + } + +#define CE_REMOVE_INTERNAL(VAR, ID, KIND) \ + if (!mInternalDataMap.Remove((int)ID, &VAR)) \ + { \ + _Fail("Invalid internal resource id"); \ + return false; \ + } \ + if (VAR->mKind != KIND) \ + { \ + _Fail("Invalid internal resource kind"); \ + return false; \ + } \ + if (VAR->mReleased) \ + { \ + _Fail("Resource already released"); \ + return false; \ + } + #define CE_GETINST(T) *((T*)(instPtr += sizeof(T)) - 1) #define CE_GETFRAME(T) *(T*)(framePtr + *((int32*)(instPtr += sizeof(int32)) - 1)) #define CEOP_BIN(OP, T) \ @@ -4422,7 +4512,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns instPtr = &ceFunction->mCode[0]; \ CE_CHECKSTACK(); -static void CeSetAddrVal(void* ptr, addr_ce val, int32 ptrSize) +static void CeSetAddrVal(void* ptr, int64 val, int32 ptrSize) { if (ptrSize == 4) *(int32*)(ptr) = (int32)val; @@ -4559,8 +4649,16 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* } else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite_Int) { - int32 intVal = *(int32*)((uint8*)stackPtr + 0); - OutputDebugStrF("Debug Val: %d\n", intVal); + if (ceModule->mSystem->mPtrSize == 4) + { + int32 intVal = *(int32*)((uint8*)stackPtr + 0); + OutputDebugStrF("Debug Val: %d\n", intVal); + } + else + { + int64 intVal = *(int64*)((uint8*)stackPtr + 0); + OutputDebugStrF("Debug Val: %lld\n", intVal); + } } else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectType) { @@ -4911,7 +5009,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* addr_ce strAddr = *(addr_ce*)((uint8*)stackPtr + 8); addr_ce endAddr = *(addr_ce*)((uint8*)stackPtr + 8 + ptrSize); - addr_ce checkAddr = strAddr; + addr_ce checkAddr = strAddr; while (true) { if ((uintptr)checkAddr >= (uintptr)memSize) @@ -4921,10 +5019,11 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* } if (memStart[checkAddr] == 0) break; + checkAddr++; } CE_CHECKADDR(strAddr, checkAddr - strAddr + 1); - char* strPtr = (char*)(memStart + strAddr); + char* strPtr = (char*)(memStart + strAddr); char** endPtr = NULL; if (endAddr != NULL) endPtr = (char**)(memStart + endAddr); @@ -4959,7 +5058,281 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* memcpy(memStart + strAddr, str, count + 1); result = count; } - else + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Close) + { + addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 0); + addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize); + + CE_CHECKADDR(outResultAddr, 4); + + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File); + BfpFile_Close(internalData->mFile, (BfpFileResult*)(memStart + outResultAddr)); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Create) + { + void* resultPtr = ((uint8*)stackPtr + 0); + addr_ce nameAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize); + int createKind = *(int*)((uint8*)stackPtr + ptrSize + ptrSize); + int createFlags = *(int*)((uint8*)stackPtr + ptrSize + ptrSize + 4); + int createFileAttrs = *(int*)((uint8*)stackPtr + ptrSize + ptrSize + 4 + 4); + addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + 4 + 4 + 4); + + String path; + CE_CHECKADDR_STR(path, nameAddr); + CE_CHECKADDR(outResultAddr, 4); + + BfProject* activeProject = NULL; + auto activeTypeDef = mCurModule->GetActiveTypeDef(); + if (activeTypeDef != NULL) + activeProject = activeTypeDef->mProject; + if (activeProject != NULL) + path = GetAbsPath(path, activeProject->mDirectory); + + auto bfpFile = BfpFile_Create(path.c_str(), (BfpFileCreateKind)createKind, (BfpFileCreateFlags)createFlags, (BfpFileAttributes)createFileAttrs, (BfpFileResult*)(memStart + outResultAddr)); + if (bfpFile != NULL) + { + if ((createKind == BfpFileCreateKind_OpenExisting) || (createKind == BfpFileCreateKind_OpenAlways)) + { + auto timeStamp = BfpFile_GetTime_LastWrite(path.c_str()); + if (timeStamp != 0) + { + CeRebuildKey rebuildKey; + rebuildKey.mKind = CeRebuildKey::Kind_File; + rebuildKey.mString = path; + + CeRebuildValue rebuildValue; + rebuildValue.mInt = timeStamp; + + AddRebuild(rebuildKey, rebuildValue); + } + } + + CeInternalData* internalData = new CeInternalData(); + internalData->mKind = CeInternalData::Kind_File; + internalData->mFile = bfpFile; + mInternalDataMap[++mCurHandleId] = internalData; + CeSetAddrVal(resultPtr, mCurHandleId, ptrSize); + } + else + CeSetAddrVal(resultPtr, 0, ptrSize); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Flush) + { + addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 0); + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File); + BfpFile_Flush(internalData->mFile); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_GetFileSize) + { + int64& result = *(int64*)((uint8*)stackPtr + 0); + addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 8); + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File); + result = BfpFile_GetFileSize(internalData->mFile); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Read) + { + void* resultPtr = ((uint8*)stackPtr + 0); + addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + ptrSize); + addr_ce bufferPtr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize); + intptr bufferSize = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize); + int timeoutMS = *(int32*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize); + addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize + ptrSize); + + CE_CHECKADDR(bufferPtr, bufferSize); + CE_CHECKADDR(outResultAddr, 4); + + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File); + int64 result = BfpFile_Read(internalData->mFile, memStart + bufferPtr, bufferSize, timeoutMS, (BfpFileResult*)(memStart + outResultAddr)); + CeSetAddrVal(resultPtr, result, ptrSize); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Release) + { + addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 0); + + CeInternalData* internalData = NULL; + CE_REMOVE_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File); + delete internalData; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Seek) + { + int64& result = *(int64*)((uint8*)stackPtr + 0); + addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 8); + int64 offset = *(int64*)((uint8*)stackPtr + 8 + ptrSize); + int seekKind = *(int*)((uint8*)stackPtr + 8 + ptrSize + 8); + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File); + result = BfpFile_Seek(internalData->mFile, offset, (BfpFileSeekKind)seekKind); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Truncate) + { + addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 0); + addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize); + + CE_CHECKADDR(outResultAddr, 4); + + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File); + BfpFile_Truncate(internalData->mFile, (BfpFileResult*)(memStart + outResultAddr)); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Write) + { + void* resultPtr = ((uint8*)stackPtr + 0); + addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + ptrSize); + addr_ce bufferPtr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize); + intptr bufferSize = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize); + int timeoutMS = *(int32*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize); + addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize + ptrSize); + + CE_CHECKADDR(bufferPtr, bufferSize); + CE_CHECKADDR(outResultAddr, 4); + + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File); + int64 result = BfpFile_Write(internalData->mFile, memStart + bufferPtr, bufferSize, timeoutMS, (BfpFileResult*)(memStart + outResultAddr)); + CeSetAddrVal(resultPtr, result, ptrSize); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSpawn_Create) + { + void* resultPtr = ((uint8*)stackPtr + 0); + addr_ce targetPathAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize); + addr_ce argsAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize); + addr_ce workingDirAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize); + addr_ce envAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize); + int flags = *(int*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize + ptrSize); + addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize + ptrSize + ptrSize); + + String targetPath; + CE_CHECKADDR_STR(targetPath, targetPathAddr); + String args; + CE_CHECKADDR_STR(args, argsAddr); + String workingDir; + CE_CHECKADDR_STR(workingDir, workingDirAddr); + String env; + CE_CHECKADDR_STR(env, envAddr); + CE_CHECKADDR(outResultAddr, 4); + + BfProject* activeProject = NULL; + auto activeTypeDef = mCurModule->GetActiveTypeDef(); + if (activeTypeDef != NULL) + activeProject = activeTypeDef->mProject; + if (activeProject != NULL) + targetPath = GetAbsPath(targetPath, activeProject->mDirectory); + + auto bfpSpawn = BfpSpawn_Create(targetPath.c_str(), args.c_str(), workingDir.c_str(), env.c_str(), (BfpSpawnFlags)flags, (BfpSpawnResult*)(memStart + outResultAddr)); + if (bfpSpawn != NULL) + { + CeInternalData* internalData = new CeInternalData(); + internalData->mKind = CeInternalData::Kind_Spawn; + internalData->mSpawn = bfpSpawn; + mInternalDataMap[++mCurHandleId] = internalData; + CeSetAddrVal(resultPtr, mCurHandleId, ptrSize); + } + else + CeSetAddrVal(resultPtr, 0, ptrSize); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSpawn_GetStdHandles) + { + addr_ce spawnId = *(addr_ce*)((uint8*)stackPtr + 0); + addr_ce outStdInAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize); + addr_ce outStdOutAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize); + addr_ce outStdErrAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize); + + CE_CHECKADDR(outStdInAddr, ptrSize); + CE_CHECKADDR(outStdOutAddr, ptrSize); + CE_CHECKADDR(outStdErrAddr, ptrSize); + + BfpFile* outStdIn = NULL; + BfpFile* outStdOut = NULL; + BfpFile* outStdErr = NULL; + + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)spawnId, CeInternalData::Kind_Spawn); + BfpSpawn_GetStdHandles(internalData->mSpawn, + (outStdInAddr != 0) ? &outStdIn : NULL, + (outStdOutAddr != 0) ? &outStdOut : NULL, + (outStdErrAddr != 0) ? &outStdErr : NULL); + + auto _SetHandle = [&](addr_ce addr, BfpFile* file) + { + if (addr == 0) + return; + if (file != NULL) + { + CeInternalData* internalData = new CeInternalData(); + internalData->mKind = CeInternalData::Kind_File; + internalData->mFile = file; + mInternalDataMap[++mCurHandleId] = internalData; + CeSetAddrVal(memStart + addr, mCurHandleId, ptrSize); + } + }; + + _SetHandle(outStdInAddr, outStdIn); + _SetHandle(outStdOutAddr, outStdOut); + _SetHandle(outStdErrAddr, outStdErr); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSpawn_Kill) + { + addr_ce spawnId = *(addr_ce*)((uint8*)stackPtr + 0); + int exitCode = *(int*)((uint8*)stackPtr + ptrSize); + int killFlags = *(int*)((uint8*)stackPtr + ptrSize + ptrSize); + addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize); + + CE_CHECKADDR(outResultAddr, 4); + + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)spawnId, CeInternalData::Kind_Spawn); + BfpSpawn_Kill(internalData->mSpawn, exitCode, (BfpKillFlags)killFlags, (BfpSpawnResult*)(memStart + outResultAddr)); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSpawn_Release) + { + addr_ce spawnId = *(addr_ce*)((uint8*)stackPtr + 0); + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)spawnId, CeInternalData::Kind_Spawn); + internalData->mReleased = true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSpawn_WaitFor) + { + bool& result = *(bool*)((uint8*)stackPtr + 0); + addr_ce spawnId = *(addr_ce*)((uint8*)stackPtr + 1); + int waitMS = *(int*)((uint8*)stackPtr + 1 + ptrSize); + addr_ce outExitCodeAddr = *(addr_ce*)((uint8*)stackPtr + 1 + ptrSize + ptrSize); + addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + 1 + ptrSize + ptrSize + ptrSize); + + CE_CHECKADDR(outExitCodeAddr, ptrSize); + CE_CHECKADDR(outResultAddr, 4); + + CeInternalData* internalData = NULL; + CE_GET_INTERNAL(internalData, (int)spawnId, CeInternalData::Kind_Spawn); + + int timeLeft = waitMS; + do + { + if (*fastFinishPtr) + { + result = false; + break; + } + + int waitTime = 20; + if (timeLeft >= 0) + { + waitTime = BF_MIN(timeLeft, 20); + timeLeft -= waitTime; + } + + int outExitCode = 0; + result = BfpSpawn_WaitFor(internalData->mSpawn, waitTime, &outExitCode, (BfpSpawnResult*)(memStart + outResultAddr)); + if (result) + break; + if (waitTime == 0) + break; + } while (true); + } + else { Fail(_GetCurFrame(), StrFormat("Unable to invoke extern method '%s'", ceModule->MethodToString(checkFunction->mMethodInstance).c_str())); return false; @@ -5005,6 +5378,17 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* ++instIdx; + if (instIdx >= /*0xBC0*/0xBA0) + { + NOP; + } + +// if (instIdx == 0x444) +// { +// _CrtCheckMemory(); +// NOP; +// } + CeOp op = CE_GETINST(CeOp); switch (op) { @@ -5580,7 +5964,12 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* auto valueType = bfType->ToTypeInstance(); if (valueType->mVirtualMethodTable.IsEmpty()) - ceModule->PopulateType(valueType, BfPopulateType_DataAndMethods); + ceModule->PopulateType(valueType, BfPopulateType_Full_Force); + if (valueType->mVirtualMethodTable.IsEmpty()) + { + _Fail("Empty virtual table"); + return false; + } auto methodInstance = (BfMethodInstance*)valueType->mVirtualMethodTable[virtualIdx].mImplementingMethod; auto callFunction = mCeMachine->GetPreparedFunction(methodInstance); @@ -6338,6 +6727,8 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* _Fail("Unhandled op"); return false; } + + //BF_ASSERT(_CrtCheckMemory() != 0); } return true; @@ -6359,7 +6750,7 @@ CeMachine::CeMachine(BfCompiler* compiler) mCurBuilder = NULL; mPreparingFunction = NULL; - mCurEmitContext = NULL; + mCurEmitContext = NULL; mAppendAllocInfo = NULL; mTempParser = NULL; @@ -6893,6 +7284,34 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction) { if (methodDef->mName == "BfpSystem_GetTimeStamp") ceFunction->mFunctionKind = CeFunctionKind_BfpSystem_GetTimeStamp; + else if (methodDef->mName == "BfpFile_Close") + ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Close; + else if (methodDef->mName == "BfpFile_Create") + ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Create; + else if (methodDef->mName == "BfpFile_Flush") + ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Flush; + else if (methodDef->mName == "BfpFile_GetFileSize") + ceFunction->mFunctionKind = CeFunctionKind_BfpFile_GetFileSize; + else if (methodDef->mName == "BfpFile_Read") + ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Read; + else if (methodDef->mName == "BfpFile_Release") + ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Release; + else if (methodDef->mName == "BfpFile_Seek") + ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Seek; + else if (methodDef->mName == "BfpFile_Truncate") + ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Truncate; + else if (methodDef->mName == "BfpFile_Write") + ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Write; + else if (methodDef->mName == "BfpSpawn_Create") + ceFunction->mFunctionKind = CeFunctionKind_BfpSpawn_Create; + else if (methodDef->mName == "BfpSpawn_GetStdHandles") + ceFunction->mFunctionKind = CeFunctionKind_BfpSpawn_GetStdHandles; + else if (methodDef->mName == "BfpSpawn_Kill") + ceFunction->mFunctionKind = CeFunctionKind_BfpSpawn_Kill; + else if (methodDef->mName == "BfpSpawn_Release") + ceFunction->mFunctionKind = CeFunctionKind_BfpSpawn_Release; + else if (methodDef->mName == "BfpSpawn_WaitFor") + ceFunction->mFunctionKind = CeFunctionKind_BfpSpawn_WaitFor; } else if (owner->IsInstanceOf(mCeModule->mCompiler->mChar32TypeDef)) { @@ -6926,45 +7345,45 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction) { if (methodDef->mName == "Abs") ceFunction->mFunctionKind = CeFunctionKind_Math_Abs; - if (methodDef->mName == "Acos") + else if (methodDef->mName == "Acos") ceFunction->mFunctionKind = CeFunctionKind_Math_Acos; - if (methodDef->mName == "Asin") + else if (methodDef->mName == "Asin") ceFunction->mFunctionKind = CeFunctionKind_Math_Asin; - if (methodDef->mName == "Atan") + else if (methodDef->mName == "Atan") ceFunction->mFunctionKind = CeFunctionKind_Math_Atan; - if (methodDef->mName == "Atan2") + else if (methodDef->mName == "Atan2") ceFunction->mFunctionKind = CeFunctionKind_Math_Atan2; - if (methodDef->mName == "Ceiling") + else if (methodDef->mName == "Ceiling") ceFunction->mFunctionKind = CeFunctionKind_Math_Ceiling; - if (methodDef->mName == "Cos") + else if (methodDef->mName == "Cos") ceFunction->mFunctionKind = CeFunctionKind_Math_Cos; - if (methodDef->mName == "Cosh") + else if (methodDef->mName == "Cosh") ceFunction->mFunctionKind = CeFunctionKind_Math_Cosh; - if (methodDef->mName == "Exp") + else if (methodDef->mName == "Exp") ceFunction->mFunctionKind = CeFunctionKind_Math_Exp; - if (methodDef->mName == "Floor") + else if (methodDef->mName == "Floor") ceFunction->mFunctionKind = CeFunctionKind_Math_Floor; - if (methodDef->mName == "Log") + else if (methodDef->mName == "Log") ceFunction->mFunctionKind = CeFunctionKind_Math_Log; - if (methodDef->mName == "Log10") + else if (methodDef->mName == "Log10") ceFunction->mFunctionKind = CeFunctionKind_Math_Log10; - if (methodDef->mName == "Mod") + else if (methodDef->mName == "Mod") ceFunction->mFunctionKind = CeFunctionKind_Math_Mod; - if (methodDef->mName == "Pow") + else if (methodDef->mName == "Pow") ceFunction->mFunctionKind = CeFunctionKind_Math_Pow; - if (methodDef->mName == "Round") + else if (methodDef->mName == "Round") ceFunction->mFunctionKind = CeFunctionKind_Math_Round; - if (methodDef->mName == "Sin") + else if (methodDef->mName == "Sin") ceFunction->mFunctionKind = CeFunctionKind_Math_Sin; - if (methodDef->mName == "Sinh") + else if (methodDef->mName == "Sinh") ceFunction->mFunctionKind = CeFunctionKind_Math_Sinh; - if (methodDef->mName == "Sqrt") + else if (methodDef->mName == "Sqrt") ceFunction->mFunctionKind = CeFunctionKind_Math_Sqrt; - if (methodDef->mName == "Tan") + else if (methodDef->mName == "Tan") ceFunction->mFunctionKind = CeFunctionKind_Math_Tan; - if (methodDef->mName == "Tanh") + else if (methodDef->mName == "Tanh") ceFunction->mFunctionKind = CeFunctionKind_Math_Tanh; - } + } ceFunction->mInitializeState = CeFunction::InitializeState_Initialized; return; @@ -7214,11 +7633,12 @@ CeContext* CeMachine::AllocContext() ceContext->mMemory.Reserve(BF_CE_INITIAL_MEMORY); } - ceContext->mCurEmitContext = mCurEmitContext; - mCurEmitContext = NULL; + ceContext->mCurEmitContext = mCurEmitContext; + mCurEmitContext = NULL; mExecuteId++; ceContext->mMemory.Resize(BF_CE_STACK_SIZE); ceContext->mExecuteId = mExecuteId; + ceContext->mCurHandleId = 0; return ceContext; } @@ -7234,9 +7654,12 @@ void CeMachine::ReleaseContext(CeContext* ceContext) ceContext->mStaticFieldMap.Clear(); ceContext->mHeap->Clear(BF_CE_MAX_CARRYOVER_HEAP); ceContext->mReflectTypeIdOffset = -1; - mCurEmitContext = ceContext->mCurEmitContext; - ceContext->mCurEmitContext = NULL; + mCurEmitContext = ceContext->mCurEmitContext; + ceContext->mCurEmitContext = NULL; mContextList.Add(ceContext); + for (auto kv : ceContext->mInternalDataMap) + delete kv.mValue; + ceContext->mInternalDataMap.Clear(); } BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray& args, CeEvalFlags flags, BfType* expectingType) @@ -7246,3 +7669,5 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns ReleaseContext(ceContext); return result; } + + diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index ca36f4b0..c8eef486 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -264,6 +264,37 @@ public: } }; +class CeInternalData +{ +public: + enum Kind + { + Kind_None, + Kind_File, + Kind_FindFileData, + Kind_Spawn + }; + +public: + Kind mKind; + bool mReleased; + + union + { + BfpFile* mFile; + BfpFindFileData* mFindFileData; + BfpSpawn* mSpawn; + }; + + CeInternalData() + { + mKind = Kind_None; + mReleased = false; + } + + ~CeInternalData(); +}; + enum CeFunctionKind { CeFunctionKind_NotSet, @@ -294,6 +325,21 @@ enum CeFunctionKind CeFunctionKind_EmitMethodExit, CeFunctionKind_EmitMixin, + CeFunctionKind_BfpFile_Close, + CeFunctionKind_BfpFile_Create, + CeFunctionKind_BfpFile_Flush, + CeFunctionKind_BfpFile_GetFileSize, + CeFunctionKind_BfpFile_Read, + CeFunctionKind_BfpFile_Release, + CeFunctionKind_BfpFile_Seek, + CeFunctionKind_BfpFile_Truncate, + CeFunctionKind_BfpFile_Write, + CeFunctionKind_BfpSpawn_Create, + CeFunctionKind_BfpSpawn_GetStdHandles, + CeFunctionKind_BfpSpawn_Kill, + CeFunctionKind_BfpSpawn_Release, + CeFunctionKind_BfpSpawn_WaitFor, + CeFunctionKind_BfpSystem_GetTimeStamp, CeFunctionKind_Sleep, @@ -328,7 +374,7 @@ enum CeFunctionKind CeFunctionKind_Math_Sinh, CeFunctionKind_Math_Sqrt, CeFunctionKind_Math_Tan, - CeFunctionKind_Math_Tanh, + CeFunctionKind_Math_Tanh, }; class CeConstStructFixup @@ -683,12 +729,40 @@ public: BfIRValue mAppendSizeValue; }; +class CeRebuildKey +{ +public: + enum Kind + { + Kind_None, + Kind_File + }; + +public: + Kind mKind; + String mString; + + bool operator==(const CeRebuildKey& other) const + { + return (mKind == other.mKind) && (mString == other.mString); + } +}; + +class CeRebuildValue +{ +public: + union + { + uint64 mInt; + }; +}; + class CeEmitContext { public: - BfType* mType; + BfType* mType; BfMethodInstance* mMethodInstance; - Array mInterfaces; + Array mInterfaces; String mEmitData; String mExitEmitData; bool mFailed; @@ -706,6 +780,25 @@ public: } }; +class BfCeTypeInfo +{ +public: + Dictionary mOnCompileMap; + Dictionary mTypeIFaceMap; + Array mPendingInterfaces; + Dictionary mRebuildMap; + Val128 mHash; + bool mFailed; + BfCeTypeInfo* mNext; + +public: + BfCeTypeInfo() + { + mFailed = false; + mNext = NULL; + } +}; + class CeContext { public: @@ -724,14 +817,15 @@ public: Dictionary mConstDataMap; HashSet mStaticCtorExecSet; Dictionary mStaticFieldMap; - Dictionary mMemToCtxMap; + Dictionary mInternalDataMap; + int mCurHandleId; BfMethodInstance* mCurMethodInstance; BfType* mCurExpectingType; BfAstNode* mCurTargetSrc; BfModule* mCurModule; CeFrame* mCurFrame; - CeEmitContext* mCurEmitContext; + CeEmitContext* mCurEmitContext; public: CeContext(); @@ -740,6 +834,7 @@ public: BfError* Fail(const StringImpl& error); BfError* Fail(const CeFrame& curFrame, const StringImpl& error); + void AddRebuild(const CeRebuildKey& key, const CeRebuildValue& value); uint8* CeMalloc(int size); bool CeFree(addr_ce addr); addr_ce CeAllocArray(BfArrayType* arrayType, int count, addr_ce& elemsAddr); @@ -791,7 +886,7 @@ public: CeAppendAllocInfo* mAppendAllocInfo; CeContext* mCurContext; - CeEmitContext* mCurEmitContext; + CeEmitContext* mCurEmitContext; CeBuilder* mCurBuilder; CeFunction* mPreparingFunction; @@ -838,3 +933,15 @@ public: }; NS_BF_END + +namespace std +{ + template <> + struct hash + { + size_t operator()(const Beefy::CeRebuildKey& key) const + { + return BeefHash()(key.mString) ^ (size_t)key.mKind; + } + }; +} \ No newline at end of file diff --git a/IDEHelper/Tests/Test0.txt b/IDEHelper/Tests/Test0.txt new file mode 100644 index 00000000..5f0767fa --- /dev/null +++ b/IDEHelper/Tests/Test0.txt @@ -0,0 +1,2 @@ +Test +0 \ No newline at end of file diff --git a/IDEHelper/Tests/src/Comptime.bf b/IDEHelper/Tests/src/Comptime.bf index 453e39c7..326d9e57 100644 --- a/IDEHelper/Tests/src/Comptime.bf +++ b/IDEHelper/Tests/src/Comptime.bf @@ -229,6 +229,9 @@ namespace Tests GC.Mark!((*ptr)); } } + + const String cTest0 = Compiler.ReadText("Test0.txt"); + [Test] public static void TestBasics() { @@ -269,6 +272,8 @@ namespace Tests SerializationContext serCtx = scope .(); iSer.Serialize(serCtx); Test.Assert(serCtx.mStr == "x 10\ny 2\n"); + + Test.Assert(cTest0 == "Test\n0"); } } }