mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-12 21:34:11 +02:00
Allow comptime attempts on generic interface dispatches
This commit is contained in:
parent
4b8983a013
commit
f1d9964ba1
3 changed files with 45 additions and 25 deletions
|
@ -5214,7 +5214,7 @@ void BfExprEvaluator::PerformCallChecks(BfMethodInstance* methodInstance, BfAstN
|
||||||
mModule->CheckErrorAttributes(methodInstance->GetOwner(), methodInstance, customAttributes, targetSrc);
|
mModule->CheckErrorAttributes(methodInstance->GetOwner(), methodInstance, customAttributes, targetSrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, 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, BfCreateCallFlags callFlags)
|
||||||
{
|
{
|
||||||
// static int sCallIdx = 0;
|
// static int sCallIdx = 0;
|
||||||
// if (!mModule->mCompiler->mIsResolveOnly)
|
// if (!mModule->mCompiler->mIsResolveOnly)
|
||||||
|
@ -5457,6 +5457,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
||||||
{
|
{
|
||||||
doConstReturn = true;
|
doConstReturn = true;
|
||||||
}
|
}
|
||||||
|
else if (((callFlags & BfCreateCallFlags_GenericParamThis) != 0) && (methodInstance->GetOwner()->IsInterface()))
|
||||||
|
{
|
||||||
|
mModule->Warn(0, "Concrete method may fail to comptime during specialization", targetSrc);
|
||||||
|
doConstReturn = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CeEvalFlags evalFlags = CeEvalFlags_None;
|
CeEvalFlags evalFlags = CeEvalFlags_None;
|
||||||
|
@ -5502,7 +5507,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
||||||
{
|
{
|
||||||
if (returnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))
|
if (returnType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))
|
||||||
{
|
{
|
||||||
if (mExpectingType->IsUndefSizedArray())
|
if ((mExpectingType != NULL) && (mExpectingType->IsUndefSizedArray()))
|
||||||
{
|
{
|
||||||
if (returnType->GetUnderlyingType() == mExpectingType->GetUnderlyingType())
|
if (returnType->GetUnderlyingType() == mExpectingType->GetUnderlyingType())
|
||||||
return mModule->GetDefaultTypedValue(mExpectingType, true, BfDefaultValueKind_Undef);
|
return mModule->GetDefaultTypedValue(mExpectingType, true, BfDefaultValueKind_Undef);
|
||||||
|
@ -5922,7 +5927,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
||||||
//argIdx++;
|
//argIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTailCall)
|
if ((callFlags & BfCreateCallFlags_TailCall) != 0)
|
||||||
mModule->mBfIRBuilder->SetTailCall(callInst);
|
mModule->mBfIRBuilder->SetTailCall(callInst);
|
||||||
|
|
||||||
if (methodDef->mIsNoReturn)
|
if (methodDef->mIsNoReturn)
|
||||||
|
@ -6001,9 +6006,9 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodMatcher* methodMatcher, BfTyped
|
||||||
|
|
||||||
PerformCallChecks(moduleMethodInstance.mMethodInstance, methodMatcher->mTargetSrc);
|
PerformCallChecks(moduleMethodInstance.mMethodInstance, methodMatcher->mTargetSrc);
|
||||||
|
|
||||||
BfCreateFallFlags callFlags = BfCreateFallFlags_None;
|
BfCreateCallFlags callFlags = BfCreateCallFlags_None;
|
||||||
if (methodMatcher->mAllowImplicitRef)
|
if (methodMatcher->mAllowImplicitRef)
|
||||||
callFlags = (BfCreateFallFlags)(callFlags | BfCreateFallFlags_AllowImplicitRef);
|
callFlags = (BfCreateCallFlags)(callFlags | BfCreateCallFlags_AllowImplicitRef);
|
||||||
return CreateCall(methodMatcher->mTargetSrc, target, BfTypedValue(), methodMatcher->mBestMethodDef, moduleMethodInstance, callFlags, methodMatcher->mArguments);
|
return CreateCall(methodMatcher->mTargetSrc, target, BfTypedValue(), methodMatcher->mBestMethodDef, moduleMethodInstance, callFlags, methodMatcher->mArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6335,10 +6340,10 @@ void BfExprEvaluator::AddCallDependencies(BfMethodInstance* methodInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: delete argumentsZ
|
//TODO: delete argumentsZ
|
||||||
BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValue& inTarget, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance moduleMethodInstance, BfCreateFallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade)
|
BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValue& inTarget, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance moduleMethodInstance, BfCreateCallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade)
|
||||||
{
|
{
|
||||||
bool bypassVirtual = (callFlags & BfCreateFallFlags_BypassVirtual) != 0;
|
bool bypassVirtual = (callFlags & BfCreateCallFlags_BypassVirtual) != 0;
|
||||||
bool skipThis = (callFlags & BfCreateFallFlags_SkipThis) != 0;;
|
bool skipThis = (callFlags & BfCreateCallFlags_SkipThis) != 0;;
|
||||||
|
|
||||||
static int sCallIdx = 0;
|
static int sCallIdx = 0;
|
||||||
if (!mModule->mCompiler->mIsResolveOnly)
|
if (!mModule->mCompiler->mIsResolveOnly)
|
||||||
|
@ -7050,7 +7055,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
||||||
refNode = targetSrc;
|
refNode = targetSrc;
|
||||||
|
|
||||||
if ((wantType->IsRef()) && (!argValue.mType->IsRef()) &&
|
if ((wantType->IsRef()) && (!argValue.mType->IsRef()) &&
|
||||||
(((callFlags & BfCreateFallFlags_AllowImplicitRef) != 0) || (wantType->IsIn())))
|
(((callFlags & BfCreateCallFlags_AllowImplicitRef) != 0) || (wantType->IsIn())))
|
||||||
argValue = mModule->ToRef(argValue, (BfRefType*)wantType);
|
argValue = mModule->ToRef(argValue, (BfRefType*)wantType);
|
||||||
|
|
||||||
if (mModule->mCurMethodState != NULL)
|
if (mModule->mCurMethodState != NULL)
|
||||||
|
@ -7277,8 +7282,12 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
||||||
return BfTypedValue();
|
return BfTypedValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfCreateCallFlags physCallFlags = BfCreateCallFlags_None;
|
||||||
|
if ((origTarget.mType != NULL) && (origTarget.mType->IsGenericParam()))
|
||||||
|
physCallFlags = (BfCreateCallFlags)(physCallFlags | BfCreateCallFlags_GenericParamThis);
|
||||||
|
|
||||||
auto func = moduleMethodInstance.mFunc;
|
auto func = moduleMethodInstance.mFunc;
|
||||||
BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs);
|
BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs, NULL, physCallFlags);
|
||||||
|
|
||||||
// This gets triggered for non-sret (ie: comptime) composite returns so they aren't considered readonly
|
// This gets triggered for non-sret (ie: comptime) composite returns so they aren't considered readonly
|
||||||
if ((callResult.mKind == BfTypedValueKind_Value) && (!callResult.mValue.IsConst()) &&
|
if ((callResult.mKind == BfTypedValueKind_Value) && (!callResult.mValue.IsConst()) &&
|
||||||
|
@ -7480,7 +7489,7 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
|
||||||
if (isFailurePass)
|
if (isFailurePass)
|
||||||
mModule->Fail(StrFormat("'%s' is inaccessible due to its protection level", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
mModule->Fail(StrFormat("'%s' is inaccessible due to its protection level", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
||||||
prevBindResult.Restore();
|
prevBindResult.Restore();
|
||||||
return CreateCall(methodMatcher.mTargetSrc, target, BfTypedValue(), methodMatcher.mBestMethodDef, moduleMethodInstance, BfCreateFallFlags_None, methodMatcher.mArguments);
|
return CreateCall(methodMatcher.mTargetSrc, target, BfTypedValue(), methodMatcher.mBestMethodDef, moduleMethodInstance, BfCreateCallFlags_None, methodMatcher.mArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sInvocationIdx = 0;
|
static int sInvocationIdx = 0;
|
||||||
|
@ -9155,11 +9164,11 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
mModule->Fail(StrFormat("Method '%s' can only be invoked at comptime. Consider adding [Comptime] to the current method.", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
mModule->Fail(StrFormat("Method '%s' can only be invoked at comptime. Consider adding [Comptime] to the current method.", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
BfCreateFallFlags subCallFlags = BfCreateFallFlags_None;
|
BfCreateCallFlags subCallFlags = BfCreateCallFlags_None;
|
||||||
if (bypassVirtual)
|
if (bypassVirtual)
|
||||||
subCallFlags = (BfCreateFallFlags)(subCallFlags | BfCreateFallFlags_BypassVirtual);
|
subCallFlags = (BfCreateCallFlags)(subCallFlags | BfCreateCallFlags_BypassVirtual);
|
||||||
if (skipThis)
|
if (skipThis)
|
||||||
subCallFlags = (BfCreateFallFlags)(subCallFlags | BfCreateFallFlags_SkipThis);
|
subCallFlags = (BfCreateCallFlags)(subCallFlags | BfCreateCallFlags_SkipThis);
|
||||||
result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, subCallFlags, argValues.mResolvedArgs, &argCascade);
|
result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, subCallFlags, argValues.mResolvedArgs, &argCascade);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9720,13 +9729,19 @@ void BfExprEvaluator::LookupQualifiedStaticField(BfAstNode* nameNode, BfIdentifi
|
||||||
{
|
{
|
||||||
mResult = LookupField(nameRight, BfTypedValue(genericParamInstance->mTypeConstraint), findName);
|
mResult = LookupField(nameRight, BfTypedValue(genericParamInstance->mTypeConstraint), findName);
|
||||||
if ((mResult) || (mPropDef != NULL))
|
if ((mResult) || (mPropDef != NULL))
|
||||||
|
{
|
||||||
|
mOrigPropTarget = lookupType;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (auto constraint : genericParamInstance->mInterfaceConstraints)
|
for (auto constraint : genericParamInstance->mInterfaceConstraints)
|
||||||
{
|
{
|
||||||
mResult = LookupField(nameRight, BfTypedValue(constraint), findName);
|
mResult = LookupField(nameRight, BfTypedValue(constraint), findName);
|
||||||
if ((mResult) || (mPropDef != NULL))
|
if ((mResult) || (mPropDef != NULL))
|
||||||
|
{
|
||||||
|
mOrigPropTarget = lookupType;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17059,7 +17074,10 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mResult = CreateCall(mPropSrc, methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args);
|
{
|
||||||
|
BfCreateCallFlags callFlags = mOrigPropTarget.mType->IsGenericParam() ? BfCreateCallFlags_GenericParamThis : BfCreateCallFlags_None;
|
||||||
|
mResult = CreateCall(mPropSrc, methodInstance.mMethodInstance, methodInstance.mFunc, mPropDefBypassVirtual, args, NULL, callFlags);
|
||||||
|
}
|
||||||
if (mResult.mType != NULL)
|
if (mResult.mType != NULL)
|
||||||
{
|
{
|
||||||
if ((mResult.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly))
|
if ((mResult.mType->IsVar()) && (mModule->mCompiler->mIsResolveOnly))
|
||||||
|
@ -21817,7 +21835,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
argValues.push_back(resolvedArg);
|
argValues.push_back(resolvedArg);
|
||||||
resolvedArg.mTypedValue = rightValue;
|
resolvedArg.mTypedValue = rightValue;
|
||||||
argValues.push_back(resolvedArg);
|
argValues.push_back(resolvedArg);
|
||||||
mResult = CreateCall(opToken, BfTypedValue(), BfTypedValue(), moduleMethodInstance.mMethodInstance->mMethodDef, moduleMethodInstance, BfCreateFallFlags_None, argValues);
|
mResult = CreateCall(opToken, BfTypedValue(), BfTypedValue(), moduleMethodInstance.mMethodInstance->mMethodDef, moduleMethodInstance, BfCreateCallFlags_None, argValues);
|
||||||
if ((mResult) &&
|
if ((mResult) &&
|
||||||
((binaryOp == BfBinaryOp_InEquality) || (binaryOp == BfBinaryOp_StrictInEquality)))
|
((binaryOp == BfBinaryOp_InEquality) || (binaryOp == BfBinaryOp_StrictInEquality)))
|
||||||
mResult.mValue = mModule->mBfIRBuilder->CreateNot(mResult.mValue);
|
mResult.mValue = mModule->mBfIRBuilder->CreateNot(mResult.mValue);
|
||||||
|
|
|
@ -41,12 +41,14 @@ enum BfResolveArgFlags
|
||||||
BfResolveArgFlag_FromGenericParam = 2
|
BfResolveArgFlag_FromGenericParam = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BfCreateFallFlags
|
enum BfCreateCallFlags
|
||||||
{
|
{
|
||||||
BfCreateFallFlags_None,
|
BfCreateCallFlags_None,
|
||||||
BfCreateFallFlags_BypassVirtual = 1,
|
BfCreateCallFlags_BypassVirtual = 1,
|
||||||
BfCreateFallFlags_SkipThis = 2,
|
BfCreateCallFlags_SkipThis = 2,
|
||||||
BfCreateFallFlags_AllowImplicitRef = 4
|
BfCreateCallFlags_AllowImplicitRef = 4,
|
||||||
|
BfCreateCallFlags_TailCall = 8,
|
||||||
|
BfCreateCallFlags_GenericParamThis = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
class BfResolvedArg
|
class BfResolvedArg
|
||||||
|
@ -444,8 +446,8 @@ public:
|
||||||
BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
|
BfTypedValue LookupIdentifier(BfIdentifierNode* identifierNode, bool ignoreInitialError = false, bool* hadError = NULL);
|
||||||
void AddCallDependencies(BfMethodInstance* methodInstance);
|
void AddCallDependencies(BfMethodInstance* methodInstance);
|
||||||
void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc);
|
void PerformCallChecks(BfMethodInstance* methodInstance, BfAstNode* targetSrc);
|
||||||
BfTypedValue CreateCall(BfAstNode* targetSrc, 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, BfCreateCallFlags callFlags = BfCreateCallFlags_None);
|
||||||
BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, BfCreateFallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade = NULL);
|
BfTypedValue CreateCall(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, BfCreateCallFlags callFlags, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade = NULL);
|
||||||
BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target);
|
BfTypedValue CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target);
|
||||||
void MakeBaseConcrete(BfTypedValue& typedValue);
|
void MakeBaseConcrete(BfTypedValue& typedValue);
|
||||||
void SplatArgs(BfTypedValue value, SizedArrayImpl<BfIRValue>& irArgs);
|
void SplatArgs(BfTypedValue value, SizedArrayImpl<BfIRValue>& irArgs);
|
||||||
|
|
|
@ -19587,14 +19587,14 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
mBfIRBuilder->PopulateType(methodInstance->mReturnType);
|
mBfIRBuilder->PopulateType(methodInstance->mReturnType);
|
||||||
auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()), methodInstance->mReturnType, true);
|
auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()), methodInstance->mReturnType, true);
|
||||||
exprEvaluator.mReceivingValue = &returnType;
|
exprEvaluator.mReceivingValue = &returnType;
|
||||||
auto retVal = exprEvaluator.CreateCall(NULL, innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true);
|
auto retVal = exprEvaluator.CreateCall(NULL, innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, BfCreateCallFlags_TailCall);
|
||||||
BF_ASSERT(exprEvaluator.mReceivingValue == NULL); // Ensure it was actually used
|
BF_ASSERT(exprEvaluator.mReceivingValue == NULL); // Ensure it was actually used
|
||||||
mBfIRBuilder->CreateRetVoid();
|
mBfIRBuilder->CreateRetVoid();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mBfIRBuilder->PopulateType(methodInstance->mReturnType);
|
mBfIRBuilder->PopulateType(methodInstance->mReturnType);
|
||||||
auto retVal = exprEvaluator.CreateCall(NULL, innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, true);
|
auto retVal = exprEvaluator.CreateCall(NULL, innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, BfCreateCallFlags_TailCall);
|
||||||
if (mCurMethodInstance->mReturnType->IsValueType())
|
if (mCurMethodInstance->mReturnType->IsValueType())
|
||||||
retVal = LoadValue(retVal);
|
retVal = LoadValue(retVal);
|
||||||
CreateReturn(retVal.mValue);
|
CreateReturn(retVal.mValue);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue