mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Support for comptime file IO and process creation
This commit is contained in:
parent
045e706600
commit
ce4b6e04de
19 changed files with 726 additions and 89 deletions
|
@ -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<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,5 +106,24 @@ namespace System.Diagnostics
|
|||
if (gIsDebuggerPresent)
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,6 +118,9 @@ namespace System
|
|||
|
||||
public this()
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
return;
|
||||
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
bool isWinSrv()
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<BfTypeInstance*> defStateChangedQueue;
|
||||
Array<BfTypeInstance*> defEmitParentCheckQueue;
|
||||
|
||||
Dictionary<String, uint64> 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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1823,23 +1823,7 @@ public:
|
|||
String mEmitData;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
class BfCeTypeInfo;
|
||||
|
||||
// Instance of struct or class
|
||||
class BfTypeInstance : public BfDependedType
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1180,6 +1180,7 @@ public:
|
|||
BfSystem* mSystem;
|
||||
String mName;
|
||||
String mSafeName;
|
||||
String mDirectory;
|
||||
Array<BfProject*> mDependencies;
|
||||
BfTargetType mTargetType;
|
||||
BfCodeGenOptions mCodeGenOptions;
|
||||
|
|
|
@ -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<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType)
|
||||
|
@ -7246,3 +7669,5 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
|||
ReleaseContext(ceContext);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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<int32> mInterfaces;
|
||||
Array<int32> mInterfaces;
|
||||
String mEmitData;
|
||||
String mExitEmitData;
|
||||
bool mFailed;
|
||||
|
@ -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
|
||||
{
|
||||
public:
|
||||
|
@ -724,14 +817,15 @@ public:
|
|||
Dictionary<Val128, addr_ce> mConstDataMap;
|
||||
HashSet<int> mStaticCtorExecSet;
|
||||
Dictionary<String, CeStaticFieldInfo> mStaticFieldMap;
|
||||
Dictionary<void*, addr_ce> mMemToCtxMap;
|
||||
Dictionary<int, CeInternalData*> 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<Beefy::CeRebuildKey>
|
||||
{
|
||||
size_t operator()(const Beefy::CeRebuildKey& key) const
|
||||
{
|
||||
return BeefHash<Beefy::String>()(key.mString) ^ (size_t)key.mKind;
|
||||
}
|
||||
};
|
||||
}
|
2
IDEHelper/Tests/Test0.txt
Normal file
2
IDEHelper/Tests/Test0.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Test
|
||||
0
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue