constexpr constructor

This commit is contained in:
drmortalwombat 2023-10-14 18:50:27 +02:00
parent d160b2ae65
commit 4e76b34f53
4 changed files with 96 additions and 46 deletions

View File

@ -621,6 +621,83 @@ Expression* ConstexprInterpreter::EvalConstructor(Expression* exp)
return mResult.ToExpression(mDataSection); return mResult.ToExpression(mDataSection);
} }
Expression* ConstexprInterpreter::EvalTempConstructor(Expression* exp)
{
Expression* cexp = exp->mLeft->mLeft;
mProcType = cexp->mLeft->mDecType;
Expression* pex = cexp->mRight;
Declaration* dec = cexp->mLeft->mDecType->mParams;
Value othis = Value(exp->mLocation, exp->mRight->mDecType);
mParams[0] = Value(exp->mLocation, dec->mBase);
mParams[0].PutPtr(Value(&othis));
int pos = 2;
if (pex->mType == EX_LIST)
pex = pex->mRight;
else
pex = nullptr;
dec = dec->mNext;
while (pex && pex->mType == EX_LIST)
{
if (!AddParam(pos, pex->mLeft, dec))
return exp;
pex = pex->mRight;
if (dec)
dec = dec->mNext;
}
if (pex)
{
if (!AddParam(pos, pex, dec))
return exp;
}
mHeap = new ExpandingArray<Value*>();
Execute(cexp->mLeft->mDecValue->mValue);
if (mHeap->Size() > 0)
mErrors->Error(exp->mLocation, EERR_UNBALANCED_HEAP_USE, "Unbalanced heap use in constexpr");
delete mHeap;
return othis.ToExpression(mDataSection);
}
bool ConstexprInterpreter::AddParam(int& pos, Expression* pex, Declaration* dec)
{
if (dec)
pos = dec->mVarIndex;
if (pex->mType == EX_CONSTANT)
{
if (pex->mDecType->mType == DT_TYPE_ARRAY)
{
Value* tmp = new Value(pex);
mTemps.Push(tmp);
mParams[pos] = Value(pex->mLocation, pex->mDecType->BuildArrayPointer());
mParams[pos].PutPtr(Value(tmp));
}
else
mParams[pos] = Value(pex);
}
else if (pex->mType == EX_VARIABLE && (pex->mDecValue->mFlags & DTF_CONST))
{
mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase);
if (pex->mDecValue->mSize > 0)
mParams[pos].PutConst(0, pex->mDecValue->mValue->mDecValue);
}
else
return false;
return true;
}
Expression* ConstexprInterpreter::EvalCall(Expression* exp) Expression* ConstexprInterpreter::EvalCall(Expression* exp)
{ {
mProcType = exp->mLeft->mDecType; mProcType = exp->mLeft->mDecType;
@ -638,57 +715,17 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp)
while (pex && pex->mType == EX_LIST) while (pex && pex->mType == EX_LIST)
{ {
if (dec) if (!AddParam(pos, pex->mLeft, dec))
pos = dec->mVarIndex;
if (pex->mLeft->mType == EX_CONSTANT)
{
if (pex->mLeft->mDecType->mType == DT_TYPE_ARRAY)
{
Value * tmp = new Value(pex->mLeft);
mTemps.Push(tmp);
mParams[pos] = Value(pex->mLeft->mLocation, pex->mLeft->mDecType->BuildArrayPointer());
mParams[pos].PutPtr(Value(tmp));
}
else
mParams[pos] = Value(pex->mLeft);
}
else if (pex->mLeft->mType == EX_VARIABLE && (pex->mLeft->mDecValue->mFlags & DTF_CONST))
{
mParams[pos] = Value(pex->mLeft->mLocation, pex->mLeft->mDecValue->mBase);
mParams[pos].PutConst(0, pex->mLeft->mDecValue->mValue->mDecValue);
}
else
return exp; return exp;
pex = pex->mRight; pex = pex->mRight;
if (dec) if (dec)
dec = dec->mNext; dec = dec->mNext;
} }
if (pex) if (pex)
{ {
if (dec) if (!AddParam(pos, pex, dec))
pos = dec->mVarIndex;
if (pex->mType == EX_CONSTANT)
{
if (pex->mDecType->mType == DT_TYPE_ARRAY)
{
Value* tmp = new Value(pex);
mTemps.Push(tmp);
mParams[pos] = Value(pex->mLocation, pex->mDecType->BuildArrayPointer());
mParams[pos].PutPtr(Value(tmp));
}
else
mParams[pos] = Value(pex);
}
else if (pex->mType == EX_VARIABLE && (pex->mDecValue->mFlags & DTF_CONST))
{
mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase);
if (pex->mDecValue->mSize > 0)
mParams[pos].PutConst(0, pex->mDecValue->mValue->mDecValue);
}
else
return exp; return exp;
} }

View File

@ -8,9 +8,13 @@ public:
ConstexprInterpreter(const Location & loc, Errors * err, LinkerSection * dataSection); ConstexprInterpreter(const Location & loc, Errors * err, LinkerSection * dataSection);
~ConstexprInterpreter(void); ~ConstexprInterpreter(void);
Expression* EvalCall(Expression* exp);
Expression* EvalConstructor(Expression* exp); Expression* EvalConstructor(Expression* exp);
Expression* EvalCall(Expression* exp);
Expression* EvalTempConstructor(Expression* exp);
protected: protected:
bool AddParam(int& pos, Expression* pex, Declaration* dec);
struct Value; struct Value;
struct ValueItem struct ValueItem

View File

@ -900,6 +900,14 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
ConstexprInterpreter cinter(mLocation, errors, dataSection); ConstexprInterpreter cinter(mLocation, errors, dataSection);
return cinter.EvalCall(this); return cinter.EvalCall(this);
} }
else if (mType == EX_CONSTRUCT && mLeft->mType == EX_LIST && !mLeft->mRight && mLeft->mLeft->mType == EX_CALL &&
mLeft->mLeft->mLeft->mType == EX_CONSTANT && (mLeft->mLeft->mLeft->mDecValue->mFlags & DTF_CONSTEXPR) &&
(mRight->mDecValue->mFlags & DTF_TEMPORARY) &&
dataSection)
{
ConstexprInterpreter cinter(mLocation, errors, dataSection);
return cinter.EvalTempConstructor(this);
}
return this; return this;
} }

View File

@ -1552,6 +1552,7 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
} }
Expression* texp = ParseInitExpression(dtype->mBase); Expression* texp = ParseInitExpression(dtype->mBase);
texp = texp->ConstantFold(mErrors, mDataSection);
for (int i = 0; i < nrep; i++) for (int i = 0; i < nrep; i++)
{ {
Declaration* cdec = CopyConstantInitializer(index, dtype->mBase, texp); Declaration* cdec = CopyConstantInitializer(index, dtype->mBase, texp);