1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Comptime updates, start of metaprogramming support

This commit is contained in:
Brian Fiete 2021-01-08 16:21:03 -08:00
parent be1c099f19
commit 3bbf2d8313
43 changed files with 1562 additions and 885 deletions

View file

@ -728,8 +728,7 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
CeStaticFieldInfo* staticFieldInfoPtr = NULL;
if (mCeMachine->mStaticFieldMap.TryGetValue(globalVar->mName, &staticFieldInfoPtr))
{
CeStaticFieldInfo* staticFieldInfo = staticFieldInfoPtr;
CeStaticFieldInfo* staticFieldInfo = staticFieldInfoPtr;
int* staticFieldTableIdxPtr = NULL;
if (mStaticFieldMap.TryAdd(globalVar, NULL, &staticFieldTableIdxPtr))
{
@ -1190,8 +1189,6 @@ void CeBuilder::Build()
bool isGenericVariation = (methodInstance->mIsUnspecializedVariation) || (methodInstance->GetOwner()->IsUnspecializedTypeVariation());
int dependentGenericStartIdx = 0;
if (methodInstance->mMethodInfoEx != NULL)
dependentGenericStartIdx = (int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size();
if ((((methodInstance->mMethodInfoEx != NULL) && ((int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size() > dependentGenericStartIdx)) ||
((methodInstance->GetOwner()->IsGenericTypeInstance()) && (!isGenericVariation) && (!methodInstance->mMethodDef->mIsLocalMethod))))
{
@ -2646,13 +2643,17 @@ CeMachine::CeMachine(BfCompiler* compiler)
mCurFunctionId = 0;
mRevisionExecuteTime = 0;
mCurTargetSrc = NULL;
mCurBuilder = NULL;
mPreparingFunction = NULL;
mCurEvalFlags = CeEvalFlags_None;
mCurFrame = NULL;
mCurModule = NULL;
mCurMethodInstance = NULL;
mCurExpectingType = NULL;
mCurEmitContext = NULL;
mHeap = NULL;
mStringCharsOffset = -1;
mAppendAllocInfo = NULL;
mAppendAllocInfo = NULL;
}
CeMachine::~CeMachine()
@ -2689,19 +2690,25 @@ CeMachine::~CeMachine()
BfError* CeMachine::Fail(const StringImpl& error)
{
auto bfError = mCurModule->Fail(StrFormat("Unable to const-evaluate %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc);
auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0);
if (bfError == NULL)
return NULL;
mCompiler->mPassInstance->MoreInfo(error);
mCompiler->mPassInstance->MoreInfo(error, mCeModule->mCompiler->GetAutoComplete() != NULL);
return bfError;
}
BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str)
{
auto bfError = mCurModule->Fail(StrFormat("Unable to const-evaluate %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc);
auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0);
if (bfError == NULL)
return NULL;
if ((mCurEvalFlags & CeEvalFlags_DeferIfNotOnlyError) != 0)
{
if (mCurModule->mHadBuildError)
bfError->mIsDeferred = true;
}
auto passInstance = mCompiler->mPassInstance;
for (int stackIdx = mCallStack.size(); stackIdx >= 0; stackIdx--)
@ -2748,7 +2755,7 @@ BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str)
contextMethodInstance = func->mCeFunctionInfo->mMethodInstance;
}
err += StrFormat("in const evaluation of ");
err += StrFormat("in comptime ");
//
{
@ -2766,7 +2773,7 @@ BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str)
if (emitEntry != NULL)
err += StrFormat(" at line% d:%d in %s", emitEntry->mLine + 1, emitEntry->mColumn + 1, ceFunction->mFiles[emitEntry->mFile].c_str());
auto moreInfo = passInstance->MoreInfo(err);
auto moreInfo = passInstance->MoreInfo(err, mCeModule->mCompiler->GetAutoComplete() != NULL);
if ((moreInfo != NULL) && (emitEntry != NULL))
{
BfErrorLocation* location = new BfErrorLocation();
@ -2785,7 +2792,7 @@ void CeMachine::Init()
mCeModule = new BfModule(mCompiler->mContext, "__constEval");
mCeModule->mIsSpecialModule = true;
//mCeModule->mIsScratchModule = true;
mCeModule->mIsConstModule = true;
mCeModule->mIsComptimeModule = true;
//mCeModule->mIsReified = true;
if (mCompiler->mIsResolveOnly)
mCeModule->mIsReified = true;
@ -2882,7 +2889,8 @@ addr_ce CeMachine::GetReflectType(int typeId)
if (bfType == NULL)
return 0;
mCeModule->PopulateType(bfType, BfPopulateType_DataAndMethods);
if (bfType->mDefineState != BfTypeDefineState_CETypeInit)
mCeModule->PopulateType(bfType, BfPopulateType_DataAndMethods);
Dictionary<int, int> usedStringMap;
auto irData = mCeModule->CreateTypeData(bfType, usedStringMap, true, true, true, false);
@ -2991,6 +2999,30 @@ void CeMachine::PrepareConstStructEntry(CeConstStructData& constEntry)
constEntry.mBindExecuteId = mExecuteId;
}
bool CeMachine::CheckMemory(addr_ce addr, int32 size)
{
if (((addr)-0x10000) + (size) > (mMemory.mSize - 0x10000))
return false;
return true;
}
bool CeMachine::GetStringFromStringView(addr_ce addr, StringImpl& str)
{
int ptrSize = mCeModule->mSystem->mPtrSize;
if (!CheckMemory(addr, ptrSize * 2))
return false;
addr_ce charsPtr = *(addr_ce*)(mMemory.mVals + addr);
int32 len = *(int32*)(mMemory.mVals + addr + ptrSize);
if (!CheckMemory(charsPtr, len))
return false;
str.Append((const char*)(mMemory.mVals + charsPtr), len);
return true;
}
BeContext* CeMachine::GetBeContext()
{
if (mCeModule == NULL)
@ -3016,6 +3048,12 @@ void CeMachine::CompileStarted()
}
}
void CeMachine::CompileDone()
{
// So things like delted local methods get recheckeds
mRevision++;
}
void CeMachine::DerefMethodInfo(CeFunctionInfo* ceFunctionInfo)
{
ceFunctionInfo->mRefCount--;
@ -3257,6 +3295,13 @@ bool CeMachine::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
}
}
if ((constant->mConstType == BfConstType_TypeOf) || (constant->mConstType == BfConstType_TypeOf_WithData))
{
auto constTypeOf = (BfTypeOf_Const*)constant;
CE_GETC(addr_ce) = GetReflectType(constTypeOf->mType->mTypeId);
return true;
}
return false;
}
@ -3489,7 +3534,6 @@ CeErrorKind CeMachine::WriteConstant(CeConstStructData& data, BeConstant* constV
return CeErrorKind_None;
}
#define CE_CREATECONST_CHECKPTR(PTR, SIZE) \
if ((((uint8*)(PTR) - memStart) - 0x10000) + (SIZE) > (memSize - 0x10000)) \
{ \
@ -3829,8 +3873,10 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
uint8* stackPtr = startStackPtr;
uint8* framePtr = startFramePtr;
bool needsFunctionIds = mCeModule->mSystem->mPtrSize != 8;
volatile bool* cancelPtr = &mCompiler->mCanceling;
int32 ptrSize = mCeModule->mSystem->mPtrSize;
volatile bool* fastFinishPtr = &mCompiler->mFastFinish;
volatile bool* cancelingPtr = &mCompiler->mCanceling;
auto _GetCurFrame = [&]()
{
@ -3973,12 +4019,30 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
handled = true;
return true;
}
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitDefinition)
{
int32 typeId = *(int32*)((uint8*)stackPtr);
addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + sizeof(int32));
if ((mCurEmitContext == NULL) || (mCurEmitContext->mType->mTypeId != typeId))
{
_Fail("Missing emit context");
return false;
}
if (!GetStringFromStringView(strViewPtr, mCurEmitContext->mEmitData))
{
_Fail("Invalid StringView");
return false;
}
handled = true;
return true;
}
else if (checkFunction->mFunctionKind == CeFunctionKind_Sleep)
{
int32 sleepMS = *(int32*)((uint8*)stackPtr);
while (sleepMS > 0)
{
if (*cancelPtr)
if (*fastFinishPtr)
break;
if (sleepMS > 200)
@ -4104,9 +4168,9 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
if (!checkFunction->mFailed)
return true;
auto error = Fail(_GetCurFrame(), "Method call failed");
auto error = Fail(_GetCurFrame(), StrFormat("Method call '%s' failed", mCeModule->MethodToString(checkFunction->mMethodInstance).c_str()));
if ((error != NULL) && (!checkFunction->mGenError.IsEmpty()))
mCompiler->mPassInstance->MoreInfo("Const Method Generation Error: " + checkFunction->mGenError);
mCompiler->mPassInstance->MoreInfo("Comptime method generation error: " + checkFunction->mGenError);
return false;
};
@ -4124,9 +4188,10 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
while (true)
{
if (*cancelPtr)
if (*fastFinishPtr)
{
_Fail("Compilation cancelled");
if (*cancelingPtr)
_Fail("Comptime evaluation canceled");
return false;
}
@ -4576,10 +4641,14 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
if (staticFieldInfo->mAddr == 0)
{
if (ceStaticFieldEntry.mSize < 0)
_Fail(StrFormat("Reference to unsized global variable '%s'", ceStaticFieldEntry.mName.c_str()));
CE_CHECKALLOC(ceStaticFieldEntry.mSize);
uint8* ptr = CeMalloc(ceStaticFieldEntry.mSize);
_FixVariables();
memset(ptr, 0, ceStaticFieldEntry.mSize);
if (ceStaticFieldEntry.mSize > 0)
memset(ptr, 0, ceStaticFieldEntry.mSize);
staticFieldInfo->mAddr = (addr_ce)(ptr - memStart);
}
@ -4641,14 +4710,22 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
callEntry.mFunction = callEntry.mFunctionInfo->mCeFunction;
if (!callEntry.mFunction->mInitialized)
{
auto curFrame = _GetCurFrame();
SetAndRestoreValue<CeFrame*> prevFrame(mCurFrame, &curFrame);
PrepareFunction(callEntry.mFunction, NULL);
}
callEntry.mBindRevision = mRevision;
}
BF_ASSERT(memStart == mMemory.mVals);
auto callFunction = callEntry.mFunction;
if (callFunction->mMethodInstance->mMethodDef->mIsLocalMethod)
{
NOP;
}
if (needsFunctionIds)
*(int32*)(framePtr + resultFrameIdx) = callFunction->mId;
else
@ -4678,7 +4755,14 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
CE_CHECKADDR(valueAddr, sizeof(int32));
int32 objTypeId = *(int32*)(memStart + valueAddr);
auto valueType = mCeModule->mContext->mTypes[objTypeId]->ToTypeInstance();
BfType* bfType = GetBfType(objTypeId);
if ((bfType == NULL) || (!bfType->IsObject()))
{
_Fail("Invalid virtual method target");
return false;
}
auto valueType = bfType->ToTypeInstance();
if (valueType->mVirtualMethodTable.IsEmpty())
mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods);
auto methodInstance = (BfMethodInstance*)valueType->mVirtualMethodTable[virtualIdx].mImplementingMethod;
@ -4702,23 +4786,26 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
CE_CHECKADDR(valueAddr, sizeof(int32));
int32 objTypeId = *(int32*)(memStart + valueAddr);
auto valueType = mCeModule->mContext->mTypes[objTypeId]->ToTypeInstance();
if (valueType->mVirtualMethodTable.IsEmpty())
mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods);
BfMethodInstance* methodInstance = NULL;
auto checkType = valueType;
while (checkType != NULL)
if (valueType != NULL)
{
for (auto& iface : checkType->mInterfaces)
if (valueType->mVirtualMethodTable.IsEmpty())
mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods);
auto checkType = valueType;
while (checkType != NULL)
{
if (iface.mInterfaceType == ifaceType)
for (auto& iface : checkType->mInterfaces)
{
methodInstance = valueType->mInterfaceMethodTable[iface.mStartInterfaceTableIdx + methodIdx].mMethodRef;
break;
if (iface.mInterfaceType == ifaceType)
{
methodInstance = valueType->mInterfaceMethodTable[iface.mStartInterfaceTableIdx + methodIdx].mMethodRef;
break;
}
}
checkType = checkType->mBaseType;
}
checkType = checkType->mBaseType;
}
if (methodInstance == NULL)
@ -5305,18 +5392,25 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
auto owner = ceFunction->mMethodInstance->GetOwner();
if (owner == mCeModule->mContext->mBfObjectType)
{
if (methodDef->mName == "ConstEval_GetType")
if (methodDef->mName == "Comptime_GetType")
{
ceFunction->mFunctionKind = CeFunctionKind_GetReflectType;
}
}
else if (owner->IsInstanceOf(mCeModule->mCompiler->mTypeTypeDef))
{
if (methodDef->mName == "ConstEval_GetTypeById")
if (methodDef->mName == "Comptime_GetTypeById")
{
ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeById;
}
}
else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef))
{
if (methodDef->mName == "Comptime_EmitDefinition")
{
ceFunction->mFunctionKind = CeFunctionKind_EmitDefinition;
}
}
else if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef))
{
if (methodDef->mName == "Write")
@ -5373,6 +5467,7 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
ceFunction->mGenerating = true;
CeBuilder ceBuilder;
SetAndRestoreValue<CeBuilder*> prevBuilder(mCurBuilder, &ceBuilder);
ceBuilder.mParentBuilder = parentBuilder;
ceBuilder.mPtrSize = mCeModule->mCompiler->mSystem->mPtrSize;
ceBuilder.mCeMachine = this;
@ -5534,6 +5629,7 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
// DISABLED
//return BfTypedValue();
SetAndRestoreValue<CeEvalFlags> prevEvalFlags(mCurEvalFlags, flags);
SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc);
SetAndRestoreValue<BfModule*> prevModule(mCurModule, module);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance);