Struct function return value

This commit is contained in:
drmortalwombat 2021-10-16 16:45:08 +02:00
parent 815f64d14c
commit 19a54432f6
2 changed files with 148 additions and 24 deletions

View File

@ -1921,6 +1921,57 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
block->Append(fins); block->Append(fins);
} }
Declaration * decResult = nullptr;
if (ftype->mBase->mType == DT_TYPE_STRUCT)
{
int nindex = proc->mNumLocals++;
Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE);
vdec->mVarIndex = nindex;
vdec->mBase = ftype->mBase;
vdec->mSize = ftype->mBase->mSize;
decResult = vdec;
InterInstruction* vins = new InterInstruction();
vins->mCode = IC_CONSTANT;
vins->mDst.mType = IT_POINTER;
vins->mDst.mTemp = proc->AddTemporary(IT_POINTER);
vins->mConst.mMemory = IM_LOCAL;
vins->mConst.mVarIndex = nindex;
vins->mConst.mOperandSize = ftype->mBase->mSize;
block->Append(vins);
InterInstruction* ains = new InterInstruction();
ains->mCode = IC_CONSTANT;
ains->mDst.mType = IT_POINTER;
ains->mDst.mTemp = proc->AddTemporary(IT_POINTER);
ains->mConst.mVarIndex = 0;
ains->mConst.mIntConst = 0;
ains->mConst.mOperandSize = 2;
if (ftype->mFlags & DTF_FASTCALL)
ains->mConst.mMemory = IM_FPARAM;
else
ains->mConst.mMemory = IM_FRAME;
block->Append(ains);
InterInstruction* wins = new InterInstruction();
wins->mCode = IC_STORE;
wins->mSrc[1].mMemory = IM_INDIRECT;
wins->mSrc[0].mType = IT_POINTER;
wins->mSrc[0].mTemp = vins->mDst.mTemp;
wins->mSrc[1].mType = IT_POINTER;
wins->mSrc[1].mTemp = ains->mDst.mTemp;
wins->mSrc[1].mOperandSize = 2;
block->Append(wins);
atotal = 2;
decResult = vdec;
}
if (exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION) if (exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION)
proc->AddCalledFunction(proc->mModule->mProcedures[exp->mLeft->mDecValue->mVarIndex]); proc->AddCalledFunction(proc->mModule->mProcedures[exp->mLeft->mDecValue->mVarIndex]);
else else
@ -2058,7 +2109,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
cins->mCode = IC_CALL; cins->mCode = IC_CALL;
cins->mSrc[0].mType = IT_POINTER; cins->mSrc[0].mType = IT_POINTER;
cins->mSrc[0].mTemp = vl.mTemp; cins->mSrc[0].mTemp = vl.mTemp;
if (ftype->mBase->mType != DT_TYPE_VOID) if (ftype->mBase->mType != DT_TYPE_VOID && ftype->mBase->mType != DT_TYPE_STRUCT)
{ {
cins->mDst.mType = InterTypeOf(ftype->mBase); cins->mDst.mType = InterTypeOf(ftype->mBase);
cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType);
@ -2081,6 +2132,19 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
block->Append(xins); block->Append(xins);
} }
if (decResult)
{
InterInstruction* vins = new InterInstruction();
vins->mCode = IC_CONSTANT;
vins->mDst.mType = IT_POINTER;
vins->mDst.mTemp = proc->AddTemporary(IT_POINTER);
vins->mConst.mMemory = IM_LOCAL;
vins->mConst.mVarIndex = decResult->mVarIndex;
block->Append(vins);
return ExValue(ftype->mBase, vins->mDst.mTemp, 1);
}
else
return ExValue(ftype->mBase, cins->mDst.mTemp); return ExValue(ftype->mBase, cins->mDst.mTemp);
} }
@ -2168,6 +2232,54 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (exp->mLeft) if (exp->mLeft)
{ {
vr = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper);
if (procType->mBase->mType == DT_TYPE_STRUCT)
{
vr = Dereference(proc, block, vr, 1);
if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID)
mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Function has void return type");
else if (!procType->mBase->CanAssign(vr.mType))
mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type");
else if (vr.mReference != 1)
mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Non addressable object");
InterInstruction* ains = new InterInstruction();
ains->mCode = IC_CONSTANT;
ains->mDst.mType = IT_POINTER;
ains->mDst.mTemp = proc->AddTemporary(IT_POINTER);
ains->mConst.mVarIndex = 0;
ains->mConst.mIntConst = 0;
ains->mConst.mOperandSize = 2;
if (procType->mFlags & DTF_FASTCALL)
ains->mConst.mMemory = IM_FPARAM;
else
ains->mConst.mMemory = IM_PARAM;
block->Append(ains);
InterInstruction* rins = new InterInstruction();
rins->mCode = IC_LOAD;
rins->mSrc[0].mMemory = IM_INDIRECT;
rins->mSrc[0].mType = IT_POINTER;
rins->mSrc[0].mTemp = ains->mDst.mTemp;
rins->mDst.mType = IT_POINTER;
rins->mDst.mTemp = proc->AddTemporary(IT_POINTER);
block->Append(rins);
InterInstruction* cins = new InterInstruction();
cins->mCode = IC_COPY;
cins->mConst.mMemory = IM_INDIRECT;
cins->mSrc[0].mType = IT_POINTER;
cins->mSrc[0].mTemp = vr.mTemp;
cins->mSrc[1].mType = IT_POINTER;
cins->mSrc[1].mTemp = rins->mDst.mTemp;
cins->mConst.mOperandSize = vr.mType->mSize;
block->Append(cins);
ins->mCode = IC_RETURN;
}
else
{
vr = Dereference(proc, block, vr); vr = Dereference(proc, block, vr);
if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID) if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID)
@ -2201,6 +2313,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
else else
ins->mCode = IC_RETURN_VALUE; ins->mCode = IC_RETURN_VALUE;
} }
}
else else
{ {
if (procType->mBase && procType->mBase->mType != DT_TYPE_VOID) if (procType->mBase && procType->mBase->mType != DT_TYPE_VOID)

View File

@ -729,6 +729,17 @@ Declaration* Parser::ParseDeclaration(bool variable)
ndec = ReverseDeclaration(ndec, bdec); ndec = ReverseDeclaration(ndec, bdec);
// Make room for return value pointer on struct return
if (ndec->mBase->mType == DT_TYPE_FUNCTION && ndec->mBase->mBase->mType == DT_TYPE_STRUCT)
{
Declaration* pdec = ndec->mBase->mParams;
while (pdec)
{
pdec->mVarIndex += 2;
pdec = pdec->mNext;
}
}
if (definingType) if (definingType)
{ {
if (ndec->mIdent) if (ndec->mIdent)