Add heap support to constexpr

This commit is contained in:
drmortalwombat 2023-09-09 12:09:05 +02:00
parent 4dd3cd967a
commit bd37877c8c
3 changed files with 107 additions and 2 deletions

View File

@ -61,6 +61,18 @@ ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec)
mData = new ValueItem[mDataSize]; mData = new ValueItem[mDataSize];
} }
ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec, int size)
: mLocation(location),
mDecType(dec),
mBaseValue(nullptr), mOffset(0),
mDataSize(size)
{
if (mDataSize <= 4)
mData = mShortData;
else
mData = new ValueItem[mDataSize];
}
ConstexprInterpreter::Value::Value(const Value& value) ConstexprInterpreter::Value::Value(const Value& value)
: mLocation(value.mLocation), : mLocation(value.mLocation),
mDecType(value.mDecType), mDecType(value.mDecType),
@ -403,6 +415,9 @@ void ConstexprInterpreter::Value::Assign(const Value& v)
case DT_TYPE_ARRAY: case DT_TYPE_ARRAY:
memcpy(GetAddr(), v.GetAddr(), mDecType->mSize); memcpy(GetAddr(), v.GetAddr(), mDecType->mSize);
break; break;
case DT_TYPE_POINTER:
PutPtr(v.GetPtr());
break;
} }
} }
@ -489,7 +504,7 @@ Expression* ConstexprInterpreter::Value::ToExpression(LinkerSection* dataSection
ConstexprInterpreter::ConstexprInterpreter(const Location & location, Errors* err, LinkerSection* dataSection) ConstexprInterpreter::ConstexprInterpreter(const Location & location, Errors* err, LinkerSection* dataSection)
: mLocation(location), mErrors(err), mDataSection(dataSection), mParams(Value()), mLocals(Value()) : mLocation(location), mErrors(err), mDataSection(dataSection), mParams(Value()), mLocals(Value()), mHeap(nullptr)
{ {
} }
@ -499,6 +514,25 @@ ConstexprInterpreter::~ConstexprInterpreter(void)
} }
ConstexprInterpreter::Value* ConstexprInterpreter::NewValue(Expression* exp, Declaration* type, int size)
{
Value* v = new Value(exp->mLocation, type, size);
mHeap->Push(v);
return v;
}
void ConstexprInterpreter::DeleteValue(Value* v)
{
int i = mHeap->IndexOf(v);
if (i >= 0)
{
delete v;
mHeap->Remove(i);
}
else
mErrors->Error(v->mLocation, EERR_DOUBLE_FREE, "Freeing not allocated memory");
}
Expression* ConstexprInterpreter::EvalCall(Expression* exp) Expression* ConstexprInterpreter::EvalCall(Expression* exp)
{ {
mProcType = exp->mLeft->mDecType; mProcType = exp->mLeft->mDecType;
@ -542,8 +576,14 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp)
return exp; return exp;
} }
mHeap = new ExpandingArray<Value*>();
Execute(exp->mLeft->mDecValue->mValue); Execute(exp->mLeft->mDecValue->mValue);
if (mHeap->Size() > 0)
mErrors->Error(exp->mLocation, EERR_UNBALANCED_HEAP_USE, "Unbalanced heap use in constexpr");
delete mHeap;
return mResult.ToExpression(mDataSection); return mResult.ToExpression(mDataSection);
} }
@ -798,6 +838,12 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalUnary(Expression* exp, con
break; break;
case TK_MUL: case TK_MUL:
return vl.GetPtr(); return vl.GetPtr();
case TK_NEW:
v.PutPtr(Value(NewValue(exp, exp->mDecType->mBase, vl.GetInt())));
break;
case TK_DELETE:
DeleteValue(vl.GetPtr().mBaseValue);
break;
default: default:
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]);
} }
@ -825,6 +871,8 @@ ConstexprInterpreter::Value ConstexprInterpreter::REval(Expression* exp)
ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, ConstexprInterpreter* caller) ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, ConstexprInterpreter* caller)
{ {
mHeap = caller->mHeap;
mProcType = exp->mLeft->mDecType; mProcType = exp->mLeft->mDecType;
Expression* pex = exp->mRight; Expression* pex = exp->mRight;
@ -882,7 +930,10 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons
mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname); mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname);
} }
else else
{
Execute(exp->mLeft->mDecValue->mValue); Execute(exp->mLeft->mDecValue->mValue);
UnwindDestructStack(0);
}
return mResult; return mResult;
} }
@ -1063,7 +1114,14 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp)
switch (exp->mType) switch (exp->mType)
{ {
case EX_SCOPE: case EX_SCOPE:
return Execute(exp->mLeft); {
int ds = mDestructStack.Size();
Flow f = Execute(exp->mLeft);
UnwindDestructStack(ds);
return f;
}
case EX_RETURN: case EX_RETURN:
mResult = EvalCoerce(exp, Eval(exp->mLeft), mProcType->mBase); mResult = EvalCoerce(exp, Eval(exp->mLeft), mProcType->mBase);
return FLOW_RETURN; return FLOW_RETURN;
@ -1141,34 +1199,53 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp)
} }
case EX_WHILE: case EX_WHILE:
{
int ds = mDestructStack.Size();
while (REval(exp->mLeft).GetInt()) while (REval(exp->mLeft).GetInt())
{ {
int ls = mDestructStack.Size();
Flow f = Execute(exp->mRight); Flow f = Execute(exp->mRight);
UnwindDestructStack(ls);
if (f == FLOW_RETURN) if (f == FLOW_RETURN)
return FLOW_RETURN; return FLOW_RETURN;
else if (f == FLOW_BREAK) else if (f == FLOW_BREAK)
break; break;
} }
UnwindDestructStack(ds);
return FLOW_NEXT; return FLOW_NEXT;
}
case EX_DO: case EX_DO:
{
int ds = mDestructStack.Size();
do { do {
int ls = mDestructStack.Size();
Flow f = Execute(exp->mRight); Flow f = Execute(exp->mRight);
UnwindDestructStack(ls);
if (f == FLOW_RETURN) if (f == FLOW_RETURN)
return FLOW_RETURN; return FLOW_RETURN;
else if (f == FLOW_BREAK) else if (f == FLOW_BREAK)
break; break;
} while (REval(exp->mLeft).GetInt()); } while (REval(exp->mLeft).GetInt());
UnwindDestructStack(ds);
return FLOW_NEXT; return FLOW_NEXT;
}
case EX_FOR: case EX_FOR:
{
int ds = mDestructStack.Size();
if (exp->mLeft->mRight) if (exp->mLeft->mRight)
Eval(exp->mLeft->mRight); Eval(exp->mLeft->mRight);
while (!exp->mLeft->mLeft->mLeft || REval(exp->mLeft->mLeft->mLeft).GetInt()) while (!exp->mLeft->mLeft->mLeft || REval(exp->mLeft->mLeft->mLeft).GetInt())
{ {
int ls = mDestructStack.Size();
Flow f = Execute(exp->mRight); Flow f = Execute(exp->mRight);
UnwindDestructStack(ls);
if (f == FLOW_RETURN) if (f == FLOW_RETURN)
return FLOW_RETURN; return FLOW_RETURN;
else if (f == FLOW_BREAK) else if (f == FLOW_BREAK)
@ -1177,8 +1254,19 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp)
if (exp->mLeft->mLeft->mRight) if (exp->mLeft->mLeft->mRight)
Eval(exp->mLeft->mLeft->mRight); Eval(exp->mLeft->mLeft->mRight);
} }
UnwindDestructStack(ds);
return FLOW_NEXT; return FLOW_NEXT;
}
case EX_CONSTRUCT:
if (exp->mLeft->mLeft)
Eval(exp->mLeft->mLeft);
if (exp->mLeft->mRight)
mDestructStack.Push(exp->mLeft->mRight);
return Execute(exp->mRight);
case EX_VOID: case EX_VOID:
return FLOW_NEXT; return FLOW_NEXT;
@ -1189,6 +1277,12 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp)
} }
} }
void ConstexprInterpreter::UnwindDestructStack(int level)
{
while (mDestructStack.Size() > level)
Eval(mDestructStack.Pop());
}
ConstexprInterpreter::ValueItem::ValueItem(void) ConstexprInterpreter::ValueItem::ValueItem(void)
: mByte(0), mBaseValue(nullptr) : mByte(0), mBaseValue(nullptr)
{ {

View File

@ -26,6 +26,7 @@ protected:
Value(const Location& location); Value(const Location& location);
Value(Expression * exp); Value(Expression * exp);
Value(const Location& location, Declaration * dec); Value(const Location& location, Declaration * dec);
Value(const Location& location, Declaration* dec, int count);
Value(const Value& value); Value(const Value& value);
Value(Value&& value); Value(Value&& value);
Value(Value * value, Declaration * type, int offset); Value(Value * value, Declaration * type, int offset);
@ -70,6 +71,9 @@ protected:
Declaration* GetConst(int offset, Declaration* type, LinkerSection* dataSection) const; Declaration* GetConst(int offset, Declaration* type, LinkerSection* dataSection) const;
}; };
Value * NewValue(Expression* exp, Declaration* type, int size);
void DeleteValue(Value* v);
Value EvalCall(Expression* exp, ConstexprInterpreter* caller); Value EvalCall(Expression* exp, ConstexprInterpreter* caller);
Value EvalBinary(Expression* exp, const Value& vl, const Value& vr); Value EvalBinary(Expression* exp, const Value& vl, const Value& vr);
Value EvalUnary(Expression* exp, const Value& vl); Value EvalUnary(Expression* exp, const Value& vl);
@ -89,11 +93,16 @@ protected:
}; };
Flow Execute(Expression* exp); Flow Execute(Expression* exp);
void UnwindDestructStack(int level);
Declaration* mProcType; Declaration* mProcType;
Location mLocation; Location mLocation;
LinkerSection* mDataSection; LinkerSection* mDataSection;
GrowingArray<Value> mParams, mLocals; GrowingArray<Value> mParams, mLocals;
ExpandingArray<Expression*> mDestructStack;
ExpandingArray<Value *> * mHeap;
Errors * mErrors; Errors * mErrors;
Value mResult; Value mResult;
}; };

View File

@ -85,6 +85,8 @@ enum ErrorID
EERR_FUNCTION_TEMPLATE, EERR_FUNCTION_TEMPLATE,
EERR_INVALID_CONSTEXPR, EERR_INVALID_CONSTEXPR,
EERR_DOUBLE_FREE,
EERR_UNBALANCED_HEAP_USE,
ERRR_STACK_OVERFLOW, ERRR_STACK_OVERFLOW,
ERRR_INVALID_NUMBER, ERRR_INVALID_NUMBER,