diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index a0de135..a5692e6 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -621,6 +621,83 @@ Expression* ConstexprInterpreter::EvalConstructor(Expression* exp) 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(); + + 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) { mProcType = exp->mLeft->mDecType; @@ -638,57 +715,17 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp) while (pex && pex->mType == EX_LIST) { - if (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 + if (!AddParam(pos, pex->mLeft, dec)) return exp; pex = pex->mRight; if (dec) dec = dec->mNext; } - if (pex) - { - 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 + if (pex) + { + if (!AddParam(pos, pex, dec)) return exp; } diff --git a/oscar64/Constexpr.h b/oscar64/Constexpr.h index 7986427..7cfc825 100644 --- a/oscar64/Constexpr.h +++ b/oscar64/Constexpr.h @@ -8,9 +8,13 @@ public: ConstexprInterpreter(const Location & loc, Errors * err, LinkerSection * dataSection); ~ConstexprInterpreter(void); - Expression* EvalCall(Expression* exp); Expression* EvalConstructor(Expression* exp); + Expression* EvalCall(Expression* exp); + Expression* EvalTempConstructor(Expression* exp); protected: + + bool AddParam(int& pos, Expression* pex, Declaration* dec); + struct Value; struct ValueItem diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 24a399a..424e2ba 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -899,7 +899,15 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio { ConstexprInterpreter cinter(mLocation, errors, dataSection); 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; } diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 84e7f75..7b7e2d8 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1552,6 +1552,7 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) } Expression* texp = ParseInitExpression(dtype->mBase); + texp = texp->ConstantFold(mErrors, mDataSection); for (int i = 0; i < nrep; i++) { Declaration* cdec = CopyConstantInitializer(index, dtype->mBase, texp);