1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 20:12:21 +02:00

Fixed StructRet issues with delegates and lambdas

This commit is contained in:
Brian Fiete 2020-05-13 07:43:59 -07:00
parent d2edcd2ae9
commit d5a2db5a06
3 changed files with 67 additions and 20 deletions

View file

@ -9542,7 +9542,8 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
{
hasThis = true;
methodInstance->GetIRFunctionInfo(mModule, irReturnType, irParamTypes);
irParamTypes[0] = mModule->mBfIRBuilder->MapType(useTypeInstance);
int thisIdx = methodInstance->HasStructRet() ? 1 : 0;
irParamTypes[thisIdx] = mModule->mBfIRBuilder->MapType(useTypeInstance);
}
else
{
@ -9558,6 +9559,12 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
auto funcType = mModule->mBfIRBuilder->CreateFunctionType(irReturnType, irParamTypes);
funcValue = mModule->mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, methodName);
if (methodInstance->HasStructRet())
{
mModule->mBfIRBuilder->Func_AddAttribute(funcValue, 1, BfIRAttribute_NoAlias);
mModule->mBfIRBuilder->Func_AddAttribute(funcValue, 1, BfIRAttribute_StructRet);
}
auto srcCallingConv = mModule->GetIRCallingConvention(methodInstance);
if ((!hasThis) && (methodInstance->mCallingConvention == BfCallingConvention_Stdcall))
srcCallingConv = BfIRCallingConv_StdCall;
@ -9571,6 +9578,11 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
fieldIdx = 0;
SizedArray<BfIRValue, 8> irArgs;
int argIdx = 0;
if (methodInstance->HasStructRet())
irArgs.push_back(mModule->mBfIRBuilder->GetArgument(argIdx++));
for (int implicitParamIdx = bindMethodInstance->HasThis() ? -1 : 0; implicitParamIdx < implicitParamCount; implicitParamIdx++)
{
auto fieldInst = &useTypeInstance->mFieldInstances[fieldIdx];
@ -9585,13 +9597,16 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
disableSplat = true;
}
}
auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(mModule->mBfIRBuilder->GetArgument(0), 0, gepIdx);
int thisIdx = methodInstance->HasStructRet() ? 1 : 0;
auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(mModule->mBfIRBuilder->GetArgument(thisIdx), 0, gepIdx);
BfTypedValue typedVal(fieldPtr, fieldType, true);
PushArg(typedVal, irArgs, disableSplat);
fieldIdx++;
}
int argIdx = hasThis ? 1 : 0;
if (hasThis)
argIdx++;
for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++)
{
auto paramType = methodInstance->GetParamType(paramIdx);
@ -9608,17 +9623,19 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
auto bindFuncVal = bindResult.mFunc;
if (mModule->mCompiler->mOptions.mAllowHotSwapping)
bindFuncVal = mModule->mBfIRBuilder->RemapBindFunction(bindFuncVal);
auto result = mModule->mBfIRBuilder->CreateCall(bindFuncVal, irArgs);
auto callInst = mModule->mBfIRBuilder->CreateCall(bindFuncVal, irArgs);
if (methodInstance->HasStructRet())
mModule->mBfIRBuilder->Call_AddAttribute(callInst, 1, BfIRAttribute_StructRet);
auto destCallingConv = mModule->GetIRCallingConvention(bindMethodInstance);
if (destCallingConv != BfIRCallingConv_CDecl)
mModule->mBfIRBuilder->SetCallCallingConv(result, destCallingConv);
if (methodInstance->mReturnType->IsValuelessType())
mModule->mBfIRBuilder->SetCallCallingConv(callInst, destCallingConv);
if ((methodInstance->mReturnType->IsValuelessType()) || (methodInstance->HasStructRet()))
{
mModule->mBfIRBuilder->CreateRetVoid();
}
else
{
mModule->mBfIRBuilder->CreateRet(result);
mModule->mBfIRBuilder->CreateRet(callInst);
}
mModule->mBfIRBuilder->SetActiveFunction(prevActiveFunction);
@ -10383,14 +10400,10 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
// If we are allowing hot swapping, we need to always mangle the name to non-static because if we add a capture
// later then we need to have the mangled names match
methodDef->mIsStatic = (closureTypeInst == NULL) && (!mModule->mCompiler->mOptions.mAllowHotSwapping);
SizedArray<BfIRType, 3> newTypes;
SizedArray<BfIRType, 8> origParamTypes;
BfIRType origReturnType;
if (!methodDef->mIsStatic)
newTypes.push_back(mModule->mBfIRBuilder->MapType(useTypeInstance));
if (invokeMethodInstance != NULL)
{
auto invokeFunctionType = mModule->mBfIRBuilder->MapMethod(invokeMethodInstance);
@ -10401,7 +10414,19 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
origReturnType = mModule->mBfIRBuilder->MapType(mModule->GetPrimitiveType(BfTypeCode_None));
}
for (int i = methodDef->mIsStatic ? 0 : 1; i < (int)origParamTypes.size(); i++)
SizedArray<BfIRType, 3> newTypes;
if (invokeMethodInstance->HasStructRet())
newTypes.push_back(origParamTypes[0]);
if (!methodDef->mIsStatic)
newTypes.push_back(mModule->mBfIRBuilder->MapType(useTypeInstance));
int paramStartIdx = 0;
if (invokeMethodInstance->HasStructRet())
paramStartIdx++;
if (!methodDef->mIsStatic)
paramStartIdx++;
for (int i = paramStartIdx; i < (int)origParamTypes.size(); i++)
newTypes.push_back(origParamTypes[i]);
auto closureFuncType = mModule->mBfIRBuilder->CreateFunctionType(origReturnType, newTypes, false);
@ -13195,11 +13220,8 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
mModule->Warn(0, "Scope specifier was not referenced in mixin", scopedInvocationTarget->mScopeName);
}
// It's tempting to do this, but it is really just covering up other issues.
//mModule->mBfIRBuilder->SetCurrentDebugLocation(prevDebugLoc);
// But does THIS work?
mModule->mBfIRBuilder->RestoreDebugLocation();
mModule->mBfIRBuilder->DupDebugLocation();
}
void BfExprEvaluator::SetMethodElementType(BfAstNode* target)

View file

@ -1098,7 +1098,7 @@ void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen)
//mBfIRBuilder->mDbgVerifyCodeGen = true;
if (
(mModuleName == "-")
//|| (mModuleName == "Raylib_Color")
//|| (mModuleName == "Blurg")
//|| (mModuleName == "System_Int32")
//|| (mModuleName == "Hey_Dude_Bro_TestClass")
)
@ -13301,6 +13301,8 @@ void BfModule::CreateDelegateInvokeMethod()
auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, memberFuncPtrPtr);
auto funcPtr = mBfIRBuilder->CreateLoad(funcPtrPtr);
nonStaticResult = mBfIRBuilder->CreateCall(funcPtr, memberFuncArgs);
if (mCurMethodInstance->HasStructRet())
mBfIRBuilder->Call_AddAttribute(nonStaticResult, 1, BfIRAttribute_StructRet);
if (callingConv != BfIRCallingConv_CDecl)
mBfIRBuilder->SetCallCallingConv(nonStaticResult, callingConv);
mCurMethodState->SetHadReturn(false);
@ -13317,6 +13319,8 @@ void BfModule::CreateDelegateInvokeMethod()
auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, staticFuncPtrPtr);
auto funcPtr = mBfIRBuilder->CreateLoad(funcPtrPtr);
staticResult = mBfIRBuilder->CreateCall(funcPtr, staticFuncArgs);
if (mCurMethodInstance->HasStructRet())
mBfIRBuilder->Call_AddAttribute(staticResult, 1, BfIRAttribute_StructRet);
if (callingConv == BfIRCallingConv_ThisCall)
callingConv = BfIRCallingConv_CDecl;
if (callingConv != BfIRCallingConv_CDecl)
@ -20021,7 +20025,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
if ((!methodInstance->IsSpecializedGenericMethodOrType()) && (!mCurTypeInstance->IsBoxed()) &&
(!methodDef->mIsLocalMethod) &&
(!CheckDefineMemberProtection(methodDef->mProtection, methodInstance->mReturnType)))
(!CheckDefineMemberProtection(methodDef->mProtection, methodInstance->mReturnType)) &&
(!methodDef->mReturnTypeRef->IsTemporary()))
{
if (methodDef->mMethodType == BfMethodType_PropertyGetter)
{

View file

@ -73,5 +73,25 @@ namespace Tests
delete dlg;
Test.Assert(b == 221);
}
struct StructA
{
public int mA0;
public this(int v) { mA0 = v; }
}
[Test]
public static void TestStructRetCapture()
{
StructA sa = .(5);
StructA saGetter() { return sa; }
delegate StructA() myTest = scope => saGetter;
var ret = myTest();
Test.Assert(ret.mA0 == 5);
delegate StructA() myTest2 = scope [&] () => { return saGetter(); };
var ret2 = myTest2();
Test.Assert(ret2.mA0 == 5);
}
}
}