1
0
Fork 0
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:
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.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;
}
}
}

View file

@ -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)));
}
}
}

View file

@ -118,6 +118,9 @@ namespace System
public this()
{
if (Compiler.IsComptime)
return;
#if BF_PLATFORM_WINDOWS
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
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);

View file

@ -624,6 +624,16 @@ public:
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)
{
StringImpl str;

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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)
@ -1918,19 +1923,7 @@ 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;
}
}
defEmitParentCheckQueue.Add(typeInst);
if (typeDef->mProject->mDisabled)
{
@ -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);

View file

@ -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);

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());
}
@ -2167,11 +2170,6 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
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)
@ -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;

View file

@ -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

View file

@ -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);

View file

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

View file

@ -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;
@ -4558,10 +4648,18 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
OutputDebugStr(str);
}
else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite_Int)
{
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)
{
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)
break;
checkAddr++;
}
CE_CHECKADDR(strAddr, checkAddr - strAddr + 1);
@ -4959,6 +5058,280 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
memcpy(memStart + strAddr, str, count + 1);
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
{
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;
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;
@ -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,43 +7345,43 @@ 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;
}
@ -7219,6 +7638,7 @@ CeContext* CeMachine::AllocContext()
mExecuteId++;
ceContext->mMemory.Resize(BF_CE_STACK_SIZE);
ceContext->mExecuteId = mExecuteId;
ceContext->mCurHandleId = 0;
return ceContext;
}
@ -7237,6 +7657,9 @@ void CeMachine::ReleaseContext(CeContext* ceContext)
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;
}

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
{
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,
@ -683,6 +729,34 @@ 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:
@ -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,7 +817,8 @@ 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;
@ -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);
@ -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;
}
};
}

View file

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

View file

@ -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");
}
}
}