1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Support for comptime file IO and process creation

This commit is contained in:
Brian Fiete 2021-12-20 09:39:39 -05:00
parent 045e706600
commit ce4b6e04de
19 changed files with 726 additions and 89 deletions

View file

@ -2,6 +2,7 @@ using System.Reflection;
using System.Diagnostics; using System.Diagnostics;
using System.Collections; using System.Collections;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.IO;
namespace System namespace System
{ {
@ -306,5 +307,21 @@ namespace System
if (Compiler.IsComptime) if (Compiler.IsComptime)
Comptime_EmitMixin(text); Comptime_EmitMixin(text);
} }
[Comptime]
public static Span<uint8> ReadBinary(StringView path)
{
List<uint8> data = scope .();
File.ReadAll(path, data);
return data;
}
[Comptime]
public static String ReadText(StringView path)
{
String data = scope .();
File.ReadAllText(path, data);
return data;
}
} }
} }

View file

@ -106,5 +106,24 @@ namespace System.Diagnostics
if (gIsDebuggerPresent) if (gIsDebuggerPresent)
Break(); Break();
} }
public static void WriteMemory(Span<uint8> 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>(T result)
{
#unwarn
WriteMemory(.((.)&result, sizeof(T)));
}
} }
} }

View file

@ -118,6 +118,9 @@ namespace System
public this() public this()
{ {
if (Compiler.IsComptime)
return;
#if BF_PLATFORM_WINDOWS #if BF_PLATFORM_WINDOWS
bool isWinSrv() bool isWinSrv()
{ {

View file

@ -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 //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 (::ReadFileEx(file->mHandle, buffer, (uint32)size, &overlapped, OverlappedReadComplete))
{ {
if (file->mAsyncData == NULL)
{
OUTRESULT(BfpFileResult_InvalidParameter);
return 0;
}
if (!file->mAsyncData->WaitAndResetEvent(timeoutMS)) if (!file->mAsyncData->WaitAndResetEvent(timeoutMS))
{ {
::CancelIoEx(file->mHandle, &overlapped); ::CancelIoEx(file->mHandle, &overlapped);

View file

@ -624,6 +624,16 @@ public:
return str; 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) static StringImpl MakeRef(const StringView& strView)
{ {
StringImpl str; StringImpl str;

View file

@ -51,7 +51,7 @@ namespace IDE.Compiler
static extern char8* BfSystem_GetNamespaceSearch(void* bfSystem, char8* typeName, void* project); static extern char8* BfSystem_GetNamespaceSearch(void* bfSystem, char8* typeName, void* project);
[CallingConvention(.Stdcall), CLink] [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] [CallingConvention(.Stdcall), CLink]
static extern void BfSystem_ClearTypeOptions(void* bfSystem); static extern void BfSystem_ClearTypeOptions(void* bfSystem);
@ -142,7 +142,7 @@ namespace IDE.Compiler
{ {
using (mMonitor.Enter()) using (mMonitor.Enter())
{ {
var bfProject = CreateProject(project.mProjectName); var bfProject = CreateProject(project.mProjectName, project.mProjectDir);
mProjectMap[project] = bfProject; mProjectMap[project] = bfProject;
} }
} }
@ -188,10 +188,10 @@ namespace IDE.Compiler
outNamespaceSearch.Append(namespaceSearch); outNamespaceSearch.Append(namespaceSearch);
} }
public BfProject CreateProject(String projectName) public BfProject CreateProject(String projectName, String projectDir)
{ {
BfProject project = new BfProject(); BfProject project = new BfProject();
project.mNativeBfProject = BfSystem_CreateProject(mNativeBfSystem, projectName); project.mNativeBfProject = BfSystem_CreateProject(mNativeBfSystem, projectName, projectDir);
return project; return project;
} }

View file

@ -9167,6 +9167,13 @@ namespace IDE
bool doCompile = false; bool doCompile = false;
if (lastCompileHadMessages) if (lastCompileHadMessages)
doCompile = true; doCompile = true;
bool needsComptime = true;
for (var project in mWorkspace.mProjects)
{
//Set needsComptime
}
if ((!workspaceOptions.mIncrementalBuild) && (!lastCompileHadMessages)) if ((!workspaceOptions.mIncrementalBuild) && (!lastCompileHadMessages))
{ {
tryQueueFiles = false; tryQueueFiles = false;
@ -9177,6 +9184,9 @@ namespace IDE
} }
} }
if (needsComptime)
tryQueueFiles = true;
if (hotProject != null) if (hotProject != null)
{ {
mWorkspace.mHadHotCompileSinceLastFullCompile = true; mWorkspace.mHadHotCompileSinceLastFullCompile = true;
@ -9210,6 +9220,9 @@ namespace IDE
} }
} }
if (needsComptime)
doCompile = true;
if (!success) if (!success)
{ {
bfCompiler.QueueDeletePassInstance(passInstance); bfCompiler.QueueDeletePassInstance(passInstance);

View file

@ -2927,7 +2927,7 @@ void BfCompiler::GenerateDynCastData()
void BfCompiler::UpdateRevisedTypes() void BfCompiler::UpdateRevisedTypes()
{ {
BfLogSysM("UpdateRevisedTypes\n"); BfLogSysM("BfCompiler::UpdateRevisedTypes\n");
BP_ZONE("BfCompiler::UpdateRevisedTypes"); BP_ZONE("BfCompiler::UpdateRevisedTypes");
// See if we have any name conflicts and remove those // See if we have any name conflicts and remove those

View file

@ -26,6 +26,7 @@
#include "BfSourceClassifier.h" #include "BfSourceClassifier.h"
#include "BfAutoComplete.h" #include "BfAutoComplete.h"
#include "BfResolvePass.h" #include "BfResolvePass.h"
#include "CeMachine.h"
#pragma warning(pop) #pragma warning(pop)
@ -1850,6 +1851,7 @@ void BfContext::PreUpdateRevisedTypes()
void BfContext::UpdateRevisedTypes() void BfContext::UpdateRevisedTypes()
{ {
BP_ZONE("BfContext::UpdateRevisedTypes"); BP_ZONE("BfContext::UpdateRevisedTypes");
BfLogSysM("BfContext::UpdateRevisedTypes\n");
int wantPtrSize; int wantPtrSize;
if ((mCompiler->mOptions.mMachineType == BfMachineType_x86) | if ((mCompiler->mOptions.mMachineType == BfMachineType_x86) |
@ -1889,6 +1891,9 @@ void BfContext::UpdateRevisedTypes()
bool wantsDebugInfo = (mCompiler->mOptions.mEmitDebugInfo); bool wantsDebugInfo = (mCompiler->mOptions.mEmitDebugInfo);
Array<BfTypeInstance*> defStateChangedQueue; Array<BfTypeInstance*> defStateChangedQueue;
Array<BfTypeInstance*> defEmitParentCheckQueue;
Dictionary<String, uint64> lastWriteTimeMap;
// Do primary 'rebuild' scan // Do primary 'rebuild' scan
for (auto type : mResolvedTypes) for (auto type : mResolvedTypes)
@ -1918,19 +1923,7 @@ void BfContext::UpdateRevisedTypes()
auto typeDef = typeInst->mTypeDef; auto typeDef = typeInst->mTypeDef;
if (typeDef->mEmitParent != NULL) if (typeDef->mEmitParent != NULL)
{ defEmitParentCheckQueue.Add(typeInst);
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->mProject->mDisabled) if (typeDef->mProject->mDisabled)
{ {
@ -1948,6 +1941,31 @@ void BfContext::UpdateRevisedTypes()
continue; 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 != NULL) && (!mCompiler->IsHotCompile()))
{ {
if (typeInst->mHotTypeData->GetLatestVersion()->mDeclHotCompileIdx != 0) 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); AutoCrit autoCrit(mSystem->mDataLock);

View file

@ -14543,8 +14543,10 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{ {
if (typeInstance->IsObject()) if (typeInstance->IsObject())
{ {
bool hasRealtimeLeakCheck = (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!IsComptime());
bool wantsCtorClear = true; bool wantsCtorClear = true;
if (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck) if (hasRealtimeLeakCheck)
{ {
// Dbg_ObjectAlloc clears internally so we don't need to call CtorClear for those // Dbg_ObjectAlloc clears internally so we don't need to call CtorClear for those
if ((!isStackAlloc) && (!allocTarget.mCustomAllocator) && (allocTarget.mScopedInvocationTarget == NULL)) 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"); BfMethodInstance* markMethod = mModule->GetRawMethodByName(mModule->mContext->mBfObjectType, "GCMarkMembers");
BF_ASSERT(markMethod != NULL); BF_ASSERT(markMethod != NULL);

View file

@ -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()); BF_ASSERT(!resolvedTypeRef->IsDeleting());
} }
@ -2167,11 +2170,6 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
args.Add(attrVal); args.Add(attrVal);
args.Add(mBfIRBuilder->CreateTypeOf(typeInstance)); 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); auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL);
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted) if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
@ -3732,6 +3730,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (typeInstance->mTypeDef != innerTypeInst->mTypeDef) if (typeInstance->mTypeDef != innerTypeInst->mTypeDef)
{ {
// Rebuild with proper typedef (generally from inner type comptime emission) // 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; typeInstance->mTypeDef = innerTypeInst->mTypeDef;
DoPopulateType(resolvedTypeRef, populateType); DoPopulateType(resolvedTypeRef, populateType);
return; return;

View file

@ -1823,23 +1823,7 @@ public:
String mEmitData; String mEmitData;
}; };
class BfCeTypeInfo class BfCeTypeInfo;
{
public:
Dictionary<int, BfCeTypeEmitEntry> mOnCompileMap;
Dictionary<int, BfCeTypeEmitEntry> mTypeIFaceMap;
Array<int> mPendingInterfaces;
Val128 mHash;
bool mFailed;
BfCeTypeInfo* mNext;
public:
BfCeTypeInfo()
{
mFailed = false;
mNext = NULL;
}
};
// Instance of struct or class // Instance of struct or class
class BfTypeInstance : public BfDependedType class BfTypeInstance : public BfDependedType

View file

@ -4159,11 +4159,12 @@ BF_EXPORT const char* BF_CALLTYPE BfSystem_GetNamespaceSearch(BfSystem* bfSystem
return outString.c_str(); 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); AutoCrit autoCrit(bfSystem->mDataLock);
BfProject* bfProject = new BfProject(); BfProject* bfProject = new BfProject();
bfProject->mName = projectName; bfProject->mName = projectName;
bfProject->mDirectory = projectDir;
bfProject->mSystem = bfSystem; bfProject->mSystem = bfSystem;
bfProject->mIdx = (int)bfSystem->mProjects.size(); bfProject->mIdx = (int)bfSystem->mProjects.size();
bfSystem->mProjects.push_back(bfProject); bfSystem->mProjects.push_back(bfProject);

View file

@ -1180,6 +1180,7 @@ public:
BfSystem* mSystem; BfSystem* mSystem;
String mName; String mName;
String mSafeName; String mSafeName;
String mDirectory;
Array<BfProject*> mDependencies; Array<BfProject*> mDependencies;
BfTargetType mTargetType; BfTargetType mTargetType;
BfCodeGenOptions mCodeGenOptions; BfCodeGenOptions mCodeGenOptions;

View file

@ -6,6 +6,8 @@
#include "BfReducer.h" #include "BfReducer.h"
#include "BfExprEvaluator.h" #include "BfExprEvaluator.h"
#include "../Backend/BeIRCodeGen.h" #include "../Backend/BeIRCodeGen.h"
#include "BeefySysLib/platform/PlatformHelper.h"
extern "C" extern "C"
{ {
#include "BeefySysLib/third_party/utf8proc/utf8proc.h" #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() CeFunction::~CeFunction()
{ {
BF_ASSERT(mId == -1); BF_ASSERT(mId == -1);
@ -1316,6 +1336,11 @@ void CeBuilder::Build()
if (mCeFunction->mInitializeState == CeFunction::InitializeState_Initialized) if (mCeFunction->mInitializeState == CeFunction::InitializeState_Initialized)
return; return;
if (methodInstance->mMethodDef->mName == "DecodeToUTF8")
{
NOP;
}
if (!dupMethodInstance.mIRFunction) if (!dupMethodInstance.mIRFunction)
{ {
mCeFunction->mFailed = true; mCeFunction->mFailed = true;
@ -2886,6 +2911,7 @@ CeContext::CeContext()
CeContext::~CeContext() CeContext::~CeContext()
{ {
delete mHeap; delete mHeap;
BF_ASSERT(mInternalDataMap.IsEmpty());
} }
BfError* CeContext::Fail(const StringImpl& error) 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) uint8* CeContext::CeMalloc(int size)
{ {
#ifdef CE_ENABLE_HEAP #ifdef CE_ENABLE_HEAP
@ -4308,6 +4345,59 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
return false; \ 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_GETINST(T) *((T*)(instPtr += sizeof(T)) - 1)
#define CE_GETFRAME(T) *(T*)(framePtr + *((int32*)(instPtr += sizeof(int32)) - 1)) #define CE_GETFRAME(T) *(T*)(framePtr + *((int32*)(instPtr += sizeof(int32)) - 1))
#define CEOP_BIN(OP, T) \ #define CEOP_BIN(OP, T) \
@ -4422,7 +4512,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
instPtr = &ceFunction->mCode[0]; \ instPtr = &ceFunction->mCode[0]; \
CE_CHECKSTACK(); CE_CHECKSTACK();
static void CeSetAddrVal(void* ptr, addr_ce val, int32 ptrSize) static void CeSetAddrVal(void* ptr, int64 val, int32 ptrSize)
{ {
if (ptrSize == 4) if (ptrSize == 4)
*(int32*)(ptr) = (int32)val; *(int32*)(ptr) = (int32)val;
@ -4558,10 +4648,18 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
OutputDebugStr(str); OutputDebugStr(str);
} }
else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite_Int) else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite_Int)
{
if (ceModule->mSystem->mPtrSize == 4)
{ {
int32 intVal = *(int32*)((uint8*)stackPtr + 0); int32 intVal = *(int32*)((uint8*)stackPtr + 0);
OutputDebugStrF("Debug Val: %d\n", intVal); 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) else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectType)
{ {
addr_ce objAddr = *(addr_ce*)((uint8*)stackPtr + ceModule->mSystem->mPtrSize); addr_ce objAddr = *(addr_ce*)((uint8*)stackPtr + ceModule->mSystem->mPtrSize);
@ -4921,6 +5019,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
} }
if (memStart[checkAddr] == 0) if (memStart[checkAddr] == 0)
break; break;
checkAddr++;
} }
CE_CHECKADDR(strAddr, checkAddr - strAddr + 1); CE_CHECKADDR(strAddr, checkAddr - strAddr + 1);
@ -4959,6 +5058,280 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
memcpy(memStart + strAddr, str, count + 1); memcpy(memStart + strAddr, str, count + 1);
result = count; result = count;
} }
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 else
{ {
Fail(_GetCurFrame(), StrFormat("Unable to invoke extern method '%s'", ceModule->MethodToString(checkFunction->mMethodInstance).c_str())); Fail(_GetCurFrame(), StrFormat("Unable to invoke extern method '%s'", ceModule->MethodToString(checkFunction->mMethodInstance).c_str()));
@ -5005,6 +5378,17 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
++instIdx; ++instIdx;
if (instIdx >= /*0xBC0*/0xBA0)
{
NOP;
}
// if (instIdx == 0x444)
// {
// _CrtCheckMemory();
// NOP;
// }
CeOp op = CE_GETINST(CeOp); CeOp op = CE_GETINST(CeOp);
switch (op) switch (op)
{ {
@ -5580,7 +5964,12 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
auto valueType = bfType->ToTypeInstance(); auto valueType = bfType->ToTypeInstance();
if (valueType->mVirtualMethodTable.IsEmpty()) 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 methodInstance = (BfMethodInstance*)valueType->mVirtualMethodTable[virtualIdx].mImplementingMethod;
auto callFunction = mCeMachine->GetPreparedFunction(methodInstance); auto callFunction = mCeMachine->GetPreparedFunction(methodInstance);
@ -6338,6 +6727,8 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
_Fail("Unhandled op"); _Fail("Unhandled op");
return false; return false;
} }
//BF_ASSERT(_CrtCheckMemory() != 0);
} }
return true; return true;
@ -6893,6 +7284,34 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
{ {
if (methodDef->mName == "BfpSystem_GetTimeStamp") if (methodDef->mName == "BfpSystem_GetTimeStamp")
ceFunction->mFunctionKind = CeFunctionKind_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)) else if (owner->IsInstanceOf(mCeModule->mCompiler->mChar32TypeDef))
{ {
@ -6926,43 +7345,43 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
{ {
if (methodDef->mName == "Abs") if (methodDef->mName == "Abs")
ceFunction->mFunctionKind = CeFunctionKind_Math_Abs; ceFunction->mFunctionKind = CeFunctionKind_Math_Abs;
if (methodDef->mName == "Acos") else if (methodDef->mName == "Acos")
ceFunction->mFunctionKind = CeFunctionKind_Math_Acos; ceFunction->mFunctionKind = CeFunctionKind_Math_Acos;
if (methodDef->mName == "Asin") else if (methodDef->mName == "Asin")
ceFunction->mFunctionKind = CeFunctionKind_Math_Asin; ceFunction->mFunctionKind = CeFunctionKind_Math_Asin;
if (methodDef->mName == "Atan") else if (methodDef->mName == "Atan")
ceFunction->mFunctionKind = CeFunctionKind_Math_Atan; ceFunction->mFunctionKind = CeFunctionKind_Math_Atan;
if (methodDef->mName == "Atan2") else if (methodDef->mName == "Atan2")
ceFunction->mFunctionKind = CeFunctionKind_Math_Atan2; ceFunction->mFunctionKind = CeFunctionKind_Math_Atan2;
if (methodDef->mName == "Ceiling") else if (methodDef->mName == "Ceiling")
ceFunction->mFunctionKind = CeFunctionKind_Math_Ceiling; ceFunction->mFunctionKind = CeFunctionKind_Math_Ceiling;
if (methodDef->mName == "Cos") else if (methodDef->mName == "Cos")
ceFunction->mFunctionKind = CeFunctionKind_Math_Cos; ceFunction->mFunctionKind = CeFunctionKind_Math_Cos;
if (methodDef->mName == "Cosh") else if (methodDef->mName == "Cosh")
ceFunction->mFunctionKind = CeFunctionKind_Math_Cosh; ceFunction->mFunctionKind = CeFunctionKind_Math_Cosh;
if (methodDef->mName == "Exp") else if (methodDef->mName == "Exp")
ceFunction->mFunctionKind = CeFunctionKind_Math_Exp; ceFunction->mFunctionKind = CeFunctionKind_Math_Exp;
if (methodDef->mName == "Floor") else if (methodDef->mName == "Floor")
ceFunction->mFunctionKind = CeFunctionKind_Math_Floor; ceFunction->mFunctionKind = CeFunctionKind_Math_Floor;
if (methodDef->mName == "Log") else if (methodDef->mName == "Log")
ceFunction->mFunctionKind = CeFunctionKind_Math_Log; ceFunction->mFunctionKind = CeFunctionKind_Math_Log;
if (methodDef->mName == "Log10") else if (methodDef->mName == "Log10")
ceFunction->mFunctionKind = CeFunctionKind_Math_Log10; ceFunction->mFunctionKind = CeFunctionKind_Math_Log10;
if (methodDef->mName == "Mod") else if (methodDef->mName == "Mod")
ceFunction->mFunctionKind = CeFunctionKind_Math_Mod; ceFunction->mFunctionKind = CeFunctionKind_Math_Mod;
if (methodDef->mName == "Pow") else if (methodDef->mName == "Pow")
ceFunction->mFunctionKind = CeFunctionKind_Math_Pow; ceFunction->mFunctionKind = CeFunctionKind_Math_Pow;
if (methodDef->mName == "Round") else if (methodDef->mName == "Round")
ceFunction->mFunctionKind = CeFunctionKind_Math_Round; ceFunction->mFunctionKind = CeFunctionKind_Math_Round;
if (methodDef->mName == "Sin") else if (methodDef->mName == "Sin")
ceFunction->mFunctionKind = CeFunctionKind_Math_Sin; ceFunction->mFunctionKind = CeFunctionKind_Math_Sin;
if (methodDef->mName == "Sinh") else if (methodDef->mName == "Sinh")
ceFunction->mFunctionKind = CeFunctionKind_Math_Sinh; ceFunction->mFunctionKind = CeFunctionKind_Math_Sinh;
if (methodDef->mName == "Sqrt") else if (methodDef->mName == "Sqrt")
ceFunction->mFunctionKind = CeFunctionKind_Math_Sqrt; ceFunction->mFunctionKind = CeFunctionKind_Math_Sqrt;
if (methodDef->mName == "Tan") else if (methodDef->mName == "Tan")
ceFunction->mFunctionKind = CeFunctionKind_Math_Tan; ceFunction->mFunctionKind = CeFunctionKind_Math_Tan;
if (methodDef->mName == "Tanh") else if (methodDef->mName == "Tanh")
ceFunction->mFunctionKind = CeFunctionKind_Math_Tanh; ceFunction->mFunctionKind = CeFunctionKind_Math_Tanh;
} }
@ -7219,6 +7638,7 @@ CeContext* CeMachine::AllocContext()
mExecuteId++; mExecuteId++;
ceContext->mMemory.Resize(BF_CE_STACK_SIZE); ceContext->mMemory.Resize(BF_CE_STACK_SIZE);
ceContext->mExecuteId = mExecuteId; ceContext->mExecuteId = mExecuteId;
ceContext->mCurHandleId = 0;
return ceContext; return ceContext;
} }
@ -7237,6 +7657,9 @@ void CeMachine::ReleaseContext(CeContext* ceContext)
mCurEmitContext = ceContext->mCurEmitContext; mCurEmitContext = ceContext->mCurEmitContext;
ceContext->mCurEmitContext = NULL; ceContext->mCurEmitContext = NULL;
mContextList.Add(ceContext); 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<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType) BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType)
@ -7246,3 +7669,5 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
ReleaseContext(ceContext); ReleaseContext(ceContext);
return result; return result;
} }

View file

@ -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 enum CeFunctionKind
{ {
CeFunctionKind_NotSet, CeFunctionKind_NotSet,
@ -294,6 +325,21 @@ enum CeFunctionKind
CeFunctionKind_EmitMethodExit, CeFunctionKind_EmitMethodExit,
CeFunctionKind_EmitMixin, 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_BfpSystem_GetTimeStamp,
CeFunctionKind_Sleep, CeFunctionKind_Sleep,
@ -683,6 +729,34 @@ public:
BfIRValue mAppendSizeValue; 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 class CeEmitContext
{ {
public: public:
@ -706,6 +780,25 @@ public:
} }
}; };
class BfCeTypeInfo
{
public:
Dictionary<int, BfCeTypeEmitEntry> mOnCompileMap;
Dictionary<int, BfCeTypeEmitEntry> mTypeIFaceMap;
Array<int> mPendingInterfaces;
Dictionary<CeRebuildKey, CeRebuildValue> mRebuildMap;
Val128 mHash;
bool mFailed;
BfCeTypeInfo* mNext;
public:
BfCeTypeInfo()
{
mFailed = false;
mNext = NULL;
}
};
class CeContext class CeContext
{ {
public: public:
@ -724,7 +817,8 @@ public:
Dictionary<Val128, addr_ce> mConstDataMap; Dictionary<Val128, addr_ce> mConstDataMap;
HashSet<int> mStaticCtorExecSet; HashSet<int> mStaticCtorExecSet;
Dictionary<String, CeStaticFieldInfo> mStaticFieldMap; Dictionary<String, CeStaticFieldInfo> mStaticFieldMap;
Dictionary<void*, addr_ce> mMemToCtxMap; Dictionary<int, CeInternalData*> mInternalDataMap;
int mCurHandleId;
BfMethodInstance* mCurMethodInstance; BfMethodInstance* mCurMethodInstance;
BfType* mCurExpectingType; BfType* mCurExpectingType;
@ -740,6 +834,7 @@ public:
BfError* Fail(const StringImpl& error); BfError* Fail(const StringImpl& error);
BfError* Fail(const CeFrame& curFrame, const StringImpl& error); BfError* Fail(const CeFrame& curFrame, const StringImpl& error);
void AddRebuild(const CeRebuildKey& key, const CeRebuildValue& value);
uint8* CeMalloc(int size); uint8* CeMalloc(int size);
bool CeFree(addr_ce addr); bool CeFree(addr_ce addr);
addr_ce CeAllocArray(BfArrayType* arrayType, int count, addr_ce& elemsAddr); addr_ce CeAllocArray(BfArrayType* arrayType, int count, addr_ce& elemsAddr);
@ -838,3 +933,15 @@ public:
}; };
NS_BF_END NS_BF_END
namespace std
{
template <>
struct hash<Beefy::CeRebuildKey>
{
size_t operator()(const Beefy::CeRebuildKey& key) const
{
return BeefHash<Beefy::String>()(key.mString) ^ (size_t)key.mKind;
}
};
}

View file

@ -0,0 +1,2 @@
Test
0

View file

@ -229,6 +229,9 @@ namespace Tests
GC.Mark!((*ptr)); GC.Mark!((*ptr));
} }
} }
const String cTest0 = Compiler.ReadText("Test0.txt");
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -269,6 +272,8 @@ namespace Tests
SerializationContext serCtx = scope .(); SerializationContext serCtx = scope .();
iSer.Serialize(serCtx); iSer.Serialize(serCtx);
Test.Assert(serCtx.mStr == "x 10\ny 2\n"); Test.Assert(serCtx.mStr == "x 10\ny 2\n");
Test.Assert(cTest0 == "Test\n0");
} }
} }
} }