1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-14 14:24:10 +02:00

Fixed argument cascades with ReturnValueDiscarded

This commit is contained in:
Brian Fiete 2021-01-02 08:51:04 -08:00
parent 8ceb7bf183
commit bd57172996
3 changed files with 78 additions and 23 deletions

View file

@ -5568,8 +5568,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodMatcher* methodMatcher, BfTyped
} }
PerformCallChecks(moduleMethodInstance.mMethodInstance, methodMatcher->mTargetSrc); PerformCallChecks(moduleMethodInstance.mMethodInstance, methodMatcher->mTargetSrc);
return CreateCall(methodMatcher->mTargetSrc, target, BfTypedValue(), methodMatcher->mBestMethodDef, moduleMethodInstance, false, methodMatcher->mArguments); return CreateCall(methodMatcher->mTargetSrc, target, BfTypedValue(), methodMatcher->mBestMethodDef, moduleMethodInstance, false, methodMatcher->mArguments);
} }
void BfExprEvaluator::MakeBaseConcrete(BfTypedValue& typedValue) void BfExprEvaluator::MakeBaseConcrete(BfTypedValue& typedValue)
@ -5873,7 +5873,7 @@ 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, bool bypassVirtual, SizedArrayImpl<BfResolvedArg>& argValues, bool skipThis) BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValue& inTarget, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance moduleMethodInstance, bool bypassVirtual, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade, bool skipThis)
{ {
static int sCallIdx = 0; static int sCallIdx = 0;
if (!mModule->mCompiler->mIsResolveOnly) if (!mModule->mCompiler->mIsResolveOnly)
@ -6617,7 +6617,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
} }
if ((argExprIdx != -1) && (argExprIdx < (int)argValues.size()) && ((argValues[argExprIdx].mArgFlags & BfArgFlag_Cascade) != 0)) if ((argExprIdx != -1) && (argExprIdx < (int)argValues.size()) && ((argValues[argExprIdx].mArgFlags & BfArgFlag_Cascade) != 0))
{
mUsedAsStatement = true;
argCascades.Add(argValue); argCascades.Add(argValue);
}
if (expandedParamsArray) if (expandedParamsArray)
{ {
@ -6787,9 +6790,17 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs); BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs);
if (argCascades.mSize == 1) if (argCascades.mSize == 1)
return argCascades[0]; {
if (argCascade == NULL)
return argCascades[0];
*argCascade = argCascades[0];
}
if (argCascades.mSize > 1) if (argCascades.mSize > 1)
return mModule->CreateTuple(argCascades, {}); {
if (argCascade == NULL)
return mModule->CreateTuple(argCascades, {});
*argCascade = mModule->CreateTuple(argCascades, {});
}
return callResult; return callResult;
} }
@ -8471,6 +8482,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
BfTypedValue result; BfTypedValue result;
BfTypedValue argCascade;
// //
{ {
@ -8486,26 +8498,13 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_ConstEval); mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_ConstEval);
} }
result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, bypassVirtual, argValues.mResolvedArgs, skipThis); result = CreateCall(targetSrc, callTarget, origTarget, methodDef, moduleMethodInstance, bypassVirtual, argValues.mResolvedArgs, &argCascade, skipThis);
} }
if (result) if (result)
{ {
if (result.mType->IsRef()) if (result.mType->IsRef())
result = mModule->RemoveRef(result); result = mModule->RemoveRef(result);
if (result.mType->IsSelf())
{
if (methodMatcher.mSelfType != NULL)
{
BF_ASSERT(mModule->IsInGeneric());
result = mModule->GetDefaultTypedValue(methodMatcher.mSelfType);
}
else
{
// Will be an error
result = mModule->GetDefaultTypedValue(methodMatcher.mBestMethodTypeInstance);
}
}
} }
PerformCallChecks(moduleMethodInstance.mMethodInstance, targetSrc); PerformCallChecks(moduleMethodInstance.mMethodInstance, targetSrc);
@ -8566,6 +8565,30 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
} }
} }
if (argCascade)
{
if (argCascade.mType->IsRef())
argCascade = mModule->RemoveRef(argCascade);
result = argCascade;
}
if (result)
{
if (result.mType->IsSelf())
{
if (methodMatcher.mSelfType != NULL)
{
BF_ASSERT(mModule->IsInGeneric());
result = mModule->GetDefaultTypedValue(methodMatcher.mSelfType);
}
else
{
// Will be an error
result = mModule->GetDefaultTypedValue(methodMatcher.mBestMethodTypeInstance);
}
}
}
return result; return result;
} }

View file

@ -431,7 +431,7 @@ public:
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, 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(BfAstNode* targetSrc, const BfTypedValue& target, const BfTypedValue& origTarget, BfMethodDef* methodDef, BfModuleMethodInstance methodInstance, bool bypassVirtual, SizedArrayImpl<BfResolvedArg>& argValues, BfTypedValue* argCascade = NULL, bool skipThis = false);
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);

View file

@ -4,27 +4,59 @@ namespace Tests
{ {
class Cascades class Cascades
{ {
public static void MethodA(int a, float b) struct StructA
{ {
public static int sDiscardCount;
public void ReturnValueDiscarded()
{
sDiscardCount++;
}
public void HandleResult()
{
}
public StructA Method0(int a)
{
return .();
}
} }
public static void MethodB(int a, out float b) static StructA MethodA(int a, float b)
{
return .();
}
static StructA MethodB(int a, out float b)
{ {
b = 100; b = 100;
return .();
} }
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
MethodA(1, 1.2f);
Test.Assert(StructA.sDiscardCount == 1);
StructA sa = .();
sa.Method0(1)..Method0(2).HandleResult();
Test.Assert(StructA.sDiscardCount == 2);
int a = MethodA(.. 12, 2.3f); int a = MethodA(.. 12, 2.3f);
Test.Assert(StructA.sDiscardCount == 3);
Test.Assert(a == 12); Test.Assert(a == 12);
var (b, c) = MethodA(.. 12, .. 2.3f); var (b, c) = MethodA(.. 12, .. 2.3f);
Test.Assert(StructA.sDiscardCount == 4);
Test.Assert(b == 12); Test.Assert(b == 12);
Test.Assert(c == 2.3f); Test.Assert(c == 2.3f);
var d = MethodA(.. 12, .. 2.3f); var d = MethodA(.. 12, .. 2.3f);
Test.Assert(StructA.sDiscardCount == 5);
Test.Assert(d == (12, 2.3f)); Test.Assert(d == (12, 2.3f));
var f = ref MethodB(12, .. var e); var f = ref MethodB(12, .. var e);
Test.Assert(StructA.sDiscardCount == 6);
e += 23; e += 23;
Test.Assert(e == (int)123); Test.Assert(e == (int)123);
Test.Assert(f == (int)123); Test.Assert(f == (int)123);