From ab273181f5b3538d36c6f57993ed8eba4244802c Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 8 Sep 2023 20:12:38 +0200 Subject: [PATCH] First shot implementing constexpr --- include/math.h | 3 + oscar64/Constexpr.cpp | 1133 +++++++++++++++++++++++++++++++ oscar64/Constexpr.h | 89 +++ oscar64/Declaration.cpp | 57 +- oscar64/Declaration.h | 10 +- oscar64/Errors.h | 2 + oscar64/InterCode.cpp | 4 +- oscar64/InterCodeGenerator.cpp | 15 +- oscar64/Parser.cpp | 128 ++-- oscar64/Parser.h | 1 + oscar64/Scanner.cpp | 3 + oscar64/Scanner.h | 1 + oscar64/oscar64.vcxproj | 2 + oscar64/oscar64.vcxproj.filters | 6 + 14 files changed, 1388 insertions(+), 66 deletions(-) create mode 100644 oscar64/Constexpr.cpp create mode 100644 oscar64/Constexpr.h diff --git a/include/math.h b/include/math.h index 842d32d..4c58d7f 100644 --- a/include/math.h +++ b/include/math.h @@ -30,6 +30,9 @@ bool isfinite(float f); #pragma intrinsic(floor) #pragma intrinsic(ceil) +#pragma intrinsic(sin) +#pragma intrinsic(cos) + #pragma compile("math.c") diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp new file mode 100644 index 0000000..91b90fe --- /dev/null +++ b/oscar64/Constexpr.cpp @@ -0,0 +1,1133 @@ +#include "Constexpr.h" +#include + +ConstexprInterpreter::Value::Value(void) + : mDecType(TheVoidTypeDeclaration), + mBaseValue(nullptr), mOffset(0), + mData(mShortData), mDataSize(0) +{ +} + +ConstexprInterpreter::Value::Value(const Location & location) + : mLocation(location), + mDecType(TheVoidTypeDeclaration), + mBaseValue(nullptr), mOffset(0), + mData(mShortData), mDataSize(0) +{ +} + +ConstexprInterpreter::Value::Value(Expression* exp) + : mLocation(exp->mLocation), + mDecType(exp->mDecType), + mBaseValue(nullptr), mOffset(0), + mDataSize(exp->mDecType->mSize) +{ + assert(exp->mType == EX_CONSTANT); + + if (mDataSize <= 4) + mData = mShortData; + else + mData = new ValueItem[mDataSize]; + + PutConst(0, exp->mDecValue); +} + +void ConstexprInterpreter::Value::PutConst(int offset, Declaration* dec) +{ + switch (dec->mType) + { + case DT_CONST_INTEGER: + PutIntAt(dec->mInteger, offset, dec->mBase); + break; + case DT_CONST_FLOAT: + PutFloatAt(float(dec->mNumber), offset, dec->mBase); + break; + case DT_CONST_STRUCT: + for (Declaration* pdec = dec->mParams; pdec; pdec = pdec->mNext) + PutConst(pdec->mOffset, pdec); + break; + } +} + +ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec) + : mLocation(location), + mDecType(dec), + mBaseValue(nullptr), mOffset(0), + mDataSize(dec->mSize) +{ + if (mDataSize <= 4) + mData = mShortData; + else + mData = new ValueItem[mDataSize]; +} + +ConstexprInterpreter::Value::Value(const Value& value) + : mLocation(value.mLocation), + mDecType(value.mDecType), + mBaseValue(value.mBaseValue), mOffset(value.mOffset), + mDataSize(value.mDataSize) + +{ + if (mDataSize <= 4) + mData = mShortData; + else + mData = new ValueItem[mDataSize]; + + for (int i = 0; i < mDataSize; i++) + mData[i] = value.mData[i]; +} + +ConstexprInterpreter::Value::Value(Value&& value) + : mLocation(value.mLocation), + mDecType(value.mDecType), + mBaseValue(value.mBaseValue), mOffset(value.mOffset), + mDataSize(value.mDataSize) +{ + if (mDataSize <= 4) + { + mData = mShortData; + for (int i = 0; i < mDataSize; i++) + mData[i] = value.mData[i]; + } + else + { + mData = value.mData; + value.mData = value.mShortData; + } +} + +ConstexprInterpreter::Value::Value(Value* value) + : mLocation(value->mLocation), + mDecType(value->mDecType), + mBaseValue(value), mOffset(0), + mDataSize(0), mData(mShortData) +{ +} + +ConstexprInterpreter::Value::Value(Value* value, Declaration* type, int offset) + : mLocation(value->mLocation), + mDecType(type), + mBaseValue(value), mOffset(offset), + mDataSize(0), mData(mShortData) +{ +} + +ConstexprInterpreter::Value::Value(const Location& location, const uint8* data, Declaration* type) + : mLocation(location), + mDecType(type), + mBaseValue(nullptr), mOffset(0), + mDataSize(type->mSize) +{ + if (mDataSize <= 4) + mData = mShortData; + else + mData = new ValueItem[mDataSize]; + + for (int i = 0; i < mDataSize; i++) + mData[i].mByte = data[i]; +} + +ConstexprInterpreter::Value::Value(const Location& location, const ValueItem* data, Declaration* type) + : mLocation(location), + mDecType(type), + mBaseValue(nullptr), mOffset(0), + mDataSize(type->mSize) +{ + if (mDataSize <= 4) + mData = mShortData; + else + mData = new ValueItem[mDataSize]; + + for (int i = 0; i < mDataSize; i++) + mData[i] = data[i]; +} + + +ConstexprInterpreter::Value::~Value(void) +{ + if (mData != mShortData) + delete[] mData; +} + + + +ConstexprInterpreter::Value& ConstexprInterpreter::Value::operator=(const Value& v) +{ + if (mData != mShortData) + { + delete[] mData; + mData = mShortData; + } + + mLocation = v.mLocation; + mDecType = v.mDecType; + mBaseValue = v.mBaseValue; + mDataSize = v.mDataSize; + mOffset = v.mOffset; + + if (mDataSize <= 4) + mData = mShortData; + else + mData = new ValueItem[mDataSize]; + + for (int i = 0; i < mDataSize; i++) + mData[i] = v.mData[i]; + + return *this; +} + +ConstexprInterpreter::Value& ConstexprInterpreter::Value::operator=(Value&& v) +{ + if (mData != mShortData) + { + delete[] mData; + mData = mShortData; + } + + mLocation = v.mLocation; + mDecType = v.mDecType; + mBaseValue = v.mBaseValue; + mDataSize = v.mDataSize; + mOffset = v.mOffset; + + if (mDataSize <= 4) + { + mData = mShortData; + for (int i = 0; i < mDataSize; i++) + mData[i] = v.mData[i]; + } + else + { + mData = v.mData; + v.mData = v.mShortData; + } + + return *this; +} + + +ConstexprInterpreter::ValueItem* ConstexprInterpreter::Value::GetAddr(void) +{ + if (mBaseValue) + return mBaseValue->mData + mOffset; + else + return mData; +} + +const ConstexprInterpreter::ValueItem* ConstexprInterpreter::Value::GetAddr(void) const +{ + if (mBaseValue) + return mBaseValue->mData + mOffset; + else + return mData; +} + +int64 ConstexprInterpreter::Value::GetInt(void) const +{ + return GetIntAt(0, mDecType); +} + +double ConstexprInterpreter::Value::GetFloat(void) const +{ + return GetFloatAt(0, mDecType); +} + +ConstexprInterpreter::Value ConstexprInterpreter::Value::GetPtr(void) const +{ + return GetPtrAt(0, mDecType->mBase); +} + +void ConstexprInterpreter::Value::PutInt(int64 v) +{ + PutIntAt(v, 0, mDecType); +} + +void ConstexprInterpreter::Value::PutFloat(double v) +{ + PutFloatAt(v, 0, mDecType); +} + +void ConstexprInterpreter::Value::PutPtr(const Value& v) +{ + PutPtrAt(v, 0, mDecType); +} + + +int64 ConstexprInterpreter::Value::GetIntAt(int at, Declaration* type) const +{ + if (type->mType == DT_TYPE_FLOAT) + { + return int64(GetFloatAt(at, type)); + } + else + { + const ValueItem* dp = GetAddr() + at; + + if (type->mFlags & DTF_SIGNED) + { + switch (type->mSize) + { + case 1: + return int8(dp[0].mByte); + case 2: + return int16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8)); + case 4: + return int32(dp[0].mByte | ((uint32)(dp[1].mByte) << 8) | ((uint32)(dp[2].mByte) << 16) | ((uint32)(dp[3].mByte) << 24)); + } + } + else + { + switch (type->mSize) + { + case 1: + return uint8(dp[0].mByte); + case 2: + return uint16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8)); + case 4: + return uint32(dp[0].mByte | ((uint32)(dp[1].mByte) << 8) | ((uint32)(dp[2].mByte) << 16) | ((uint32)(dp[3].mByte) << 24)); + } + } + } + + return 0; +} + +double ConstexprInterpreter::Value::GetFloatAt(int at, Declaration* type) const +{ + if (type->mType == DT_TYPE_FLOAT) + { + const ValueItem* dp = GetAddr() + at; + + union + { + float f; + uint32 i; + } u; + + u.i = uint32(dp[0].mByte | ((uint32)(dp[1].mByte) << 8) | ((uint32)(dp[2].mByte) << 16) | ((uint32)(dp[3].mByte) << 24)); + return u.f; + } + else + { + int64 iv = GetIntAt(at, type); + return double(iv); + } + +} + +ConstexprInterpreter::Value ConstexprInterpreter::Value::GetPtrAt(int at, Declaration* type) const +{ + const ValueItem* dp = GetAddr() + at; + + return Value(dp->mBaseValue, type, uint16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8))); +} + +void ConstexprInterpreter::Value::PutIntAt(int64 v, int at, Declaration* type) +{ + if (type->mType == DT_TYPE_FLOAT) + { + PutFloatAt(float(v), at, type); + } + else + { + ValueItem* dp = GetAddr() + at; + + switch (type->mSize) + { + case 4: + dp[3].mByte = uint8((v >> 24) & 0xff); + dp[2].mByte = uint8((v >> 16) & 0xff); + case 2: + dp[1].mByte = uint8((v >> 8) & 0xff); + case 1: + dp[0].mByte = uint8(v & 0xff); + } + } +} + +void ConstexprInterpreter::Value::PutFloatAt(double v, int at, Declaration* type) +{ + if (type->mType == DT_TYPE_FLOAT) + { + ValueItem* dp = GetAddr() + at; + + union + { + float f; + uint32 i; + } u; + + u.f = float(v); + + dp[3].mByte = uint8((u.i >> 24) & 0xff); + dp[2].mByte = uint8((u.i >> 16) & 0xff); + dp[1].mByte = uint8((u.i >> 8) & 0xff); + dp[0].mByte = uint8(u.i & 0xff); + } + else + { + PutIntAt(int64(v), at, type); + } +} + +void ConstexprInterpreter::Value::PutPtrAt(const Value& v, int at, Declaration* type) +{ + ValueItem* dp = GetAddr() + at; + + dp[0].mBaseValue = v.mBaseValue; + dp[1].mByte = uint8((v.mOffset >> 8) & 0xff); + dp[0].mByte = uint8(v.mOffset & 0xff); +} + +ConstexprInterpreter::Value ConstexprInterpreter::Value::ToRValue(void) const +{ + if (mBaseValue) + return Value(mLocation, GetAddr(), mDecType); + else + return *this; +} + +void ConstexprInterpreter::Value::Assign(const Value& v) +{ + switch (mDecType->mType) + { + case DT_TYPE_INTEGER: + case DT_TYPE_BOOL: + PutInt(v.GetInt()); + break; + case DT_TYPE_FLOAT: + PutFloat(v.GetFloat()); + break; + case DT_TYPE_STRUCT: + case DT_TYPE_UNION: + case DT_TYPE_ARRAY: + memcpy(GetAddr(), v.GetAddr(), mDecType->mSize); + break; + } +} + +Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type, LinkerSection* dataSection) const +{ + Declaration* dec = nullptr; + + switch (type->mType) + { + case DT_TYPE_INTEGER: + case DT_TYPE_BOOL: + dec = new Declaration(mLocation, DT_CONST_INTEGER); + dec->mBase = type; + dec->mFlags = type->mFlags & DTF_SIGNED; + dec->mSize = type->mSize; + dec->mInteger = GetIntAt(offset, type); + break; + case DT_TYPE_FLOAT: + dec = new Declaration(mLocation, DT_CONST_FLOAT); + dec->mBase = type; + dec->mSize = type->mSize; + dec->mNumber = GetFloatAt(offset, type); + break; + case DT_TYPE_STRUCT: + { + dec = new Declaration(mLocation, DT_CONST_STRUCT); + dec->mBase = type; + dec->mSize = type->mSize; + dec->mSection = dataSection; + dec->mOffset = offset; + Declaration* ldec = nullptr; + for (Declaration* mdec = type->mParams; mdec; mdec = mdec->mNext) + { + Declaration * cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection); + cdec->mOffset = mdec->mOffset; + + if (ldec) + ldec->mNext = cdec; + else + dec->mParams = cdec; + + ldec = cdec; + + } + break; + } + case DT_TYPE_ARRAY: + { + dec = new Declaration(mLocation, DT_CONST_STRUCT); + dec->mBase = type; + dec->mSize = type->mSize; + dec->mSection = dataSection; + dec->mOffset = offset; + Declaration* ldec = nullptr; + for (int i=0; imSize; i += type->mBase->mSize) + { + Declaration* cdec = GetConst(offset + i, type->mBase, dataSection); + cdec->mOffset = i; + + if (ldec) + ldec->mNext = cdec; + else + dec->mParams = cdec; + + ldec = cdec; + } + break; + } + + } + + return dec; +} + +Expression* ConstexprInterpreter::Value::ToExpression(LinkerSection* dataSection) const +{ + Expression* exp = new Expression(mLocation, EX_CONSTANT); + + exp->mDecType = mDecType; + exp->mDecValue = GetConst(0, mDecType, dataSection); + + return exp; +} + + +ConstexprInterpreter::ConstexprInterpreter(const Location & location, Errors* err, LinkerSection* dataSection) + : mLocation(location), mErrors(err), mDataSection(dataSection), mParams(Value()), mLocals(Value()) +{ + +} + +ConstexprInterpreter::~ConstexprInterpreter(void) +{ + +} + +Expression* ConstexprInterpreter::EvalCall(Expression* exp) +{ + mProcType = exp->mLeft->mDecType; + + Expression* pex = exp->mRight; + Declaration* dec = exp->mLeft->mDecType->mParams; + + int pos = 0; + while (pex && pex->mType == EX_LIST) + { + if (dec) + pos = dec->mVarIndex; + + if (pex->mLeft->mType == EX_CONSTANT) + 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; + + pex = pex->mRight; + if (dec) + dec = dec->mNext; + } + if (pex) + { + if (dec) + pos = dec->mVarIndex; + + if (pex->mType == EX_CONSTANT) + mParams[pos] = Value(pex); + else if (pex->mType == EX_VARIABLE && (pex->mDecValue->mFlags & DTF_CONST)) + { + mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase); + mParams[pos].PutConst(0, pex->mDecValue->mValue->mDecValue); + } + else + return exp; + } + + Eval(exp->mLeft->mDecValue->mValue); + + return mResult.ToExpression(mDataSection); +} + +ConstexprInterpreter::Value ConstexprInterpreter::EvalBinary(Expression * exp, const Value& vl, const Value& vr) +{ + Value v(exp->mLocation, exp->mDecType); + + if (exp->mDecType->mType == DT_TYPE_FLOAT) + { + switch (exp->mToken) + { + case TK_ADD: + case TK_ASSIGN_ADD: + v.PutFloat(vl.GetFloat() + vr.GetFloat()); + break; + case TK_SUB: + case TK_ASSIGN_SUB: + v.PutFloat(vl.GetFloat() - vr.GetFloat()); + break; + case TK_MUL: + case TK_ASSIGN_MUL: + v.PutFloat(vl.GetFloat() * vr.GetFloat()); + break; + case TK_DIV: + case TK_ASSIGN_DIV: + if (vr.GetInt() == 0) + mErrors->Error(exp->mLocation, EERR_INVALID_VALUE, "Constant division by zero"); + else + v.PutFloat(vl.GetFloat() / vr.GetFloat()); + break; + default: + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); + } + } + else + { + switch (exp->mToken) + { + case TK_ADD: + case TK_ASSIGN_ADD: + v.PutInt(vl.GetInt() + vr.GetInt()); + break; + case TK_SUB: + case TK_ASSIGN_SUB: + v.PutInt(vl.GetInt() - vr.GetInt()); + break; + case TK_MUL: + case TK_ASSIGN_MUL: + v.PutInt(vl.GetInt() * vr.GetInt()); + break; + case TK_DIV: + case TK_ASSIGN_DIV: + if (vr.GetInt() == 0) + mErrors->Error(exp->mLocation, EERR_INVALID_VALUE, "Constant division by zero"); + else + v.PutInt(vl.GetInt() / vr.GetInt()); + break; + case TK_MOD: + case TK_ASSIGN_MOD: + if (vr.GetInt() == 0) + mErrors->Error(exp->mLocation, EERR_INVALID_VALUE, "Constant division by zero"); + else + v.PutInt(vl.GetInt() % vr.GetInt()); + break; + case TK_LEFT_SHIFT: + case TK_ASSIGN_SHL: + v.PutInt(vl.GetInt() << vr.GetInt()); + break; + case TK_RIGHT_SHIFT: + case TK_ASSIGN_SHR: + v.PutInt(vl.GetInt() >> vr.GetInt()); + break; + case TK_BINARY_AND: + case TK_ASSIGN_AND: + v.PutInt(vl.GetInt() & vr.GetInt()); + break; + case TK_BINARY_OR: + case TK_ASSIGN_OR: + v.PutInt(vl.GetInt() | vr.GetInt()); + break; + case TK_BINARY_XOR: + case TK_ASSIGN_XOR: + v.PutInt(vl.GetInt() ^ vr.GetInt()); + break; + default: + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); + } + } + + return v; +} + +ConstexprInterpreter::Value ConstexprInterpreter::EvalRelational(Expression* exp, const Value& vl, const Value& vr) +{ + Value v(exp->mLocation, TheBoolTypeDeclaration); + + bool check = false; + if (vl.mDecType->mType == DT_TYPE_FLOAT || vr.mDecType->mType == DT_TYPE_FLOAT) + { + switch (exp->mToken) + { + case TK_EQUAL: + check = vl.GetFloat() == vr.GetFloat(); + break; + case TK_NOT_EQUAL: + check = vl.GetFloat() != vr.GetFloat(); + break; + case TK_GREATER_THAN: + check = vl.GetFloat() > vr.GetFloat(); + break; + case TK_GREATER_EQUAL: + check = vl.GetFloat() >= vr.GetFloat(); + break; + case TK_LESS_THAN: + check = vl.GetFloat() < vr.GetFloat(); + break; + case TK_LESS_EQUAL: + check = vl.GetFloat() <= vr.GetFloat(); + break; + default: + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); + } + } + else if (vl.mDecType->mType == DT_TYPE_POINTER && vr.mDecType->mType == DT_TYPE_POINTER) + { + Value pl = vl.GetPtr(); + Value pr = vr.GetPtr(); + + if (pl.mBaseValue == pr.mBaseValue) + { + switch (exp->mToken) + { + case TK_EQUAL: + check = pl.mOffset == pr.mOffset; + break; + case TK_NOT_EQUAL: + check = pl.mOffset != pr.mOffset; + break; + case TK_GREATER_THAN: + check = pl.mOffset > pr.mOffset; + break; + case TK_GREATER_EQUAL: + check = pl.mOffset >= pr.mOffset; + break; + case TK_LESS_THAN: + check = pl.mOffset < pr.mOffset; + break; + case TK_LESS_EQUAL: + check = pl.mOffset <= pr.mOffset; + break; + default: + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); + } + } + else + { + switch (exp->mToken) + { + case TK_EQUAL: + check = false; + break; + case TK_NOT_EQUAL: + check = true; + break; + default: + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); + } + } + } + else + { + switch (exp->mToken) + { + case TK_EQUAL: + check = vl.GetInt() == vr.GetInt(); + break; + case TK_NOT_EQUAL: + check = vl.GetInt() != vr.GetInt(); + break; + case TK_GREATER_THAN: + check = vl.GetInt() > vr.GetInt(); + break; + case TK_GREATER_EQUAL: + check = vl.GetInt() >= vr.GetInt(); + break; + case TK_LESS_THAN: + check = vl.GetInt() < vr.GetInt(); + break; + case TK_LESS_EQUAL: + check = vl.GetInt() <= vr.GetInt(); + break; + default: + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); + } + } + + v.PutInt(check ? 1 : 0); + + return v; +} + +ConstexprInterpreter::Value ConstexprInterpreter::EvalUnary(Expression* exp, const Value& vl) +{ + Value v(exp->mLocation, exp->mDecType); + + if (exp->mDecType->mType == DT_TYPE_FLOAT) + { + switch (exp->mToken) + { + case TK_ADD: + v.PutFloat(vl.GetFloat()); + break; + case TK_SUB: + v.PutFloat(-vl.GetFloat()); + break; + case TK_INC: + v.PutFloat(vl.GetFloat() + 1); + break; + case TK_DEC: + v.PutFloat(vl.GetFloat() - 1); + break; + case TK_MUL: + return vl.GetPtr(); + default: + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); + } + } + else + { + switch (exp->mToken) + { + case TK_ADD: + v.PutInt(vl.GetInt()); + break; + case TK_SUB: + v.PutInt(-vl.GetInt()); + break; + case TK_BINARY_NOT: + v.PutInt(~vl.GetInt()); + break; + case TK_INC: + v.PutInt(vl.GetInt() + 1); + break; + case TK_DEC: + v.PutInt(vl.GetInt() - 1); + break; + case TK_BINARY_AND: + if (vl.mBaseValue) + v.PutPtr(vl); + else + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not an addressable value"); + break; + case TK_MUL: + return vl.GetPtr(); + default: + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); + } + } + + return v; +} + +ConstexprInterpreter::Value ConstexprInterpreter::EvalTypeCast(Expression* exp, const Value& vl, Declaration* type) +{ + Value v(exp->mLocation, type); + + if (type->mType == DT_TYPE_FLOAT) + v.PutFloat(vl.GetFloat()); + else if (type->IsIntegerType()) + v.PutInt(vl.GetInt()); + + return v; +} + +ConstexprInterpreter::Value ConstexprInterpreter::REval(Expression* exp) +{ + return Eval(exp).ToRValue(); +} + +ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, ConstexprInterpreter* caller) +{ + mProcType = exp->mLeft->mDecType; + + Expression* pex = exp->mRight; + Declaration* dec = exp->mLeft->mDecType->mParams; + + int pos = 0; + while (pex && pex->mType == EX_LIST) + { + if (dec) + pos = dec->mVarIndex; + + mParams[pos] = caller->REval(pex->mLeft); + pos += dec->mSize; + pex = pex->mRight; + if (dec) + dec = dec->mNext; + } + if (pex) + { + if (dec) + pos = dec->mVarIndex; + mParams[pos] = caller->REval(pex); + } + + if (exp->mLeft->mDecValue->mFlags & DTF_INTRINSIC) + { + const Ident* iname = exp->mLeft->mDecValue->mIdent; + + if (!strcmp(iname->mString, "fabs")) + { + mResult = Value(exp->mLocation, TheFloatTypeDeclaration); + mResult.PutFloat(fabs(mParams[0].GetFloat())); + } + else if (!strcmp(iname->mString, "floor")) + { + mResult = Value(exp->mLocation, TheFloatTypeDeclaration); + mResult.PutFloat(floor(mParams[0].GetFloat())); + } + else if (!strcmp(iname->mString, "ceil")) + { + mResult = Value(exp->mLocation, TheFloatTypeDeclaration); + mResult.PutFloat(ceil(mParams[0].GetFloat())); + } + else if (!strcmp(iname->mString, "sin")) + { + mResult = Value(exp->mLocation, TheFloatTypeDeclaration); + mResult.PutFloat(sin(mParams[0].GetFloat())); + } + else if (!strcmp(iname->mString, "cos")) + { + mResult = Value(exp->mLocation, TheFloatTypeDeclaration); + mResult.PutFloat(cos(mParams[0].GetFloat())); + } + else + mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname); + } + else + Eval(exp->mLeft->mDecValue->mValue); + + return mResult; +} + +ConstexprInterpreter::Value ConstexprInterpreter::EvalCoerce(Expression* exp, const Value& vl, Declaration* type) +{ + if (type->IsReference()) + return vl; + else + { + Value v = vl.ToRValue(); + while (v.mDecType->IsReference()) + v.mDecType = v.mDecType->mBase; + + if (type->mType == DT_TYPE_FLOAT && v.mDecType->IsIntegerType()) + { + Value vf(exp->mLocation, type); + vf.PutFloat(v.GetFloat()); + v = vf; + } + else if (v.mDecType->mType == DT_TYPE_FLOAT && type->IsIntegerType()) + { + Value vf(exp->mLocation, type); + vf.PutInt(v.GetInt()); + v = vf; + } + + return v; + } +} + +ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) +{ + switch (exp->mType) + { + case EX_SCOPE: + return Eval(exp->mLeft); + case EX_RETURN: + mResult = EvalCoerce(exp, Eval(exp->mLeft), mProcType->mBase); + return mResult; + case EX_CONSTANT: + return Value(exp); + case EX_VARIABLE: + if (exp->mDecValue->mType == DT_ARGUMENT) + return Value(&mParams[exp->mDecValue->mVarIndex]); + else if (exp->mDecValue->mType == DT_VARIABLE) + { + if (!(exp->mDecValue->mFlags & (DTF_STATIC | DTF_GLOBAL))) + { + if (!mLocals[exp->mDecValue->mVarIndex].mDataSize) + mLocals[exp->mDecValue->mVarIndex] = Value(exp->mDecValue->mLocation, exp->mDecValue->mBase); + return Value(&mLocals[exp->mDecValue->mVarIndex]); + } + } + break; + case EX_BINARY: + return EvalBinary(exp, REval(exp->mLeft), REval(exp->mRight)); + + case EX_RELATIONAL: + return EvalRelational(exp, REval(exp->mLeft), REval(exp->mRight)); + + case EX_PREFIX: + return EvalUnary(exp, Eval(exp->mLeft)); + + case EX_TYPECAST: + return EvalTypeCast(exp, REval(exp->mLeft), exp->mDecType); + + case EX_CALL: + { + ConstexprInterpreter cinter(exp->mLocation, mErrors, mDataSection); + return cinter.EvalCall(exp, this); + } + + case EX_LIST: + Eval(exp->mLeft); + return Eval(exp->mRight); + + case EX_CONDITIONAL: + { + Value v = REval(exp->mLeft); + if (v.GetInt()) + return Eval(exp->mRight->mLeft); + else + return Eval(exp->mRight->mRight); + } + + case EX_LOGICAL_AND: + { + Value v = REval(exp->mLeft); + if (!v.GetInt()) + return v; + else + return REval(exp->mRight); + } + + case EX_LOGICAL_OR: + { + Value v = REval(exp->mLeft); + if (v.GetInt()) + return v; + else + return REval(exp->mRight); + } + + case EX_LOGICAL_NOT: + { + Value v(exp->mLocation, TheBoolTypeDeclaration); + Value vr = REval(exp->mLeft); + if (v.GetInt()) + v.PutInt(0); + else + v.PutInt(1); + return v; + } + + case EX_SEQUENCE: + if (exp->mRight) + { + Eval(exp->mLeft); + return Eval(exp->mRight); + } + else + return Eval(exp->mLeft); + + case EX_INITIALIZATION: + case EX_ASSIGNMENT: + { + Value lexp = Eval(exp->mLeft); + Value rexp = REval(exp->mRight); + + if (exp->mToken != TK_ASSIGN) + rexp = EvalBinary(exp, lexp.ToRValue(), rexp); + lexp.Assign(EvalCoerce(exp, rexp, lexp.mDecType)); + return lexp; + } + + case EX_IF: + { + Value v = REval(exp->mLeft); + if (v.GetInt()) + Eval(exp->mRight->mLeft); + else if (exp->mRight->mRight) + Eval(exp->mRight->mRight); + return Value(); + } + + case EX_POSTINCDEC: + { + Value vl = Eval(exp->mLeft); + Value vr = vl.ToRValue(); + vl.Assign(EvalUnary(exp, vr)); + return vr; + } + + case EX_PREINCDEC: + { + Value vl = Eval(exp->mLeft); + vl.Assign(EvalUnary(exp, vl.ToRValue())); + return vl; + } + + case EX_WHILE: + { + Value v = REval(exp->mLeft); + while (v.GetInt()) + { + Eval(exp->mRight); + v = REval(exp->mLeft); + } + return Value(); + } + + case EX_DO: + { + Value v; + + do { + Eval(exp->mRight); + v = REval(exp->mLeft); + } while (v.GetInt()); + + return Value(); + } + + case EX_FOR: + { + Value v; + + if (exp->mLeft->mRight) + Eval(exp->mLeft->mRight); + + if (exp->mLeft->mLeft->mLeft) + v = REval(exp->mLeft->mLeft->mLeft); + else + v.PutInt(1); + + while (v.GetInt()) + { + Eval(exp->mRight); + + if (exp->mLeft->mLeft->mRight) + Eval(exp->mLeft->mLeft->mRight); + + if (exp->mLeft->mLeft->mLeft) + v = REval(exp->mLeft->mLeft->mLeft); + } + + return Value(); + } + + case EX_QUALIFY: + { + Value v = Eval(exp->mLeft); + if (v.mBaseValue) + return Value(v.mBaseValue, exp->mDecType, v.mOffset + exp->mDecValue->mOffset); + } + + case EX_INDEX: + { + Value v = Eval(exp->mLeft); + Value vi = REval(exp->mRight); + + if (v.mDecType->mType == DT_TYPE_ARRAY) + { + if (v.mBaseValue) + return Value(v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * vi.GetInt()); + } + else if (v.mDecType->mType == DT_TYPE_POINTER) + { + Value p = v.GetPtr(); + return Value(p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * vi.GetInt()); + } + } + + case EX_VOID: + return Value(exp->mLocation); + + } + + mErrors->Error(exp->mLocation, EERR_INVALID_CONSTEXPR, "Invalid constexpr"); + + return exp; +} + +ConstexprInterpreter::ValueItem::ValueItem(void) + : mByte(0), mBaseValue(nullptr) +{ +} diff --git a/oscar64/Constexpr.h b/oscar64/Constexpr.h new file mode 100644 index 0000000..b675cba --- /dev/null +++ b/oscar64/Constexpr.h @@ -0,0 +1,89 @@ +#pragma once + +#include "Declaration.h" + +class ConstexprInterpreter +{ +public: + ConstexprInterpreter(const Location & loc, Errors * err, LinkerSection * dataSection); + ~ConstexprInterpreter(void); + + Expression* EvalCall(Expression* exp); +protected: + struct Value; + + struct ValueItem + { + uint8 mByte; + Value* mBaseValue; + + ValueItem(void); + }; + + struct Value + { + ~Value(void); + Value(const Location& location); + Value(Expression * exp); + Value(const Location& location, Declaration * dec); + Value(const Value& value); + Value(Value&& value); + Value(Value * value, Declaration * type, int offset); + Value(Value* value); + Value(const Location& location, const uint8 * data, Declaration* type); + Value(const Location& location, const ValueItem* data, Declaration* type); + Value(void); + + Value& operator=(const Value& v); + Value& operator=(Value&& v); + + Value ToRValue(void) const; + Expression* ToExpression(LinkerSection* dataSection) const; + void Assign(const Value& v); + + Location mLocation; + Declaration * mDecType; + Value * mBaseValue; + int mOffset; + ValueItem * mData; + int mDataSize; + ValueItem mShortData[4]; + + ValueItem* GetAddr(void); + const ValueItem* GetAddr(void) const; + + int64 GetInt(void) const; + double GetFloat(void) const; + Value GetPtr(void) const; + void PutInt(int64 v); + void PutFloat(double v); + void PutPtr(const Value& v); + + int64 GetIntAt(int at, Declaration* type) const; + double GetFloatAt(int at, Declaration* type) const; + Value GetPtrAt(int at, Declaration* type) const; + void PutIntAt(int64 v, int at, Declaration* type); + void PutFloatAt(double v, int at, Declaration* type); + void PutPtrAt(const Value& v, int at, Declaration* type); + + void PutConst(int offset, Declaration * dec); + Declaration* GetConst(int offset, Declaration* type, LinkerSection* dataSection) const; + }; + + Value EvalCall(Expression* exp, ConstexprInterpreter* caller); + Value EvalBinary(Expression* exp, const Value& vl, const Value& vr); + Value EvalUnary(Expression* exp, const Value& vl); + Value EvalRelational(Expression* exp, const Value& vl, const Value& vr); + Value EvalTypeCast(Expression* exp, const Value& vl, Declaration* type); + Value EvalCoerce(Expression* exp, const Value& vl, Declaration* type); + + Value REval(Expression* exp); + Value Eval(Expression* exp); + + Declaration* mProcType; + Location mLocation; + LinkerSection* mDataSection; + GrowingArray mParams, mLocals; + Errors * mErrors; + Value mResult; +}; \ No newline at end of file diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 73ed7fd..d5ee14d 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1,4 +1,6 @@ #include "Declaration.h" +#include "Constexpr.h" +#include DeclarationScope::DeclarationScope(DeclarationScope* parent, ScopeLevel level, const Ident* name) { @@ -430,7 +432,7 @@ Expression* Expression::LogicInvertExpression(void) } } -Expression* Expression::ConstantFold(Errors * errors) +Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSection) { if (mType == EX_PREFIX && mLeft->mType == EX_CONSTANT) { @@ -775,9 +777,9 @@ Expression* Expression::ConstantFold(Errors * errors) if (mLeft->mDecValue->mType == DT_CONST_INTEGER) { if (mLeft->mDecValue->mInteger != 0) - return mRight->mLeft->ConstantFold(errors); + return mRight->mLeft->ConstantFold(errors, dataSection); else - return mRight->mRight->ConstantFold(errors); + return mRight->mRight->ConstantFold(errors, dataSection); } } else if (mType == EX_BINARY && mToken == TK_ADD && mLeft->mType == EX_VARIABLE && mLeft->mDecValue->mType == DT_VARIABLE && (mLeft->mDecValue->mFlags & DTF_GLOBAL) && mLeft->mDecType->mType == DT_TYPE_ARRAY && mRight->mType == EX_CONSTANT && mRight->mDecValue->mType == DT_CONST_INTEGER) @@ -807,7 +809,7 @@ Expression* Expression::ConstantFold(Errors * errors) else if (mType == EX_BINARY && mToken == TK_ADD && mLeft->mType == EX_VARIABLE && mLeft->mDecValue->mType == DT_VARIABLE && (mLeft->mDecValue->mFlags & DTF_CONST) && mLeft->mDecType->mType == DT_TYPE_POINTER && mRight->mType == EX_CONSTANT && mRight->mDecValue->mType == DT_CONST_INTEGER) { mLeft = mLeft->mDecValue->mValue; - return this->ConstantFold(errors); + return this->ConstantFold(errors, dataSection); } else if (mType == EX_QUALIFY && mLeft->mType == EX_VARIABLE && mLeft->mDecValue->mType == DT_VARIABLE && (mLeft->mDecValue->mFlags & DTF_GLOBAL) && mLeft->mDecType->mType == DT_TYPE_STRUCT) { @@ -833,6 +835,44 @@ Expression* Expression::ConstantFold(Errors * errors) ex->mDecType = mDecType; return ex; } + else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_INTRINSIC) && mRight->mType == EX_CONSTANT) + { + Declaration* decf = mLeft->mDecValue, * decp = mRight->mDecValue; + const Ident* iname = decf->mQualIdent; + + if (decp->mType == DT_TYPE_FLOAT || decp->mType == DT_TYPE_INTEGER) + { + double d = decp->mType == DT_TYPE_FLOAT ? decp->mNumber : decp->mInteger; + + bool check = false; + + if (!strcmp(iname->mString, "fabs")) + d = fabs(d); + else if (!strcmp(iname->mString, "floor")) + d = floor(d); + else if (!strcmp(iname->mString, "ceil")) + d = ceil(d); + else if (!strcmp(iname->mString, "sin")) + d = sin(d); + else if (!strcmp(iname->mString, "cos")) + d = cos(d); + else + return this; + + Expression* ex = new Expression(mLocation, EX_CONSTANT); + Declaration* dec = new Declaration(mLocation, DT_CONST_FLOAT); + dec->mBase = TheFloatTypeDeclaration; + dec->mNumber = d; + ex->mDecValue = dec; + ex->mDecType = dec->mBase; + return ex; + } + } + else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_CONSTEXPR)) + { + ConstexprInterpreter cinter(mLocation, errors, dataSection); + return cinter.EvalCall(this); + } return this; } @@ -1195,7 +1235,7 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) Declaration *ftdec = tdec->mTemplate; while (ftdec) { - if (ftdec->mBase == fdec) + if (ftdec->mBase->IsConstSame(fdec)) { Declaration* fpdec = ftdec->mParams; Declaration* tpdec = tdec->mTemplate->mParams; @@ -1361,6 +1401,7 @@ Declaration* Declaration::ToConstType(void) ndec->mParams = mParams; ndec->mIdent = mIdent; ndec->mQualIdent = mQualIdent; + ndec->mTemplate = mTemplate; ndec->mDefaultConstructor = mDefaultConstructor; ndec->mCopyConstructor = mCopyConstructor; @@ -1392,6 +1433,7 @@ Declaration* Declaration::ToMutableType(void) ndec->mParams = mParams; ndec->mIdent = mIdent; ndec->mQualIdent = mQualIdent; + ndec->mTemplate = mTemplate; ndec->mDefaultConstructor = mDefaultConstructor; ndec->mCopyConstructor = mCopyConstructor; @@ -1926,6 +1968,7 @@ Declaration* TheVoidTypeDeclaration, * TheConstVoidTypeDeclaration, * TheSignedI Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheConstVoidPointerTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration; Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration; Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration; +Expression* TheVoidExpression; void InitDeclarations(void) { @@ -2004,4 +2047,8 @@ void InitDeclarations(void) TheConstCharPointerTypeDeclaration->mBase = TheConstCharTypeDeclaration; TheConstCharPointerTypeDeclaration->mSize = 2; TheConstCharPointerTypeDeclaration->mFlags = DTF_DEFINED; + + TheVoidExpression = new Expression(noloc, EX_CONSTANT); + TheVoidExpression->mDecType = TheConstVoidTypeDeclaration; + TheVoidExpression->mDecValue = TheConstVoidValueDeclaration; } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index d01e043..e98a54d 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -93,6 +93,7 @@ static const uint64 DTF_PROTECTED = (1ULL << 27); static const uint64 DTF_VIRTUAL = (1ULL << 28); static const uint64 DTF_TEMPORARY = (1ULL << 29); static const uint64 DTF_COMPLETED = (1ULL << 30); +static const uint64 DTF_CONSTEXPR = (1ULL << 31); static const uint64 DTF_FUNC_VARIABLE = (1ULL << 32); static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33); @@ -104,9 +105,9 @@ static const uint64 DTF_FUNC_INTRSAVE = (1ULL << 37); static const uint64 DTF_FUNC_INTRCALLED = (1ULL << 38); static const uint64 DTF_FUNC_PURE = (1ULL << 39); -static const uint64 DTF_FPARAM_CONST = (1ULL << 40); -static const uint64 DTF_FPARAM_NOCONST = (1ULL << 41); -static const uint64 DTF_VAR_ADDRESS = (1ULL << 42); +static const uint64 DTF_FPARAM_CONST = (1ULL << 40); +static const uint64 DTF_FPARAM_NOCONST = (1ULL << 41); +static const uint64 DTF_VAR_ADDRESS = (1ULL << 42); static const uint64 DTF_FUNC_THIS = (1ULL << 43); @@ -236,7 +237,7 @@ public: bool mConst; Expression* LogicInvertExpression(void); - Expression* ConstantFold(Errors * errors); + Expression* ConstantFold(Errors * errors, LinkerSection* dataSection); bool HasSideEffects(void) const; bool IsSame(const Expression* exp) const; @@ -328,4 +329,5 @@ extern Declaration* TheVoidTypeDeclaration, * TheConstVoidTypeDeclaration, * The extern Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheConstVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration; extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration; extern Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration; +extern Expression* TheVoidExpression; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 95c32f1..672710b 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -84,6 +84,8 @@ enum ErrorID EERR_TEMPLATE_PARAMS, EERR_FUNCTION_TEMPLATE, + EERR_INVALID_CONSTEXPR, + ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, EERR_OVERLAPPING_DATA_SECTIONS, diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index a37c0ae..0ba2108 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16921,7 +16921,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "opp::sort::iterator,>"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; @@ -18444,7 +18444,7 @@ void InterCodeProcedure::Disassemble(FILE* file) void InterCodeProcedure::Disassemble(const char* name, bool dumpSets) { -#if 1 +#if 0 #ifdef _WIN32 FILE* file; static bool initial = true; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 9d9e70c..e683d77 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -100,6 +100,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p return v; } + if (v.mType->IsReference() && type->IsSimpleType()) + { + v.mReference++; + v.mType = v.mType->mBase; + v = Dereference(proc, exp, block, v); + } + if (v.mType->IsIntegerType() && type->mType == DT_TYPE_FLOAT) { if (v.mType->mSize == 1) @@ -2878,6 +2885,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* return ExValue(TheFloatTypeDeclaration, ins->mDst.mTemp); } + else if (!strcmp(iname->mString, "sin")) + { + } + else if (!strcmp(iname->mString, "cos")) + { + } else if (!strcmp(iname->mString, "malloc")) { vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); @@ -4734,7 +4747,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mQualIdent, mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_BYTE_CODE, dec->mAlignment)); #if 0 - if (proc->mIdent && !strcmp(proc->mIdent->mString, "test")) + if (proc->mIdent && !strcmp(proc->mIdent->mString, "main")) exp->Dump(0); #endif #if 0 diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index d4f18e3..86ab51d 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -508,6 +508,31 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio return dec; } +Declaration* Parser::ParseBaseTypeQualify(bool qualified, Declaration* dec, const Ident*& pident) +{ + while (dec && (dec->mType == DT_NAMESPACE || (qualified && (dec->mType == DT_TYPE_STRUCT || dec->mType == DT_TYPE_TEMPLATE))) && ConsumeTokenIf(TK_COLCOLON)) + { + if (ExpectToken(TK_IDENT)) + { + pident = mScanner->mTokenIdent; + if (dec->mType == DT_TYPE_TEMPLATE) + { + Declaration* ndec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); + ndec->mFlags |= DTF_DEFINED; + ndec->mBase = dec; + ndec->mIdent = pident; + dec = ndec; + } + else + dec = dec->mScope->Lookup(pident); + + mScanner->NextToken(); + } + } + + return dec; +} + Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Declaration* ptempl) { Declaration* dec = nullptr; @@ -633,31 +658,15 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl mScanner->NextToken(); + dec = ParseBaseTypeQualify(qualified, dec, pident); + if (dec && dec->mTemplate) dec = ParseTemplateExpansion(dec->mTemplate, nullptr); } else mScanner->NextToken(); - while (qualified && dec && (dec->mType == DT_TYPE_STRUCT || dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_TEMPLATE) && ConsumeTokenIf(TK_COLCOLON)) - { - if (ExpectToken(TK_IDENT)) - { - pident = mScanner->mTokenIdent; - if (dec->mType == DT_TYPE_TEMPLATE) - { - Declaration* ndec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); - ndec->mFlags |= DTF_DEFINED; - ndec->mBase = dec; - ndec->mIdent = mScanner->mTokenIdent; - dec = ndec; - } - else - dec = dec->mScope->Lookup(mScanner->mTokenIdent); - - mScanner->NextToken(); - } - } + dec = ParseBaseTypeQualify(qualified, dec, pident); if (dec && dec->mType <= DT_TYPE_FUNCTION) { @@ -3341,6 +3350,11 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex storageFlags |= DTF_STATIC; mScanner->NextToken(); } + else if (mScanner->mToken == TK_CONSTEXPR) + { + storageFlags |= DTF_CONSTEXPR; + mScanner->NextToken(); + } else if (mScanner->mToken == TK_EXTERN) { storageFlags |= DTF_EXTERN; @@ -4035,7 +4049,11 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex ndec->mValue = ParseInitExpression(ndec->mBase); if (ndec->mBase->mType == DT_TYPE_AUTO) { - ndec->mBase = ndec->mValue->mDecType; + if (ndec->mBase->mFlags & DTF_CONST) + ndec->mBase = ndec->mValue->mDecType->ToConstType(); + else + ndec->mBase = ndec->mValue->mDecType; + if (ndec->mBase->mType == DT_TYPE_ARRAY) { ndec->mBase = ndec->mBase->Clone(); @@ -4603,7 +4621,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) dexp->mDecType = texp->mDecType->mBase; dexp->mLeft = texp; - dexp = dexp->ConstantFold(mErrors); + dexp = dexp->ConstantFold(mErrors, mDataSection); exp = ParseQualify(dexp); } @@ -4750,7 +4768,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; nexp->mLeft = ParsePrefixExpression(false); - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } } break; @@ -4830,7 +4848,7 @@ Expression* Parser::ParseQualify(Expression* exp) { Declaration* dtype = exp->mDecType; - exp = exp->ConstantFold(mErrors); + exp = exp->ConstantFold(mErrors, mDataSection); if (dtype->mType == DT_TYPE_REFERENCE || dtype->mType == DT_TYPE_RVALUEREF) dtype = dtype->mBase; @@ -4896,14 +4914,14 @@ Expression* Parser::ParseQualify(Expression* exp) if (exp->mDecType->mFlags & DTF_CONST) nexp->mDecType = nexp->mDecType->ToConstType(); - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } else if (mdec->mType == DT_VARIABLE) { nexp = new Expression(mScanner->mLocation, EX_VARIABLE); nexp->mDecValue = mdec; nexp->mDecType = mdec->mBase; - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } else if (mdec->mType == DT_CONST_FUNCTION) { @@ -5264,7 +5282,7 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) { if (!type->IsConstSame(tdec)) { - Declaration* fcons = type->mScope->Lookup(type->mIdent->PreMangle("+")); + Declaration* fcons = type->mScope ? type->mScope->Lookup(type->mIdent->PreMangle("+")) : nullptr; if (fcons) { while (fcons && !(fcons->mBase->mParams && fcons->mBase->mParams->mNext && !fcons->mBase->mParams->mNext->mNext && fcons->mBase->mParams->mNext->mBase->CanAssign(tdec))) @@ -5595,7 +5613,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; nexp->mLeft = pexp; - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } else { @@ -6162,7 +6180,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) nexp->mDecType = nexp->mLeft->mDecType; } nexp = CheckOperatorOverload(nexp); - return nexp->ConstantFold(mErrors); + return nexp->ConstantFold(mErrors, mDataSection); } else return ParsePostfixExpression(lhs); @@ -6187,7 +6205,7 @@ Expression* Parser::ParseMulExpression(bool lhs) exp = CheckOperatorOverload(nexp); - exp = exp->ConstantFold(mErrors); + exp = exp->ConstantFold(mErrors, mDataSection); } return exp; @@ -6235,7 +6253,7 @@ Expression* Parser::ParseAddExpression(bool lhs) exp = CheckOperatorOverload(nexp); - exp = exp->ConstantFold(mErrors); + exp = exp->ConstantFold(mErrors, mDataSection); } return exp; @@ -6254,7 +6272,7 @@ Expression* Parser::ParseShiftExpression(bool lhs) nexp->mRight = ParseAddExpression(false); nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); exp = CheckOperatorOverload(exp); } @@ -6275,7 +6293,7 @@ Expression* Parser::ParseRelationalExpression(bool lhs) nexp->mRight = ParseShiftExpression(false); nexp->mDecType = TheBoolTypeDeclaration; - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); exp = CheckOperatorOverload(exp); } @@ -6296,7 +6314,7 @@ Expression* Parser::ParseBinaryAndExpression(bool lhs) nexp->mRight = ParseRelationalExpression(false); nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); exp = CheckOperatorOverload(exp); } @@ -6316,7 +6334,7 @@ Expression* Parser::ParseBinaryXorExpression(bool lhs) mScanner->NextToken(); nexp->mRight = ParseBinaryAndExpression(false); nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); exp = CheckOperatorOverload(exp); } @@ -6336,7 +6354,7 @@ Expression* Parser::ParseBinaryOrExpression(bool lhs) mScanner->NextToken(); nexp->mRight = ParseBinaryXorExpression(false); nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); exp = CheckOperatorOverload(exp); } @@ -6356,7 +6374,7 @@ Expression* Parser::ParseLogicAndExpression(bool lhs) mScanner->NextToken(); nexp->mRight = CoerceExpression(ParseBinaryOrExpression(false), TheBoolTypeDeclaration); nexp->mDecType = TheBoolTypeDeclaration; - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } return exp; @@ -6374,7 +6392,7 @@ Expression* Parser::ParseLogicOrExpression(bool lhs) mScanner->NextToken(); nexp->mRight = CoerceExpression(ParseLogicAndExpression(false), TheBoolTypeDeclaration); nexp->mDecType = TheBoolTypeDeclaration; - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } return exp; @@ -6397,7 +6415,7 @@ Expression* Parser::ParseConditionalExpression(bool lhs) texp->mRight = ParseConditionalExpression(false); nexp->mDecType = texp->mLeft->mDecType; - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } return exp; @@ -6405,7 +6423,7 @@ Expression* Parser::ParseConditionalExpression(bool lhs) Expression* Parser::ParseRExpression(void) { - return ParseConditionalExpression(false); + return ParseConditionalExpression(false)->ConstantFold(mErrors, mDataSection); } Expression* Parser::ParseParenthesisExpression(void) @@ -6515,7 +6533,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp->ConstantFold(mErrors); + lexp->mLeft = texp->ConstantFold(mErrors, mDataSection); lexp->mRight = nexp->mRight; nexp->mRight = lexp; @@ -6533,7 +6551,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; - if (tdec->mType == DT_TYPE_STRUCT) + if (tdec->mType == DT_TYPE_STRUCT && tdec->mScope) { const Ident* opident = Ident::Unique("operator[]"); @@ -6558,7 +6576,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp->ConstantFold(mErrors); + lexp->mLeft = texp->ConstantFold(mErrors, mDataSection); lexp->mRight = nexp->mRight; nexp->mRight = lexp; @@ -6585,7 +6603,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) if (opident) { Declaration* tdec = exp->mLeft->mDecType; - if (tdec->mType == DT_TYPE_STRUCT) + if (tdec->mType == DT_TYPE_STRUCT && tdec->mScope) { Declaration* mdec = tdec->mScope->Lookup(opident); if (mdec) @@ -6607,7 +6625,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mBase = exp->mLeft->mDecType; texp->mDecType->mSize = 2; - nexp->mRight = texp->ConstantFold(mErrors); + nexp->mRight = texp->ConstantFold(mErrors, mDataSection); nexp = ResolveOverloadCall(nexp); nexp->mDecType = nexp->mLeft->mDecType->mBase; @@ -6656,7 +6674,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp->ConstantFold(mErrors); + lexp->mLeft = texp->ConstantFold(mErrors, mDataSection); lexp->mRight = new Expression(nexp->mLocation, EX_CONSTANT); lexp->mRight->mDecType = TheSignedIntTypeDeclaration; lexp->mRight->mDecValue = new Declaration(nexp->mLocation, DT_CONST_INTEGER); @@ -6772,7 +6790,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp->ConstantFold(mErrors); + lexp->mLeft = texp->ConstantFold(mErrors, mDataSection); lexp->mRight = nexp->mRight; nexp->mRight = lexp; @@ -6834,7 +6852,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; - nexp->mRight = texp->ConstantFold(mErrors); + nexp->mRight = texp->ConstantFold(mErrors, mDataSection); nexp = ResolveOverloadCall(nexp); nexp->mDecType = nexp->mLeft->mDecType->mBase; @@ -6873,7 +6891,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; - nexp->mRight = texp->ConstantFold(mErrors); + nexp->mRight = texp->ConstantFold(mErrors, mDataSection); nexp = ResolveOverloadCall(nexp); nexp->mDecType = nexp->mLeft->mDecType->mBase; @@ -7578,6 +7596,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp bdec->mTemplate = tdec; bdec->mBase = tmpld->mBase; tdec->mNext = tmpld; + bdec->mIdent = tdec->MangleIdent(); return bdec; } @@ -7754,8 +7773,9 @@ void Parser::ParseTemplateDeclaration(void) mTemplateScope = tdec->mScope; ConsumeTokenIf(TK_INLINE); + ConsumeTokenIf(TK_CONSTEXPR); - Declaration* bdec = ParseBaseTypeDeclaration(0, false); + Declaration* bdec = ParseBaseTypeDeclaration(0, true); Declaration* adec = ParsePostfixDeclaration(); adec = ReverseDeclaration(adec, bdec); @@ -7991,7 +8011,7 @@ Expression* Parser::ParseAssemblerMulOperand(Declaration* pcasm, int pcoffset) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseAssemblerBaseOperand(pcasm, pcoffset); - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } return exp; } @@ -8050,7 +8070,7 @@ Expression* Parser::ParseAssemblerAddOperand(Declaration* pcasm, int pcoffset) mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Integer offset expected"); } else - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } return exp; } @@ -8065,7 +8085,7 @@ Expression* Parser::ParseAssemblerShiftOperand(Declaration* pcasm, int pcoffset) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseAssemblerAddOperand(pcasm, pcoffset); - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } return exp; } @@ -8081,7 +8101,7 @@ Expression* Parser::ParseAssemblerAndOperand(Declaration* pcasm, int pcoffset) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseAssemblerShiftOperand(pcasm, pcoffset); - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } return exp; } @@ -8096,7 +8116,7 @@ Expression* Parser::ParseAssemblerOrOperand(Declaration* pcasm, int pcoffset) nexp->mLeft = exp; mScanner->NextToken(); nexp->mRight = ParseAssemblerAndOperand(pcasm, pcoffset); - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors, mDataSection); } return exp; } diff --git a/oscar64/Parser.h b/oscar64/Parser.h index bf3faad..064be45 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -57,6 +57,7 @@ protected: Expression * AddFunctionCallRefReturned(Expression * exp); Expression* CleanupExpression(Expression* exp); + Declaration* ParseBaseTypeQualify(bool qualified, Declaration* dec, const Ident *& pident); Declaration* ParseBaseTypeDeclaration(uint64 flags, bool qualified, Declaration* ptempl = nullptr); Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr, Declaration * ptempl = nullptr); Declaration* ParseStructDeclaration(uint64 flags, DecType dt, Declaration* ptempl = nullptr); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 895438c..39e8efb 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -164,6 +164,7 @@ const char* TokenNames[] = "'operator'", "'template'", "'friend'", + "'constexpr'", }; @@ -1514,6 +1515,8 @@ void Scanner::NextRawToken(void) mToken = TK_TEMPLATE; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "friend")) mToken = TK_FRIEND; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "constexpr")) + mToken = TK_CONSTEXPR; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 98b5756..3408285 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -163,6 +163,7 @@ enum Token TK_OPERATOR, TK_TEMPLATE, TK_FRIEND, + TK_CONSTEXPR, NUM_TOKENS }; diff --git a/oscar64/oscar64.vcxproj b/oscar64/oscar64.vcxproj index 619162a..a87fe01 100644 --- a/oscar64/oscar64.vcxproj +++ b/oscar64/oscar64.vcxproj @@ -158,6 +158,7 @@ + @@ -184,6 +185,7 @@ + diff --git a/oscar64/oscar64.vcxproj.filters b/oscar64/oscar64.vcxproj.filters index d4cd396..cbde344 100644 --- a/oscar64/oscar64.vcxproj.filters +++ b/oscar64/oscar64.vcxproj.filters @@ -78,6 +78,9 @@ Source Files + + Source Files + @@ -152,6 +155,9 @@ Header Files + + Header Files +