1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Expanding CTFE

This commit is contained in:
Brian Fiete 2020-12-14 03:50:28 -08:00
parent 577e199dcd
commit 6d058ba59c
9 changed files with 662 additions and 263 deletions

View file

@ -1009,7 +1009,7 @@ void BfCompiler::EmitTestMethod(BfVDataModule* bfModule, Array<TestMethod>& test
}
BfExprEvaluator exprEvaluator(bfModule);
exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
bfModule->mBfIRBuilder->CreateBr(testHeadBlock);
}

View file

@ -645,6 +645,7 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
dupMethodInstance.mMethodProcessRequest = NULL;
dupMethodInstance.mIsReified = true;
dupMethodInstance.mHotMethod = NULL;
dupMethodInstance.mInCEMachine = false; // Only have the original one
BF_ASSERT(module->mIsReified); // We should only bother inlining in reified modules
{

View file

@ -4801,7 +4801,7 @@ void BfExprEvaluator::PerformCallChecks(BfMethodInstance* methodInstance, BfAstN
mModule->CheckErrorAttributes(methodInstance->GetOwner(), methodInstance, customAttributes, targetSrc);
}
BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret, bool isTailCall)
BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret, bool isTailCall)
{
// static int sCallIdx = 0;
// if (!mModule->mCompiler->mIsResolveOnly)
@ -4990,7 +4990,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
}
else if ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0)
{
auto constRet = mModule->mCompiler->mCEMachine->Call(mModule, methodInstance, irArgs, CeEvalFlags_None);
auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, CeEvalFlags_None);
if (constRet)
return constRet;
}
@ -6632,7 +6632,7 @@ SplatArgs(lookupVal, irArgs);
}
auto func = moduleMethodInstance.mFunc;
BfTypedValue result = CreateCall(methodInstance, func, bypassVirtual, irArgs);
BfTypedValue result = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs);
if ((result.mType != NULL) && (result.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly))
mModule->Fail("Method return type reference failed to resolve", targetSrc);
return result;
@ -9144,7 +9144,7 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
exprEvaluator.MatchMethod(elementExpr, NULL, initValue, false, false, "Add", argValues, NULL);
if (addFunctionBindResult.mMethodInstance != NULL)
CreateCall(addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, addFunctionBindResult.mIRArgs);
CreateCall(initExpr, addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, addFunctionBindResult.mIRArgs);
isFirstAdd = false;
}
@ -9162,7 +9162,7 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
PushArg(argValue, irArgs);
for (int argIdx = (int)irArgs.size(); argIdx < (int)addFunctionBindResult.mIRArgs.size(); argIdx++)
irArgs.Add(addFunctionBindResult.mIRArgs[argIdx]);
CreateCall(addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, irArgs);
CreateCall(initExpr, addFunctionBindResult.mMethodInstance, addFunctionBindResult.mFunc, true, irArgs);
}
}
@ -13100,7 +13100,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
BF_ASSERT(calcAppendMethodModule.mFunc);
appendSizeTypedValue = CreateCall(calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, irArgs);
appendSizeTypedValue = CreateCall(objCreateExpr, calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, irArgs);
BF_ASSERT(appendSizeTypedValue.mType == mModule->GetPrimitiveType(BfTypeCode_IntPtr));
}
appendSizeValue = appendSizeTypedValue.mValue;
@ -13187,7 +13187,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
SizedArray<BfIRValue, 1> irArgs;
irArgs.push_back(mResult.mValue);
CreateCall(ctorClear.mMethodInstance, ctorClear.mFunc, false, irArgs);
CreateCall(objCreateExpr, ctorClear.mMethodInstance, ctorClear.mFunc, false, irArgs);
}
}
@ -13255,7 +13255,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
}
if (!typeInstance->IsValuelessType())
bindResult.mIRArgs.Insert(0, mResult.mValue);
CreateCall(bindResult.mMethodInstance, bindResult.mFunc, false, bindResult.mIRArgs);
CreateCall(objCreateExpr, bindResult.mMethodInstance, bindResult.mFunc, false, bindResult.mIRArgs);
}
}
}
@ -15870,7 +15870,7 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
}
}
else
mResult = CreateCall(methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args);
mResult = CreateCall(mPropSrc, methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args);
if (mResult.mType != NULL)
{
if ((mResult.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly))
@ -16794,7 +16794,7 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
PushArg(convVal, args);
if (methodInstance)
CreateCall(methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args);
CreateCall(assignExpr, methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args);
mPropDef = NULL;
mResult = convVal;
@ -16868,7 +16868,7 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
SizedArray<BfIRValue, 1> args;
exprEvaluator.PushThis(assignExpr->mLeft, leftValue, moduleMethodInstance.mMethodInstance, args);
exprEvaluator.PushArg(rightValue, args);
exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, args);
exprEvaluator.CreateCall(assignExpr, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, args);
convVal = leftValue;
handled = true;
break;
@ -19068,7 +19068,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
}
PushArg(writeToProp, args);
CreateCall(methodInstance.mMethodInstance, methodInstance.mFunc, false, args);
CreateCall(opToken, methodInstance.mMethodInstance, methodInstance.mFunc, false, args);
}
}

View file

@ -420,7 +420,7 @@ public:
BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
void AddCallDependencies(BfMethodInstance* methodInstance);
void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc);
BfTypedValue CreateCall(BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret = NULL, bool isTailCall = false);
BfTypedValue CreateCall(BfAstNode* targetSrc, BfMethodInstance* methodInstance, BfIRValue func, bool bypassVirtual, SizedArrayImpl<BfIRValue>& irArgs, BfTypedValue* sret = NULL, bool isTailCall = false);
BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, bool bypassVirtual, SizedArrayImpl<BfResolvedArg>& argValues, bool skipThis = false);
BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target);
void MakeBaseConcrete(BfTypedValue& typedValue);

View file

@ -694,7 +694,7 @@ public:
{
BF_ASSERT(calcAppendMethodModule.mFunc);
subDependSize = exprEvaluator.CreateCall(calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, calcAppendArgs);
subDependSize = exprEvaluator.CreateCall(objCreateExpr, calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, calcAppendArgs);
BF_ASSERT(subDependSize.mType == mModule->GetPrimitiveType(BfTypeCode_IntPtr));
}
if (subDependSize)
@ -9211,7 +9211,7 @@ void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* tar
SizedArray<BfIRValue, 4> irArgs;
irArgs.push_back(objectParam);
irArgs.push_back(GetConstValue32(targetType->mTypeId));
auto callResult = exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
auto callResult = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
auto resultType = ResolveTypeDef(mSystem->mTypeBool);
auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult.mValue, GetDefaultValue(callResult.mType));
irb->CreateCondBr(cmpResult, trueBlock, falseBlock);
@ -14788,7 +14788,7 @@ BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly)
calcAppendArgs = bindResult.mIRArgs;
}
BF_ASSERT(calcAppendMethodModule.mFunc);
appendSizeTypedValue = exprEvaluator.CreateCall(calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, calcAppendArgs);
appendSizeTypedValue = exprEvaluator.CreateCall(NULL, calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, calcAppendArgs);
BF_ASSERT(appendSizeTypedValue.mType == GetPrimitiveType(BfTypeCode_IntPtr));
@ -15648,7 +15648,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
SizedArray<BfIRValue, 1> irArgs;
exprEvaluator.PushThis(NULL, GetThis(), moduleMethodInstance.mMethodInstance, irArgs);
exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
calledCtorNoBody = true;
}
@ -16131,7 +16131,7 @@ void BfModule::EmitEnumToStringBody()
SizedArray<BfIRValue, 2> args;
args.Add(stringDestVal.mValue);
args.Add(caseStr);
exprEvaluator.CreateCall(appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
auto payloadType = fieldInstance.mResolvedType->ToTypeInstance();
BF_ASSERT(payloadType->IsTuple());
@ -16150,7 +16150,7 @@ void BfModule::EmitEnumToStringBody()
exprEvaluator.PushThis(NULL, payload, toStringMethod.mMethodInstance, irArgs);
stringDestVal = LoadValue(stringDestAddr);
irArgs.Add(stringDestVal.mValue);
exprEvaluator.CreateCall(toStringMethod.mMethodInstance, toStringMethod.mFunc, true, irArgs);
exprEvaluator.CreateCall(NULL, toStringMethod.mMethodInstance, toStringMethod.mFunc, true, irArgs);
}
mBfIRBuilder->CreateBr(endBlock);
@ -16186,7 +16186,7 @@ void BfModule::EmitEnumToStringBody()
auto stringDestVal = LoadValue(stringDestAddr);
args.Add(stringDestVal.mValue);
args.Add(mBfIRBuilder->CreateLoad(strVal));
exprEvaluator.CreateCall(appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
mBfIRBuilder->CreateBr(endBlock);
mBfIRBuilder->AddBlock(noMatchBlock);
@ -16197,7 +16197,7 @@ void BfModule::EmitEnumToStringBody()
args.Add(int64Val);
stringDestVal = LoadValue(stringDestAddr);
args.Add(stringDestVal.mValue);
exprEvaluator.CreateCall(toStringModuleMethodInstance.mMethodInstance, toStringModuleMethodInstance.mFunc, false, args);
exprEvaluator.CreateCall(NULL, toStringModuleMethodInstance.mMethodInstance, toStringModuleMethodInstance.mFunc, false, args);
mBfIRBuilder->CreateBr(endBlock);
mBfIRBuilder->AddBlock(endBlock);
@ -16226,7 +16226,7 @@ void BfModule::EmitTupleToStringBody()
auto stringDestVal = LoadValue(stringDestRef);
args.Add(stringDestVal.mValue);
args.Add(mBfIRBuilder->CreateConst(BfTypeCode_Char8, (int)c));
exprEvaluator.CreateCall(appendCharModuleMethodInstance.mMethodInstance, appendCharModuleMethodInstance.mFunc, false, args);
exprEvaluator.CreateCall(NULL, appendCharModuleMethodInstance.mMethodInstance, appendCharModuleMethodInstance.mFunc, false, args);
};
int fieldIdx = 0;
@ -16254,7 +16254,7 @@ void BfModule::EmitTupleToStringBody()
auto stringDestVal = LoadValue(stringDestRef);
args.Add(stringDestVal.mValue);
args.Add(commaStr);
exprEvaluator.CreateCall(appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
}
fieldIdx++;
@ -16300,7 +16300,7 @@ void BfModule::EmitTupleToStringBody()
auto stringDestVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]);
stringDestVal = LoadValue(stringDestVal);
args.Add(stringDestVal.mValue);
exprEvaluator.CreateCall(toStringSafeModuleMethodInstance.mMethodInstance, toStringSafeModuleMethodInstance.mFunc, false, args);
exprEvaluator.CreateCall(NULL, toStringSafeModuleMethodInstance.mMethodInstance, toStringSafeModuleMethodInstance.mFunc, false, args);
continue;
}
@ -16324,7 +16324,7 @@ void BfModule::EmitTupleToStringBody()
auto stringDestVal = LoadValue(stringDestRef);
args.Add(stringDestVal.mValue);
args.Add(strVal);
exprEvaluator.CreateCall(appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
continue;
}
@ -16389,7 +16389,7 @@ void BfModule::EmitGCMarkValue(BfTypedValue markVal, BfModuleMethodInstance mark
val = mBfIRBuilder->CreateBitCast(val, mBfIRBuilder->MapType(mContext->mBfObjectType));
SizedArray<BfIRValue, 1> args;
args.push_back(val);
exprEvaluator.CreateCall(markFromGCThreadMethodInstance.mMethodInstance, markFromGCThreadMethodInstance.mFunc, false, args);
exprEvaluator.CreateCall(NULL, markFromGCThreadMethodInstance.mMethodInstance, markFromGCThreadMethodInstance.mFunc, false, args);
}
else if ((fieldTypeInst->IsComposite()) && (!fieldTypeInst->IsTypedPrimitive()))
{
@ -16403,7 +16403,7 @@ void BfModule::EmitGCMarkValue(BfTypedValue markVal, BfModuleMethodInstance mark
markVal = Cast(NULL, markVal, methodOwner);
exprEvaluator.PushThis(NULL, markVal, markMemberMethodInstance.mMethodInstance, args);
exprEvaluator.CreateCall(markMemberMethodInstance.mMethodInstance, markMemberMethodInstance.mFunc, false, args);
exprEvaluator.CreateCall(NULL, markMemberMethodInstance.mMethodInstance, markMemberMethodInstance.mFunc, false, args);
}
}
}
@ -16452,7 +16452,7 @@ void BfModule::CallChainedMethods(BfMethodInstance* methodInstance, bool reverse
BfExprEvaluator exprEvaluator(this);
SizedArray<BfIRValue, 1> args;
exprEvaluator.PushThis(chainedMethodInst->mMethodDef->GetRefNode(), GetThis(), chainedMethodInst, args);
exprEvaluator.CreateCall(moduleMethodInst.mMethodInstance, moduleMethodInst.mFunc, true, args);
exprEvaluator.CreateCall(NULL, moduleMethodInst.mMethodInstance, moduleMethodInst.mFunc, true, args);
}
}
@ -18617,14 +18617,14 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
mBfIRBuilder->PopulateType(methodInstance->mReturnType);
auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()), methodInstance->mReturnType, true);
exprEvaluator.mReceivingValue = &returnType;
auto retVal = exprEvaluator.CreateCall(innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true);
auto retVal = exprEvaluator.CreateCall(NULL, innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true);
BF_ASSERT(exprEvaluator.mReceivingValue == NULL); // Ensure it was actually used
mBfIRBuilder->CreateRetVoid();
}
else
{
mBfIRBuilder->PopulateType(methodInstance->mReturnType);
auto retVal = exprEvaluator.CreateCall(innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true);
auto retVal = exprEvaluator.CreateCall(NULL, innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true);
if (mCurMethodInstance->mReturnType->IsValueType())
retVal = LoadValue(retVal);
CreateReturn(retVal.mValue);
@ -21680,9 +21680,12 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
auto checkMethod = nextMethod;
nextMethod = nextMethod->mNextWithSameName;
if ((checkMethod != methodDef) && (typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault != NULL))
{
if (checkMethod == methodDef)
continue;
auto checkMethodInstance = typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
if (checkMethodInstance == NULL)
continue;
if (((checkMethodInstance->mChainType == BfMethodChainType_None) || (checkMethodInstance->mChainType == BfMethodChainType_ChainHead)) &&
(checkMethodInstance->GetExplicitInterface() == methodInstance->GetExplicitInterface()) &&
@ -21782,7 +21785,6 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
}
}
}
}
// Virtual methods give their error while slotting
if ((!typeInstance->IsBoxed()) && (!methodDef->mIsVirtual) && (methodDef->mProtection != BfProtection_Private) &&

View file

@ -4370,9 +4370,14 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount);
// Pass 2
// Def passes. First non-overrides then overrides (for in-place overrides in methods)
for (int pass = 0; pass < 2; pass++)
{
for (auto methodDef : typeDef->mMethods)
{
if ((pass == 1) != (methodDef->mIsOverride))
continue;
auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodDef->mIdx];
if ((methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_AlwaysInclude) &&
@ -4469,6 +4474,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
disableYield.Acquire();
}
}
}
BF_ASSERT(typeInstance->mVirtualMethodTable.size() == typeInstance->mVirtualMethodTableSize);
@ -11031,7 +11037,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
SizedArray<BfIRValue, 1> args;
exprEvaluator.PushArg(castedFromValue, args);
operatorOut = exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : moduleMethodInstance.mFunc, false, args);
operatorOut = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : moduleMethodInstance.mFunc, false, args);
if ((operatorOut.mType != NULL) && (operatorOut.mType->IsSelf()))
{
BF_ASSERT(IsInGeneric());

View file

@ -760,7 +760,7 @@ void BfModule::EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, Siz
}
BfExprEvaluator expressionEvaluator(this);
expressionEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, ((flags & BfDeferredBlockFlag_BypassVirtual) != 0), llvmArgs);
expressionEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, ((flags & BfDeferredBlockFlag_BypassVirtual) != 0), llvmArgs);
if ((flags & BfDeferredBlockFlag_DoNullChecks) != 0)
{
@ -3956,7 +3956,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt)
BF_ASSERT(methodInstance->mMethodDef->mName == "~this");
SizedArray<BfIRValue, 4> llvmArgs;
llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(objectType)));
expressionEvaluator.CreateCall(methodInstance, methodInstance->mIRFunction, false, llvmArgs);
expressionEvaluator.CreateCall(deleteStmt->mDeleteToken, methodInstance, methodInstance->mIRFunction, false, llvmArgs);
}
if ((deleteStmt->mTargetTypeToken != NULL) && (!isAppendDelete))
@ -5998,7 +5998,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
SizedArray<BfIRValue, 1> args;
auto castedTarget = Cast(forEachStmt->mCollectionExpression, target, getEnumeratorMethod.mMethodInstance->GetOwner());
exprEvaluator.PushThis(forEachStmt->mCollectionExpression, castedTarget, getEnumeratorMethod.mMethodInstance, args);
itr = exprEvaluator.CreateCall(getEnumeratorMethod.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : getEnumeratorMethod.mFunc, false, args);
itr = exprEvaluator.CreateCall(forEachStmt->mCollectionExpression, getEnumeratorMethod.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : getEnumeratorMethod.mFunc, false, args);
}
}

View file

@ -16,6 +16,13 @@ struct CeOpInfo
CeOperandInfoKind mOperandC;
};
#define CEOPINFO_SIZED_1(OPNAME, OPINFOA) \
{OPNAME##"_8", OPINFOA}, \
{OPNAME##"_16", OPINFOA}, \
{OPNAME##"_32", OPINFOA}, \
{OPNAME##"_64", OPINFOA}, \
{OPNAME##"_X", OPINFOA, CEOI_IMM32}
#define CEOPINFO_SIZED_2(OPNAME, OPINFOA, OPINFOB) \
{OPNAME##"_8", OPINFOA, OPINFOB}, \
{OPNAME##"_16", OPINFOA, OPINFOB}, \
@ -43,6 +50,11 @@ struct CeOpInfo
{OPNAME##"_I64", OPINFOA, OPINFOB}, \
{OPNAME##"_F32", OPINFOA, OPINFOB}, \
{OPNAME##"_F64", OPINFOA, OPINFOB}
#define CEOPINFO_SIZED_NUMERIC_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \
{OPNAME##"_I8", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I16", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I32", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I64", OPINFOA, OPINFOB, OPINFOC}
#define CEOPINFO_SIZED_NUMERIC_PLUSF_3(OPNAME, OPINFOA, OPINFOB, OPINFOC) \
{OPNAME##"_I8", OPINFOA, OPINFOB, OPINFOC}, \
{OPNAME##"_I16", OPINFOA, OPINFOB, OPINFOC}, \
@ -60,6 +72,7 @@ static CeOpInfo gOpInfo[] =
{"JmpIfNot", CEOI_None, CEOI_JMPREL, CEOI_FrameRef},
{"FrameAddr32", CEOI_FrameRef, CEOI_FrameRef},
{"FrameAddr64", CEOI_FrameRef, CEOI_FrameRef},
{"Zero", CEOI_FrameRef, CEOI_IMM32},
{"Const_8", CEOI_FrameRef, CEOI_IMM8},
{"Const_16", CEOI_FrameRef, CEOI_IMM16},
@ -71,15 +84,33 @@ static CeOpInfo gOpInfo[] =
CEOPINFO_SIZED_3("Store", CEOI_None, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_3("Move", CEOI_None, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_2("Push", CEOI_None, CEOI_FrameRef),
CEOPINFO_SIZED_1("Pop", CEOI_FrameRef),
{"AdjustSP", CEOI_None, CEOI_FrameRef},
{"Call", CEOI_None, CEOI_IMM32},
{"Conv_I32_I64", CEOI_FrameRef, CEOI_FrameRef},
{"AddConst_I8", CEOI_FrameRef, CEOI_IMM8},
{"AddConst_I16", CEOI_FrameRef, CEOI_IMM16},
{"AddConst_I32", CEOI_FrameRef, CEOI_IMM32},
{"AddConst_I64", CEOI_FrameRef, CEOI_IMM64},
{"AddConst_F32", CEOI_FrameRef, CEOI_IMMF32},
{"AddConst_F64", CEOI_FrameRef, CEOI_IMMF64},
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Add", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Sub", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Mul", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("SDiv", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_3("UDiv", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("SMod", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_3("UMod", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_EQ", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_SLT", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_3("Cmp_ULT", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_PLUSF_3("Cmp_SLE", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
CEOPINFO_SIZED_NUMERIC_3("Cmp_ULE", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef),
//{"Cmp_SLT_I32", CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef},
CEOPINFO_SIZED_NUMERIC_PLUSF_2("Neg", CEOI_FrameRef, CEOI_FrameRef),
@ -441,12 +472,6 @@ void CeBuilder::EmitSizedOp(CeOp baseOp, const CeOperand& operand, CeOperand* ou
Emit(op);
if (outResult != NULL)
{
*outResult = FrameAlloc(operand.mType);
EmitFrameOffset(*outResult);
}
if (!isStdSize)
{
if (!allowNonStdSize)
@ -454,6 +479,12 @@ void CeBuilder::EmitSizedOp(CeOp baseOp, const CeOperand& operand, CeOperand* ou
Emit((int32)operand.mType->mSize);
}
if (outResult != NULL)
{
*outResult = FrameAlloc(operand.mType);
EmitFrameOffset(*outResult);
}
EmitFrameOffset(operand);
}
@ -468,7 +499,7 @@ CeOperand CeBuilder::FrameAlloc(BeType* type)
return result;
}
CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca)
CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImmediate)
{
if (value == NULL)
return CeOperand();
@ -530,11 +561,20 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca)
CeOperand mcOperand;
switch (constant->mType->mTypeCode)
{
case BeTypeCode_Boolean:
case BeTypeCode_Int8:
case BeTypeCode_Int16:
case BeTypeCode_Int32:
case BeTypeCode_Int64:
if (allowImmediate)
{
CeOperand result;
result.mKind = CeOperandKind_Immediate;
result.mImmediate = constant->mInt32;
result.mType = constant->mType;
return result;
}
case BeTypeCode_Boolean:
case BeTypeCode_Double:
dataPtr = &constant->mUInt64;
dataSize = constant->mType->mSize;
@ -572,17 +612,25 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca)
}
}
break;
// case BeTypeCode_Struct:
// case BeTypeCode_SizedArray:
// case BeTypeCode_Vector:
// mcOperand.mImmediate = constant->mInt64;
// mcOperand.mKind = CeOperandKind_Immediate_i64;
// break;
case BeTypeCode_Struct:
case BeTypeCode_SizedArray:
case BeTypeCode_Vector:
{
auto beType = constant->mType;
auto result = FrameAlloc(beType);
Emit(CeOp_Zero);
EmitFrameOffset(result);
Emit((int32)beType->mSize);
return result;
}
//mcOperand.mImmediate = constant->mInt64;
//mcOperand.mKind = CeOperandKind_Immediate_i64;
break;
// default:
// Fail("Unhandled constant type");
}
if (dataPtr != NULL)
if (dataSize != 0)
{
auto beType = constant->mType;
auto result = FrameAlloc(beType);
@ -592,7 +640,13 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca)
EmitFrameOffset(result);
if (sizeClass == CeSizeClass_X)
Emit((int32)dataSize);
if (dataPtr != 0)
Emit(dataPtr, dataSize);
else
{
for (int i = 0; i < dataSize; i++)
Emit((uint8)0);
}
return result;
}
@ -952,6 +1006,7 @@ void CeBuilder::Build()
dupMethodInstance.mMethodProcessRequest = NULL;
dupMethodInstance.mIsReified = true;
dupMethodInstance.mHotMethod = NULL;
dupMethodInstance.mInCEMachine = false; // Only have the original one
mCeMachine->mCeModule->ProcessMethod(&dupMethodInstance, true);
@ -1147,6 +1202,24 @@ void CeBuilder::Build()
case BeBinaryOpKind_Add:
EmitBinaryOp(CeOp_Add_I8, CeOp_Add_F32, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_Subtract:
EmitBinaryOp(CeOp_Sub_I8, CeOp_Sub_F32, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_Multiply:
EmitBinaryOp(CeOp_Mul_I8, CeOp_Mul_F32, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_SDivide:
EmitBinaryOp(CeOp_SDiv_I8, CeOp_SDiv_F32, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_UDivide:
EmitBinaryOp(CeOp_UDiv_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_SModulus:
EmitBinaryOp(CeOp_SMod_I8, CeOp_SMod_F32, ceLHS, ceRHS, result);
break;
case BeBinaryOpKind_UModulus:
EmitBinaryOp(CeOp_UMod_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
break;
default:
Fail("Invalid binary op");
}
@ -1274,6 +1347,16 @@ void CeBuilder::Build()
iOp = CeOp_Cmp_SLT_I8;
fOp = CeOp_Cmp_SLT_F32;
break;
case BeCmpKind_ULT:
iOp = CeOp_Cmp_ULT_I8;
break;
case BeCmpKind_SLE:
iOp = CeOp_Cmp_SLE_I8;
fOp = CeOp_Cmp_SLE_F32;
break;
case BeCmpKind_ULE:
iOp = CeOp_Cmp_ULE_I8;
break;
}
if (iOp == CeOp_InvalidOp)
@ -1299,6 +1382,128 @@ void CeBuilder::Build()
// mcInst->mResult = result;
}
break;
case BeGEPInst::TypeId:
{
auto castedInst = (BeGEPInst*)inst;
auto mcVal = GetOperand(castedInst->mPtr);
auto mcIdx0 = GetOperand(castedInst->mIdx0, false, true);
BePointerType* ptrType = (BePointerType*)mcVal.mType;
BF_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer);
result = mcVal;
if (castedInst->mIdx1 != NULL)
{
// We assume we never do both an idx0 and idx1 at once. Fix if we change that.
BF_ASSERT(castedInst->mIdx0);
auto mcIdx1 = GetOperand(castedInst->mIdx1);
if (!mcIdx1.IsImmediate())
{
// This path is used when we have a const array that gets indexed by a non-const index value
// if (ptrType->mElementType->mTypeCode == BeTypeCode_SizedArray)
// {
// auto arrayType = (BeSizedArrayType*)ptrType->mElementType;
//
// auto elementPtrType = mModule->mContext->GetPointerTo(arrayType->mElementType);
//
// auto ptrValue = AllocVirtualReg(elementPtrType);
// auto ptrInfo = GetVRegInfo(ptrValue);
// ptrInfo->mIsExpr = true;
// ptrInfo->mRelTo = result;
// CreateDefineVReg(ptrValue);
// result = ptrValue;
//
// BeMCOperand mcRelOffset;
// int relScale = 1;
// if (mcIdx1.IsImmediate())
// {
// mcRelOffset = BeMCOperand::FromImmediate(mcIdx1.mImmediate * arrayType->mElementType->mSize);
// }
// else
// {
// mcRelOffset = mcIdx1;
// relScale = arrayType->mElementType->mSize;
// }
//
// result = AllocRelativeVirtualReg(elementPtrType, result, mcRelOffset, relScale);
// // The def is primary to create a single 'master location' for the GEP vreg to become legalized before use
// CreateDefineVReg(result);
// //TODO: Always correct?
// result.mKind = BeMCOperandKind_VReg;
//
// }
// else
// SoftFail("Invalid GEP", inst->mDbgLoc);
Fail("Invalid GEP");
}
else
{
BF_ASSERT(mcIdx1.IsImmediate());
int byteOffset = 0;
BeType* elementType = NULL;
if (ptrType->mElementType->mTypeCode == BeTypeCode_Struct)
{
BeStructType* structType = (BeStructType*)ptrType->mElementType;
auto& structMember = structType->mMembers[mcIdx1.mImmediate];
elementType = structMember.mType;
byteOffset = structMember.mByteOffset;
}
else if (ptrType->mElementType->mTypeCode == BeTypeCode_SizedArray)
{
auto arrayType = (BeSizedArrayType*)ptrType->mElementType;
elementType = arrayType->mElementType;
byteOffset = mcIdx1.mImmediate * elementType->mSize;
}
else if (ptrType->mElementType->mTypeCode == BeTypeCode_Vector)
{
auto arrayType = (BeVectorType*)ptrType->mElementType;
elementType = arrayType->mElementType;
byteOffset = mcIdx1.mImmediate * elementType->mSize;
}
else
{
Fail("Invalid gep target");
}
auto elementPtrType = beModule->mContext->GetPointerTo(elementType);
//result = AllocRelativeVirtualReg(elementPtrType, result, GetImmediate(byteOffset), 1);
// The def is primary to create a single 'master location' for the GEP vreg to become legalized before use
//CreateDefineVReg(result);
//result.mKind = BeMCOperandKind_VReg;
}
}
else
{
// It's temping to do a (IsNonZero) precondition, but if we make a reference to a VReg that is NOT in Addr form,
// then this will encode that so we will know we need to do a Load on that value at the Def during legalization
Fail("Unhandled gep");
// BeMCOperand mcRelOffset;
// int relScale = 1;
// if (mcIdx0.IsImmediate())
// {
// mcRelOffset = BeMCOperand::FromImmediate(mcIdx0.mImmediate * ptrType->mElementType->mSize);
// }
// else
// {
// mcRelOffset = mcIdx0;
// relScale = ptrType->mElementType->mSize;
// }
//
// result = AllocRelativeVirtualReg(ptrType, result, mcRelOffset, relScale);
// // The def is primary to create a single 'master location' for the GEP vreg to become legalized before use
// CreateDefineVReg(result);
// //TODO: Always correct?
// result.mKind = BeMCOperandKind_VReg;
}
}
break;
case BeBrInst::TypeId:
{
auto castedInst = (BeBrInst*)inst;
@ -1373,7 +1578,7 @@ void CeBuilder::Build()
bool isVarArg = false;
bool useAltArgs = false;
SizedArray<BeValue*, 6> args;
//SizedArray<BeValue*, 6> args;
int callIdx = -1;
@ -1394,6 +1599,13 @@ void CeBuilder::Build()
callIdx = *callIdxPtr;
for (int argIdx = (int)castedInst->mArgs.size() - 1; argIdx >= 0; argIdx--)
{
auto& arg = castedInst->mArgs[argIdx];
auto ceArg = GetOperand(arg.mValue);
EmitSizedOp(CeOp_Push_8, ceArg, NULL, true);
}
int stackAdjust = 0;
auto beFuncType = beFunction->GetFuncType();
@ -1407,6 +1619,12 @@ void CeBuilder::Build()
Emit(CeOp_Call);
Emit((int32)callIdx);
if (beFuncType->mReturnType->mSize > 0)
{
result = FrameAlloc(beFuncType->mReturnType);
EmitSizedOp(CeOp_Pop_8, result, NULL, true);
}
if (stackAdjust > 0)
{
Emit(CeOp_AdjustSP);
@ -1497,6 +1715,8 @@ CeMachine::CeMachine(BfCompiler* compiler)
mCeModule = NULL;
mStackMin = NULL;
mRevision = 0;
mCurTargetSrc = NULL;
mCurModule = NULL;
}
CeMachine::~CeMachine()
@ -1504,6 +1724,11 @@ CeMachine::~CeMachine()
delete mCeModule;
}
void CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str)
{
mCurModule->Fail(str, mCurTargetSrc);
}
void CeMachine::Init()
{
mCeModule = new BfModule(mCompiler->mContext, "__constEval");
@ -1535,8 +1760,12 @@ void CeMachine::RemoveMethod(BfMethodInstance* methodInstance)
{
auto itr = mFunctions.Find(methodInstance);
auto ceFunction = itr->mValue;
BF_ASSERT(itr != mFunctions.end());
if (itr != mFunctions.end())
{
mNamedFunctionMap.Remove(ceFunction->mName);
mFunctions.Remove(itr);
}
}
int CeMachine::GetConstantSize(BfConstant* constant)
@ -1607,6 +1836,12 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant)
return;
}
}
#define CE_CHECKSTACK() \
if (stackPtr < mStackMin) \
{ \
_Fail("Stack overflow"); \
return false; \
}
#define CE_GETINST(T) *((T*)(instPtr += sizeof(T)) - 1)
#define CE_GETFRAME(T) *(T*)(framePtr + *((int32*)(instPtr += sizeof(int32)) - 1))
@ -1636,27 +1871,50 @@ void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant)
auto val = CE_GETFRAME(TFROM); \
result = (TTO)val; \
}
#define CE_MOVE(T) \
#define CEOP_MOVE(T) \
{ \
auto val = CE_GETFRAME(T); \
auto& ptr = CE_GETFRAME(T); \
ptr = val; \
}
bool CeMachine::Execute()
{
uint8* memStart = &mMemory[0];
uint8* framePtr;
uint8* instPtr;
uint8* stackPtr;
//
{
auto& ceFrame = mCallStack.back();
instPtr = ceFrame.mInstPtr;
stackPtr = ceFrame.mStackPtr;
framePtr = ceFrame.mFramePtr;
framePtr = mCallStack.back().mFramePtr;
#define CEOP_PUSH(T) \
{ \
stackPtr -= sizeof(T); \
auto val = CE_GETFRAME(T); \
*((T*)stackPtr) = val; \
CE_CHECKSTACK(); \
}
#define CEOP_POP(T) \
{ \
auto& result = CE_GETFRAME(T); \
result = *((T*)stackPtr); \
stackPtr += sizeof(T); \
}
bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr)
{
CeFunction* ceFunction = startFunction;
uint8* memStart = &mMemory[0];
uint8* instPtr = &ceFunction->mCode[0];
uint8* stackPtr = startStackPtr;
uint8* framePtr = startFramePtr;
auto _GetCurFrame = [&]()
{
CeFrame ceFrame;
ceFrame.mFunction = ceFunction;
ceFrame.mFramePtr = framePtr;
ceFrame.mStackPtr = stackPtr;
ceFrame.mInstPtr = instPtr;
return ceFrame;
};
auto _Fail = [&](const StringImpl& error)
{
Fail(_GetCurFrame(), error);
};
int callCount = 0;
while (true)
{
@ -1665,15 +1923,16 @@ bool CeMachine::Execute()
{
case CeOp_Ret:
{
if (mCallStack.mSize == 0)
return true;
auto& ceFrame = mCallStack.back();
ceFunction = ceFrame.mFunction;
instPtr = ceFrame.mInstPtr;
stackPtr = ceFrame.mStackPtr;
framePtr = ceFrame.mFramePtr;
mCallStack.pop_back();
if (mCallStack.mSize == 0)
return true;
}
break;
case CeOp_Jmp:
@ -1705,6 +1964,13 @@ bool CeMachine::Execute()
result = addr - memStart;
}
break;
case CeOp_Zero:
{
auto resultPtr = &CE_GETFRAME(uint8);
int32 constSize = CE_GETINST(int32);
memset(resultPtr, 0, constSize);
}
break;
case CeOp_Const_8:
{
auto& result = CE_GETFRAME(int8);
@ -1751,16 +2017,91 @@ bool CeMachine::Execute()
}
break;
case CeOp_Move_8:
CE_MOVE(int8);
CEOP_MOVE(int8);
break;
case CeOp_Move_16:
CE_MOVE(int16);
CEOP_MOVE(int16);
break;
case CeOp_Move_32:
CE_MOVE(int32);
CEOP_MOVE(int32);
break;
case CeOp_Move_64:
CE_MOVE(int64);
CEOP_MOVE(int64);
break;
case CeOp_Move_X:
{
int32 size = CE_GETINST(int32);
auto valPtr = &CE_GETFRAME(uint8);
auto destPtr = &CE_GETFRAME(uint8);
memcpy(destPtr, valPtr, size);
}
break;
case CeOp_Push_8:
CEOP_PUSH(int8);
break;
case CeOp_Push_16:
CEOP_PUSH(int16);
break;
case CeOp_Push_32:
CEOP_PUSH(int32);
break;
case CeOp_Push_64:
CEOP_PUSH(int64);
break;
case CeOp_Pop_8:
CEOP_POP(int8);
break;
case CeOp_Pop_16:
CEOP_POP(int16);
break;
case CeOp_Pop_32:
CEOP_POP(int32);
break;
case CeOp_Pop_64:
CEOP_POP(int64);
break;
case CeOp_AdjustSP:
{
int32 adjust = CE_GETINST(int32);
stackPtr += adjust;
}
break;
case CeOp_Call:
{
callCount++;
int32 callIdx = CE_GETINST(int32);
auto& callEntry = ceFunction->mCallTable[callIdx];
if (callEntry.mBindRevision != mRevision)
{
callEntry.mFunction = NULL;
mNamedFunctionMap.TryGetValue(callEntry.mFunctionName, &callEntry.mFunction);
callEntry.mBindRevision = mRevision;
}
if (callEntry.mFunction == NULL)
{
_Fail("Unable to locate function entry");
break;
}
// if (callEntry.mFunction->mName.Contains("__static_dump"))
// {
// int32 val = *(int32*)(stackPtr);
// OutputDebugStrF("__static_dump: %d\n", val);
// }
if (callEntry.mFunction != NULL)
{
mCallStack.Add(_GetCurFrame());
ceFunction = callEntry.mFunction;
framePtr = stackPtr;
stackPtr -= ceFunction->mFrameSize;
instPtr = &ceFunction->mCode[0];
CE_CHECKSTACK();
}
}
break;
case CeOp_Conv_I32_I64:
CE_CAST(int32, int64);
@ -1771,12 +2112,36 @@ bool CeMachine::Execute()
case CeOp_Add_I64:
CEOP_BIN(+, int64);
break;
case CeOp_Sub_I32:
CEOP_BIN(-, int32);
break;
case CeOp_Sub_I64:
CEOP_BIN(-, int64);
break;
case CeOp_Mul_I32:
CEOP_BIN(*, int32);
break;
case CeOp_Mul_I64:
CEOP_BIN(*, int64);
break;
case CeOp_Cmp_EQ_I32:
CEOP_CMP(==, int32);
break;
case CeOp_Cmp_SLT_I32:
CEOP_CMP(<, int32);
break;
case CeOp_Cmp_ULT_I32:
CEOP_CMP(<, uint32);
break;
case CeOp_Cmp_SLE_I32:
CEOP_CMP(<=, int32);
break;
case CeOp_Cmp_SLE_I64:
CEOP_CMP(<= , int64);
break;
case CeOp_Cmp_ULE_I32:
CEOP_CMP(<=, uint32);
break;
case CeOp_Neg_I32:
CEOP_UNARY(-, int32);
break;
@ -1784,7 +2149,7 @@ bool CeMachine::Execute()
CEOP_UNARY(-, int64);
break;
default:
BF_FATAL("CeMachine op failure");
_Fail("Unhandled op");
return false;
}
}
@ -1829,12 +2194,13 @@ void CeMachine::ProcessWorkQueue()
}
}
CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance)
CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, bool& added)
{
CeFunction** functionValuePtr = NULL;
CeFunction* ceFunction = NULL;
if (mFunctions.TryAdd(methodInstance, NULL, &functionValuePtr))
{
added = true;
auto module = methodInstance->GetOwner()->mModule;
BF_ASSERT(!methodInstance->mInCEMachine);
@ -1852,12 +2218,13 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance)
void CeMachine::QueueMethod(BfMethodInstance* methodInstance)
{
auto ceFunction = GetFunction(methodInstance);
if (!ceFunction->mInitialized)
bool added = false;
auto ceFunction = GetFunction(methodInstance, added);
if (added)
mWorkQueue.Add(ceFunction);
}
BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags)
BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags)
{
// for (int argIdx = 0; argIdx < (int)args.size(); argIdx++)
// {
@ -1869,6 +2236,9 @@ BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance,
// DISABLED
return BfTypedValue();
SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc);
SetAndRestoreValue<BfModule*> prevModule(mCurModule, module);
BF_ASSERT(mCallStack.IsEmpty());
auto methodDef = methodInstance->mMethodDef;
@ -1878,7 +2248,8 @@ BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance,
return BfTypedValue();
}
CeFunction* ceFunction = GetFunction(methodInstance);
bool added = false;
CeFunction* ceFunction = GetFunction(methodInstance, added);
if (!ceFunction->mInitialized)
{
PrepareFunction(ceFunction);
@ -1914,14 +2285,7 @@ BfTypedValue CeMachine::Call(BfModule* module, BfMethodInstance* methodInstance,
retPtr = stackPtr;
}
CeFrame ceFrame;
ceFrame.mFunction = ceFunction;
ceFrame.mFramePtr = stackPtr;
ceFrame.mStackPtr = stackPtr - ceFunction->mFrameSize;
ceFrame.mInstPtr = &ceFunction->mCode[0];
mCallStack.Add(ceFrame);
bool success = Execute();
bool success = Execute(ceFunction, stackPtr - ceFunction->mFrameSize, stackPtr);
mCallStack.Clear();

View file

@ -49,20 +49,32 @@ enum CeOp : int16
CeOp_FrameAddr32,
CeOp_FrameAddr64,
CeOp_Zero,
CEOP_SIZED(Const),
CEOP_SIZED(Load),
CEOP_SIZED(Store),
CEOP_SIZED(Move),
CEOP_SIZED(Push),
CEOP_SIZED(Pop),
CeOp_AdjustSP,
CeOp_Call,
CeOp_Conv_I32_I64,
CEOP_SIZED_NUMERIC_PLUSF(AddConst),
CEOP_SIZED_NUMERIC_PLUSF(Add),
CEOP_SIZED_NUMERIC_PLUSF(Sub),
CEOP_SIZED_NUMERIC_PLUSF(Mul),
CEOP_SIZED_NUMERIC_PLUSF(SDiv),
CEOP_SIZED_NUMERIC(UDiv),
CEOP_SIZED_NUMERIC_PLUSF(SMod),
CEOP_SIZED_NUMERIC(UMod),
CEOP_SIZED_NUMERIC_PLUSF(Cmp_EQ),
CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLT),
CEOP_SIZED_NUMERIC(Cmp_ULT),
CEOP_SIZED_NUMERIC_PLUSF(Cmp_SLE),
CEOP_SIZED_NUMERIC(Cmp_ULE),
CEOP_SIZED_NUMERIC_PLUSF(Neg),
@ -127,6 +139,7 @@ enum CeOperandKind
CeOperandKind_FrameOfs,
CeOperandKind_AllocaAddr,
CeOperandKind_Block,
CeOperandKind_Immediate
};
class CeOperand
@ -137,6 +150,7 @@ public:
{
int mFrameOfs;
int mBlockIdx;
int mImmediate;
};
BeType* mType;
@ -152,6 +166,11 @@ public:
{
return mKind != CeOperandKind_None;
}
bool IsImmediate()
{
return mKind == CeOperandKind_Immediate;
}
};
#define BF_CE_STACK_SIZE 1024*1024
@ -164,6 +183,8 @@ enum CeOperandInfoKind
CEOI_IMM16,
CEOI_IMM32,
CEOI_IMM64,
CEOI_IMMF32,
CEOI_IMMF64,
CEOI_IMM_VAR,
CEOI_JMPREL
};
@ -254,7 +275,7 @@ public:
void Fail(const StringImpl& error);
CeOperand FrameAlloc(BeType* type);
CeOperand GetOperand(BeValue* value, bool allowAlloca = false);
CeOperand GetOperand(BeValue* value, bool allowAlloca = false, bool allowImmediate = false);
CeSizeClass GetSizeClass(int size);
int GetCodePos();
@ -309,25 +330,30 @@ public:
uint8* mStackMin;
Array<CeFunction*> mWorkQueue;
BfAstNode* mCurTargetSrc;
BfModule* mCurModule;
public:
CeMachine(BfCompiler* compiler);
~CeMachine();
void Fail(const CeFrame& curFrame, const StringImpl& error);
void Init();
void RemoveMethod(BfMethodInstance* methodInstance);
int GetConstantSize(BfConstant* constant);
void WriteConstant(uint8* ptr, BfConstant* constant);
void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction);
bool Execute();
bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr);
void PrepareFunction(CeFunction* methodInstance);
void ProcessWorkQueue();
CeFunction* GetFunction(BfMethodInstance* methodInstance);
CeFunction* GetFunction(BfMethodInstance* methodInstance, bool& added);
public:
void CompileStarted();
void QueueMethod(BfMethodInstance* methodInstance);
BfTypedValue Call(BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags);
BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags);
};
NS_BF_END