mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Expanding CTFE
This commit is contained in:
parent
577e199dcd
commit
6d058ba59c
9 changed files with 662 additions and 263 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,107 +21680,109 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
|
|||
auto checkMethod = nextMethod;
|
||||
nextMethod = nextMethod->mNextWithSameName;
|
||||
|
||||
if ((checkMethod != methodDef) && (typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault != NULL))
|
||||
{
|
||||
auto checkMethodInstance = typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
|
||||
if (checkMethod == methodDef)
|
||||
continue;
|
||||
|
||||
if (((checkMethodInstance->mChainType == BfMethodChainType_None) || (checkMethodInstance->mChainType == BfMethodChainType_ChainHead)) &&
|
||||
(checkMethodInstance->GetExplicitInterface() == methodInstance->GetExplicitInterface()) &&
|
||||
(checkMethod->mIsMutating == methodDef->mIsMutating) &&
|
||||
(CompareMethodSignatures(checkMethodInstance, mCurMethodInstance)))
|
||||
{
|
||||
bool canChain = false;
|
||||
auto checkMethodInstance = typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
|
||||
if (checkMethodInstance == NULL)
|
||||
continue;
|
||||
|
||||
if ((methodDef->mParams.empty()) &&
|
||||
(checkMethodInstance->mMethodDef->mIsStatic == methodInstance->mMethodDef->mIsStatic))
|
||||
if (((checkMethodInstance->mChainType == BfMethodChainType_None) || (checkMethodInstance->mChainType == BfMethodChainType_ChainHead)) &&
|
||||
(checkMethodInstance->GetExplicitInterface() == methodInstance->GetExplicitInterface()) &&
|
||||
(checkMethod->mIsMutating == methodDef->mIsMutating) &&
|
||||
(CompareMethodSignatures(checkMethodInstance, mCurMethodInstance)))
|
||||
{
|
||||
bool canChain = false;
|
||||
|
||||
if ((methodDef->mParams.empty()) &&
|
||||
(checkMethodInstance->mMethodDef->mIsStatic == methodInstance->mMethodDef->mIsStatic))
|
||||
{
|
||||
if ((methodDef->mMethodType == BfMethodType_CtorNoBody) || (methodDef->mMethodType == BfMethodType_Dtor))
|
||||
canChain = true;
|
||||
else if (methodDef->mMethodType == BfMethodType_Normal)
|
||||
{
|
||||
if ((methodDef->mMethodType == BfMethodType_CtorNoBody) || (methodDef->mMethodType == BfMethodType_Dtor))
|
||||
if ((methodDef->mName == BF_METHODNAME_MARKMEMBERS) ||
|
||||
(methodDef->mName == BF_METHODNAME_MARKMEMBERS_STATIC) ||
|
||||
(methodDef->mName == BF_METHODNAME_FIND_TLS_MEMBERS))
|
||||
canChain = true;
|
||||
else if (methodDef->mMethodType == BfMethodType_Normal)
|
||||
{
|
||||
if ((methodDef->mName == BF_METHODNAME_MARKMEMBERS) ||
|
||||
(methodDef->mName == BF_METHODNAME_MARKMEMBERS_STATIC) ||
|
||||
(methodDef->mName == BF_METHODNAME_FIND_TLS_MEMBERS))
|
||||
canChain = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (canChain)
|
||||
}
|
||||
|
||||
if (canChain)
|
||||
{
|
||||
bool isBetter;
|
||||
bool isWorse;
|
||||
CompareDeclTypes(checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse);
|
||||
if (isBetter && !isWorse)
|
||||
{
|
||||
bool isBetter;
|
||||
bool isWorse;
|
||||
CompareDeclTypes(checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse);
|
||||
if (isBetter && !isWorse)
|
||||
{
|
||||
methodInstance->mChainType = BfMethodChainType_ChainHead;
|
||||
checkMethodInstance->mChainType = BfMethodChainType_ChainMember;
|
||||
}
|
||||
else
|
||||
{
|
||||
checkMethodInstance->mChainType = BfMethodChainType_ChainHead;
|
||||
methodInstance->mChainType = BfMethodChainType_ChainMember;
|
||||
}
|
||||
methodInstance->mChainType = BfMethodChainType_ChainHead;
|
||||
checkMethodInstance->mChainType = BfMethodChainType_ChainMember;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType))
|
||||
continue;
|
||||
|
||||
bool silentlyAllow = false;
|
||||
bool extensionWarn = false;
|
||||
if (checkMethod->mDeclaringType != methodDef->mDeclaringType)
|
||||
{
|
||||
if (typeInstance->IsInterface())
|
||||
{
|
||||
if (methodDef->mIsOverride)
|
||||
checkMethodInstance->mChainType = BfMethodChainType_ChainHead;
|
||||
methodInstance->mChainType = BfMethodChainType_ChainMember;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType))
|
||||
continue;
|
||||
|
||||
bool silentlyAllow = false;
|
||||
bool extensionWarn = false;
|
||||
if (checkMethod->mDeclaringType != methodDef->mDeclaringType)
|
||||
{
|
||||
if (typeInstance->IsInterface())
|
||||
{
|
||||
if (methodDef->mIsOverride)
|
||||
silentlyAllow = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((methodDef->mIsOverride) && (checkMethod->mIsExtern))
|
||||
{
|
||||
silentlyAllow = true;
|
||||
methodInstance->mIsInnerOverride = true;
|
||||
CheckOverridenMethod(methodInstance, checkMethodInstance);
|
||||
}
|
||||
else if ((methodDef->mDeclaringType->mProject != checkMethod->mDeclaringType->mProject) &&
|
||||
(!checkMethod->mDeclaringType->IsExtension()))
|
||||
{
|
||||
foundHiddenMethod = true;
|
||||
if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mIsStatic))
|
||||
silentlyAllow = true;
|
||||
else if (methodDef->mIsNew)
|
||||
silentlyAllow = true;
|
||||
else
|
||||
extensionWarn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((methodDef->mIsOverride) && (checkMethod->mIsExtern))
|
||||
{
|
||||
silentlyAllow = true;
|
||||
methodInstance->mIsInnerOverride = true;
|
||||
CheckOverridenMethod(methodInstance, checkMethodInstance);
|
||||
}
|
||||
else if ((methodDef->mDeclaringType->mProject != checkMethod->mDeclaringType->mProject) &&
|
||||
(!checkMethod->mDeclaringType->IsExtension()))
|
||||
{
|
||||
foundHiddenMethod = true;
|
||||
if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mIsStatic))
|
||||
silentlyAllow = true;
|
||||
else if (methodDef->mIsNew)
|
||||
silentlyAllow = true;
|
||||
else
|
||||
extensionWarn = true;
|
||||
}
|
||||
else
|
||||
silentlyAllow = true;
|
||||
}
|
||||
silentlyAllow = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((checkMethod->mCommutableKind == BfCommutableKind_Reverse) || (methodDef->mCommutableKind == BfCommutableKind_Reverse))
|
||||
silentlyAllow = true;
|
||||
|
||||
if (!silentlyAllow)
|
||||
if ((checkMethod->mCommutableKind == BfCommutableKind_Reverse) || (methodDef->mCommutableKind == BfCommutableKind_Reverse))
|
||||
silentlyAllow = true;
|
||||
|
||||
if (!silentlyAllow)
|
||||
{
|
||||
if ((!methodDef->mName.IsEmpty()) || (checkMethodInstance->mMethodDef->mIsOperator))
|
||||
{
|
||||
if ((!methodDef->mName.IsEmpty()) || (checkMethodInstance->mMethodDef->mIsOperator))
|
||||
{
|
||||
auto refNode = methodDef->GetRefNode();
|
||||
BfError* bfError;
|
||||
if (extensionWarn)
|
||||
bfError = Warn(BfWarning_CS0114_MethodHidesInherited,
|
||||
StrFormat("This method hides a method in the root type definition. Use the 'new' keyword if the hiding was intentional. Note that this method is not callable from project '%s'.",
|
||||
checkMethod->mDeclaringType->mProject->mName.c_str()), refNode);
|
||||
else
|
||||
bfError = Fail("Method already declared with the same parameter types", refNode, true);
|
||||
if (bfError != NULL)
|
||||
mCompiler->mPassInstance->MoreInfo("First declaration", checkMethod->GetRefNode());
|
||||
}
|
||||
auto refNode = methodDef->GetRefNode();
|
||||
BfError* bfError;
|
||||
if (extensionWarn)
|
||||
bfError = Warn(BfWarning_CS0114_MethodHidesInherited,
|
||||
StrFormat("This method hides a method in the root type definition. Use the 'new' keyword if the hiding was intentional. Note that this method is not callable from project '%s'.",
|
||||
checkMethod->mDeclaringType->mProject->mName.c_str()), refNode);
|
||||
else
|
||||
bfError = Fail("Method already declared with the same parameter types", refNode, true);
|
||||
if (bfError != NULL)
|
||||
mCompiler->mPassInstance->MoreInfo("First declaration", checkMethod->GetRefNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4370,103 +4370,109 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
|
||||
BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount);
|
||||
|
||||
// Pass 2
|
||||
for (auto methodDef : typeDef->mMethods)
|
||||
// Def passes. First non-overrides then overrides (for in-place overrides in methods)
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
{
|
||||
auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodDef->mIdx];
|
||||
for (auto methodDef : typeDef->mMethods)
|
||||
{
|
||||
if ((pass == 1) != (methodDef->mIsOverride))
|
||||
continue;
|
||||
|
||||
if ((methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_AlwaysInclude) &&
|
||||
(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingDecl))
|
||||
{
|
||||
BfLogSysM("Skipping GetMethodInstance on MethodDef: %p OnDemandKind: %d\n", methodDef, methodInstanceGroup->mOnDemandKind);
|
||||
continue;
|
||||
}
|
||||
auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodDef->mIdx];
|
||||
|
||||
if (methodDef->mMethodType == BfMethodType_Init)
|
||||
continue;
|
||||
|
||||
int prevWorklistSize = (int)mContext->mMethodWorkList.size();
|
||||
auto moduleMethodInstance = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), ((methodDef->mGenericParams.size() != 0) || (typeInstance->IsUnspecializedType())) ? BfGetMethodInstanceFlag_UnspecializedPass : BfGetMethodInstanceFlag_None);
|
||||
|
||||
auto methodInstance = moduleMethodInstance.mMethodInstance;
|
||||
if (methodInstance == NULL)
|
||||
{
|
||||
BF_ASSERT(typeInstance->IsGenericTypeInstance() && (typeInstance->mTypeDef->mIsCombinedPartial));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((!mCompiler->mIsResolveOnly) &&
|
||||
((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) || (!typeInstance->IsReified())))
|
||||
{
|
||||
bool forceMethodImpl = false;
|
||||
|
||||
BfCustomAttributes* customAttributes = methodInstance->GetCustomAttributes();
|
||||
if ((customAttributes != NULL) && (typeInstance->IsReified()))
|
||||
if ((methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_AlwaysInclude) &&
|
||||
(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingDecl))
|
||||
{
|
||||
for (auto& attr : customAttributes->mAttributes)
|
||||
{
|
||||
auto attrTypeInst = attr.mType->ToTypeInstance();
|
||||
auto attrCustomAttributes = attrTypeInst->mCustomAttributes;
|
||||
if (attrCustomAttributes == NULL)
|
||||
continue;
|
||||
BfLogSysM("Skipping GetMethodInstance on MethodDef: %p OnDemandKind: %d\n", methodDef, methodInstanceGroup->mOnDemandKind);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto& attrAttr : attrCustomAttributes->mAttributes)
|
||||
if (methodDef->mMethodType == BfMethodType_Init)
|
||||
continue;
|
||||
|
||||
int prevWorklistSize = (int)mContext->mMethodWorkList.size();
|
||||
auto moduleMethodInstance = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), ((methodDef->mGenericParams.size() != 0) || (typeInstance->IsUnspecializedType())) ? BfGetMethodInstanceFlag_UnspecializedPass : BfGetMethodInstanceFlag_None);
|
||||
|
||||
auto methodInstance = moduleMethodInstance.mMethodInstance;
|
||||
if (methodInstance == NULL)
|
||||
{
|
||||
BF_ASSERT(typeInstance->IsGenericTypeInstance() && (typeInstance->mTypeDef->mIsCombinedPartial));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((!mCompiler->mIsResolveOnly) &&
|
||||
((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) || (!typeInstance->IsReified())))
|
||||
{
|
||||
bool forceMethodImpl = false;
|
||||
|
||||
BfCustomAttributes* customAttributes = methodInstance->GetCustomAttributes();
|
||||
if ((customAttributes != NULL) && (typeInstance->IsReified()))
|
||||
{
|
||||
for (auto& attr : customAttributes->mAttributes)
|
||||
{
|
||||
if (attrAttr.mType->ToTypeInstance()->mTypeDef == mCompiler->mAttributeUsageAttributeTypeDef)
|
||||
auto attrTypeInst = attr.mType->ToTypeInstance();
|
||||
auto attrCustomAttributes = attrTypeInst->mCustomAttributes;
|
||||
if (attrCustomAttributes == NULL)
|
||||
continue;
|
||||
|
||||
for (auto& attrAttr : attrCustomAttributes->mAttributes)
|
||||
{
|
||||
// Check for Flags arg
|
||||
if (attrAttr.mCtorArgs.size() < 2)
|
||||
continue;
|
||||
auto constant = attrTypeInst->mConstHolder->GetConstant(attrAttr.mCtorArgs[1]);
|
||||
if (constant == NULL)
|
||||
continue;
|
||||
if (constant->mTypeCode == BfTypeCode_Boolean)
|
||||
continue;
|
||||
if ((constant->mInt8 & BfCustomAttributeFlags_AlwaysIncludeTarget) != 0)
|
||||
forceMethodImpl = true;
|
||||
if (attrAttr.mType->ToTypeInstance()->mTypeDef == mCompiler->mAttributeUsageAttributeTypeDef)
|
||||
{
|
||||
// Check for Flags arg
|
||||
if (attrAttr.mCtorArgs.size() < 2)
|
||||
continue;
|
||||
auto constant = attrTypeInst->mConstHolder->GetConstant(attrAttr.mCtorArgs[1]);
|
||||
if (constant == NULL)
|
||||
continue;
|
||||
if (constant->mTypeCode == BfTypeCode_Boolean)
|
||||
continue;
|
||||
if ((constant->mInt8 & BfCustomAttributeFlags_AlwaysIncludeTarget) != 0)
|
||||
forceMethodImpl = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeInstance->mTypeDef->mProject->mTargetType == BfTargetType_BeefTest)
|
||||
{
|
||||
if ((customAttributes != NULL) && (customAttributes->Contains(mCompiler->mTestAttributeTypeDef)))
|
||||
if (typeInstance->mTypeDef->mProject->mTargetType == BfTargetType_BeefTest)
|
||||
{
|
||||
forceMethodImpl = true;
|
||||
if ((customAttributes != NULL) && (customAttributes->Contains(mCompiler->mTestAttributeTypeDef)))
|
||||
{
|
||||
forceMethodImpl = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (forceMethodImpl)
|
||||
{
|
||||
if (!typeInstance->IsReified())
|
||||
mContext->mScratchModule->PopulateType(typeInstance, BfPopulateType_Data);
|
||||
// Reify method
|
||||
mContext->mScratchModule->GetMethodInstance(typeInstance, methodDef, BfTypeVector());
|
||||
BF_ASSERT(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingReference);
|
||||
}
|
||||
}
|
||||
|
||||
if (forceMethodImpl)
|
||||
|
||||
bool methodUsedVirtually = false;
|
||||
if (typeInstance->IsInterface())
|
||||
{
|
||||
if (!typeInstance->IsReified())
|
||||
mContext->mScratchModule->PopulateType(typeInstance, BfPopulateType_Data);
|
||||
// Reify method
|
||||
mContext->mScratchModule->GetMethodInstance(typeInstance, methodDef, BfTypeVector());
|
||||
BF_ASSERT(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Decl_AwaitingReference);
|
||||
if ((!methodDef->mIsConcrete) && (!methodDef->mIsStatic) && (!methodInstance->HasSelf()))
|
||||
SlotInterfaceMethod(methodInstance);
|
||||
}
|
||||
else if (!methodDef->IsEmptyPartial())
|
||||
{
|
||||
methodUsedVirtually = SlotVirtualMethod(methodInstance, &ambiguityContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool methodUsedVirtually = false;
|
||||
if (typeInstance->IsInterface())
|
||||
{
|
||||
if ((!methodDef->mIsConcrete) && (!methodDef->mIsStatic) && (!methodInstance->HasSelf()))
|
||||
SlotInterfaceMethod(methodInstance);
|
||||
}
|
||||
else if (!methodDef->IsEmptyPartial())
|
||||
{
|
||||
methodUsedVirtually = SlotVirtualMethod(methodInstance, &ambiguityContext);
|
||||
}
|
||||
|
||||
// This is important for reducing latency of autocomplete popup, but it's important we don't allow the autocomplete
|
||||
// thread to cause any reentry issues by re-populating a type at an "inopportune time". We do allow certain
|
||||
// reentries in PopulateType, but not when we're resolving fields (for example)
|
||||
if ((mContext->mFieldResolveReentrys.size() == 0) && (!mContext->mResolvingVarField))
|
||||
{
|
||||
disableYield.Release();
|
||||
mSystem->CheckLockYield();
|
||||
disableYield.Acquire();
|
||||
// This is important for reducing latency of autocomplete popup, but it's important we don't allow the autocomplete
|
||||
// thread to cause any reentry issues by re-populating a type at an "inopportune time". We do allow certain
|
||||
// reentries in PopulateType, but not when we're resolving fields (for example)
|
||||
if ((mContext->mFieldResolveReentrys.size() == 0) && (!mContext->mResolvingVarField))
|
||||
{
|
||||
disableYield.Release();
|
||||
mSystem->CheckLockYield();
|
||||
disableYield.Acquire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
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);
|
||||
Emit(dataPtr, 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;
|
||||
mNamedFunctionMap.Remove(ceFunction->mName);
|
||||
mFunctions.Remove(itr);
|
||||
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;
|
||||
mCallStack.pop_back();
|
||||
}
|
||||
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);
|
||||
|
@ -1749,18 +2015,93 @@ bool CeMachine::Execute()
|
|||
}
|
||||
result = *(uint32*)(memStart + ceAddr);
|
||||
}
|
||||
break;
|
||||
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();
|
||||
|
||||
|
|
|
@ -49,20 +49,32 @@ enum CeOp : int16
|
|||
CeOp_FrameAddr32,
|
||||
CeOp_FrameAddr64,
|
||||
|
||||
CeOp_Zero,
|
||||
CEOP_SIZED(Const),
|
||||
CEOP_SIZED(Load),
|
||||
CEOP_SIZED(Store),
|
||||
CEOP_SIZED(Store),
|
||||
CEOP_SIZED(Move),
|
||||
CEOP_SIZED(Push),
|
||||
|
||||
CEOP_SIZED(Pop),
|
||||
|
||||
CeOp_AdjustSP,
|
||||
CeOp_Call,
|
||||
|
||||
CeOp_Conv_I32_I64,
|
||||
|
||||
CEOP_SIZED_NUMERIC_PLUSF(Add),
|
||||
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);
|
||||
void ProcessWorkQueue();
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue