Fix pointers in constexpr

This commit is contained in:
drmortalwombat 2023-09-20 14:19:56 +02:00
parent e20c098ab1
commit a0409002b6
16 changed files with 1216 additions and 306 deletions

View File

@ -18,6 +18,9 @@ rem @echo off
@call :test opp_streamtest.cpp @call :test opp_streamtest.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test opp_pairtest.cpp
@if %errorlevel% neq 0 goto :error
@call :test operatoroverload.cpp @call :test operatoroverload.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error

28
autotest/opp_pairtest.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <assert.h>
#include <opp/vector.h>
#include <opp/utility.h>
#include <opp/iostream.h>
using namespace opp;
int main(void)
{
vector<pair<int, int> > vii;
for(int i=0; i<100; i++)
vii.push_back(make_pair(i, i * i));
int sum1 = 0;
long sum2 = 0;
for(const auto & v : vii)
{
sum1 += v.first;
sum2 += v.second;
}
assert(sum1 == 4950);
assert(sum2 == 328350l);
return 0;
}

View File

@ -1,14 +0,0 @@
#ifndef OPP_MOVE_H
#define OPP_MOVE_H
namespace opp {
template <class T>
T && move(T & m)
{
return (T &&)m;
}
}
#endif

34
include/opp/utility.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef OPP_UTILITY_H
#define OPP_UTILITY_H
namespace opp {
template <class T>
T && move(T & m)
{
return (T &&)m;
}
template<class T1, class T2>
struct pair
{
T1 first;
T2 second;
pair(T1 && t1, T2 && t2)
: first(t1), second(t2)
{}
};
template<class T1, class T2>
constexpr pair<T1, T2> make_pair(T1 && t1, T2 && t2)
{
return pair<T1, T2>(t1, t2);
}
}
#endif

View File

@ -2,7 +2,7 @@
#define OPP_VECTOR_H #define OPP_VECTOR_H
#include <stdlib.h> #include <stdlib.h>
#include <opp/move.h> #include <opp/utility.h>
namespace opp { namespace opp {

View File

@ -37,6 +37,7 @@ void ConstexprInterpreter::Value::PutConst(int offset, Declaration* dec)
switch (dec->mType) switch (dec->mType)
{ {
case DT_CONST_INTEGER: case DT_CONST_INTEGER:
case DT_CONST_ADDRESS:
PutIntAt(dec->mInteger, offset, dec->mBase); PutIntAt(dec->mInteger, offset, dec->mBase);
break; break;
case DT_CONST_FLOAT: case DT_CONST_FLOAT:
@ -46,6 +47,10 @@ void ConstexprInterpreter::Value::PutConst(int offset, Declaration* dec)
for (Declaration* pdec = dec->mParams; pdec; pdec = pdec->mNext) for (Declaration* pdec = dec->mParams; pdec; pdec = pdec->mNext)
PutConst(pdec->mOffset, pdec); PutConst(pdec->mOffset, pdec);
break; break;
case DT_CONST_DATA:
for (int i = 0; i < dec->mBase->mSize; i++)
PutIntAt(dec->mData[i], offset + i, TheConstCharTypeDeclaration);
break;
} }
} }
@ -116,8 +121,8 @@ ConstexprInterpreter::Value::Value(Value* value)
{ {
} }
ConstexprInterpreter::Value::Value(Value* value, Declaration* type, int offset) ConstexprInterpreter::Value::Value(const Location& location, Value* value, Declaration* type, int offset)
: mLocation(value->mLocation), : mLocation(location),
mDecType(type), mDecType(type),
mBaseValue(value), mOffset(offset), mBaseValue(value), mOffset(offset),
mDataSize(0), mData(mShortData) mDataSize(0), mData(mShortData)
@ -331,7 +336,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Value::GetPtrAt(int at, Declar
{ {
const ValueItem* dp = GetAddr() + at; const ValueItem* dp = GetAddr() + at;
return Value(dp->mBaseValue, type, uint16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8))); return Value(mLocation, dp->mBaseValue, type, uint16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8)));
} }
void ConstexprInterpreter::Value::PutIntAt(int64 v, int at, Declaration* type) void ConstexprInterpreter::Value::PutIntAt(int64 v, int at, Declaration* type)
@ -448,19 +453,27 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
dec->mSize = type->mSize; dec->mSize = type->mSize;
dec->mSection = dataSection; dec->mSection = dataSection;
dec->mOffset = offset; dec->mOffset = offset;
Declaration* ldec = nullptr; Declaration* ldec = nullptr;
for (Declaration* mdec = type->mParams; mdec; mdec = mdec->mNext) while (type)
{ {
Declaration * cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection); for (Declaration* mdec = type->mParams; mdec; mdec = mdec->mNext)
cdec->mOffset = mdec->mOffset; {
Declaration* cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection);
cdec->mOffset = mdec->mOffset;
if (ldec) if (ldec)
ldec->mNext = cdec; ldec->mNext = cdec;
else
dec->mParams = cdec;
ldec = cdec;
}
if (type->mBase)
type = type->mBase->mBase;
else else
dec->mParams = cdec; type = nullptr;
ldec = cdec;
} }
break; break;
} }
@ -486,6 +499,46 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
} }
break; break;
} }
case DT_TYPE_POINTER:
{
Value vp = GetPtrAt(offset, type);
if (vp.mBaseValue)
{
dec = new Declaration(mLocation, DT_CONST_POINTER);
dec->mBase = type;
dec->mSize = type->mSize;
Declaration* target;
if (vp.mBaseValue->mDecType->mType == DT_TYPE_ARRAY)
{
target = new Declaration(mLocation, DT_CONST_DATA);
target->mSize = vp.mBaseValue->mDataSize;
target->mBase = vp.mBaseValue->mDecType;
target->mSection = dataSection;
uint8* buffer = new uint8[target->mSize];
for (int i = 0; i < target->mSize; i++)
buffer[i] = uint8(vp.mBaseValue->GetIntAt(i, TheUnsignedCharTypeDeclaration));
target->mData = buffer;
}
else
target = vp.mBaseValue->GetConst(0, vp.mBaseValue->mDecType, dataSection);
dec->mValue = new Expression(mLocation, EX_CONSTANT);
dec->mValue->mDecType = target->mBase;
dec->mValue->mDecValue = target;
}
else
{
dec = new Declaration(mLocation, DT_CONST_ADDRESS);
dec->mBase = type;
dec->mFlags = 0;
dec->mSize = type->mSize;
dec->mInteger = vp.mOffset;
}
break;
}
} }
@ -511,7 +564,8 @@ ConstexprInterpreter::ConstexprInterpreter(const Location & location, Errors* er
ConstexprInterpreter::~ConstexprInterpreter(void) ConstexprInterpreter::~ConstexprInterpreter(void)
{ {
for (int i = 0; i < mTemps.Size(); i++)
delete mTemps[i];
} }
ConstexprInterpreter::Value* ConstexprInterpreter::NewValue(Expression* exp, Declaration* type, int size) ConstexprInterpreter::Value* ConstexprInterpreter::NewValue(Expression* exp, Declaration* type, int size)
@ -541,13 +595,30 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp)
Declaration* dec = exp->mLeft->mDecType->mParams; Declaration* dec = exp->mLeft->mDecType->mParams;
int pos = 0; int pos = 0;
if (mProcType->mBase && mProcType->mBase->mType == DT_TYPE_STRUCT)
{
mResult = Value(exp->mLocation, mProcType->mBase);
mParams[0] = Value(&mResult);
pos = 2;
}
while (pex && pex->mType == EX_LIST) while (pex && pex->mType == EX_LIST)
{ {
if (dec) if (dec)
pos = dec->mVarIndex; pos = dec->mVarIndex;
if (pex->mLeft->mType == EX_CONSTANT) if (pex->mLeft->mType == EX_CONSTANT)
mParams[pos] = Value(pex->mLeft); {
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)) 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] = Value(pex->mLeft->mLocation, pex->mLeft->mDecValue->mBase);
@ -566,7 +637,17 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp)
pos = dec->mVarIndex; pos = dec->mVarIndex;
if (pex->mType == EX_CONSTANT) if (pex->mType == EX_CONSTANT)
mParams[pos] = Value(pex); {
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)) else if (pex->mType == EX_VARIABLE && (pex->mDecValue->mFlags & DTF_CONST))
{ {
mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase); mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase);
@ -619,6 +700,12 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalBinary(Expression * exp, c
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]);
} }
} }
else if (exp->mDecType->mType == DT_TYPE_POINTER)
{
Value vlp = vl.GetPtr();
vlp.mOffset += int(vr.GetInt() * vl.mDecType->mBase->mSize);
v.PutPtr(vlp);
}
else else
{ {
switch (exp->mToken) switch (exp->mToken)
@ -880,6 +967,13 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons
Declaration* dec = exp->mLeft->mDecType->mParams; Declaration* dec = exp->mLeft->mDecType->mParams;
int pos = 0; int pos = 0;
if (mProcType->mBase && mProcType->mBase->mType == DT_TYPE_STRUCT)
{
mResult = Value(exp->mLocation, mProcType->mBase);
mParams[0] = Value(&mResult);
pos = 2;
}
while (pex && pex->mType == EX_LIST) while (pex && pex->mType == EX_LIST)
{ {
if (dec) if (dec)
@ -1096,7 +1190,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
{ {
Value v = Eval(exp->mLeft); Value v = Eval(exp->mLeft);
if (v.mBaseValue) if (v.mBaseValue)
return Value(v.mBaseValue, exp->mDecType, v.mOffset + exp->mDecValue->mOffset); return Value(exp->mLocation, v.mBaseValue, exp->mDecType, v.mOffset + exp->mDecValue->mOffset);
} }
case EX_INDEX: case EX_INDEX:
@ -1107,15 +1201,26 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
if (v.mDecType->mType == DT_TYPE_ARRAY) if (v.mDecType->mType == DT_TYPE_ARRAY)
{ {
if (v.mBaseValue) if (v.mBaseValue)
return Value(v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt())); return Value(exp->mLocation, v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt()));
} }
else if (v.mDecType->mType == DT_TYPE_POINTER) else if (v.mDecType->mType == DT_TYPE_POINTER)
{ {
Value p = v.GetPtr(); Value p = v.GetPtr();
return Value(p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt())); return Value(exp->mLocation, p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt()));
} }
} }
case EX_RESULT:
if (mParams[0].mBaseValue)
return mParams[0];
else
return Value(&mParams[0]);
case EX_CONSTRUCT:
if (exp->mLeft->mLeft)
Eval(exp->mLeft->mLeft);
return Eval(exp->mRight);
case EX_VOID: case EX_VOID:
return Value(exp->mLocation); return Value(exp->mLocation);
@ -1162,6 +1267,7 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp)
case EX_PREINCDEC: case EX_PREINCDEC:
case EX_QUALIFY: case EX_QUALIFY:
case EX_INDEX: case EX_INDEX:
case EX_RESULT:
Eval(exp); Eval(exp);
return FLOW_NEXT; return FLOW_NEXT;

View File

@ -29,7 +29,7 @@ protected:
Value(const Location& location, Declaration* dec, int count); 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(const Location& location, Value * value, Declaration * type, int offset);
Value(Value* value); Value(Value* value);
Value(const Location& location, const uint8 * data, Declaration* type); Value(const Location& location, const uint8 * data, Declaration* type);
Value(const Location& location, const ValueItem* data, Declaration* type); Value(const Location& location, const ValueItem* data, Declaration* type);
@ -101,6 +101,7 @@ protected:
GrowingArray<Value> mParams, mLocals; GrowingArray<Value> mParams, mLocals;
ExpandingArray<Expression*> mDestructStack; ExpandingArray<Expression*> mDestructStack;
ExpandingArray<Value *> * mHeap; ExpandingArray<Value *> * mHeap;
ExpandingArray<Value*> mTemps;
Errors * mErrors; Errors * mErrors;
Value mResult; Value mResult;

View File

@ -303,6 +303,9 @@ void Expression::Dump(int ident) const
case EX_PACK: case EX_PACK:
printf("PACK"); printf("PACK");
break; break;
case EX_PACK_TYPE:
printf("PACK_TYPE");
break;
} }
printf("\n"); printf("\n");
@ -355,6 +358,16 @@ bool Expression::IsRValue(void) const
return true; return true;
} }
bool Expression::IsConstRef(void) const
{
if (mDecType->mType == DT_TYPE_RVALUEREF || mDecType->mType == DT_TYPE_REFERENCE)
return true;
else if (mType == EX_VARIABLE || mType == EX_QUALIFY || mType == EX_INDEX || mType == EX_PREFIX && mToken == TK_MUL)
return true;
else
return false;
}
bool Expression::IsLValue(void) const bool Expression::IsLValue(void) const
{ {
if (mDecType->mFlags & DTF_CONST) if (mDecType->mFlags & DTF_CONST)
@ -996,7 +1009,7 @@ Declaration* Declaration::DeduceAuto(Declaration * dec)
if (dec->mType == DT_TYPE_ARRAY) if (dec->mType == DT_TYPE_ARRAY)
dec = dec->mBase->BuildPointer(mLocation); dec = dec->mBase->BuildPointer(mLocation);
if (mFlags & DTF_CONST) if ((IsReference() ? mBase->mFlags : mFlags) & DTF_CONST)
dec = dec->ToConstType(); dec = dec->ToConstType();
else else
dec = dec->ToMutableType(); dec = dec->ToMutableType();
@ -1133,7 +1146,7 @@ const Ident* Declaration::MangleIdent(void)
} }
else if (mType == DT_PACK_TYPE) else if (mType == DT_PACK_TYPE)
{ {
Declaration* dec = mBase; Declaration* dec = mParams;
while (dec) while (dec)
{ {
const Ident* id = dec->MangleIdent(); const Ident* id = dec->MangleIdent();
@ -1288,7 +1301,7 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec)
tpdec->mIdent = pdec->mBase->mBase->mIdent; tpdec->mIdent = pdec->mBase->mBase->mIdent;
else else
tpdec->mIdent = pdec->mBase->mIdent; tpdec->mIdent = pdec->mBase->mIdent;
tpdec->mBase = phead; tpdec->mParams = phead;
mScope->Insert(tpdec->mIdent, tpdec); mScope->Insert(tpdec->mIdent, tpdec);
} }
else else
@ -1434,25 +1447,66 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
Declaration *ftdec = tdec->mTemplate; Declaration *ftdec = tdec->mTemplate;
while (ftdec) while (ftdec)
{ {
if (ftdec->mBase->IsConstSame(fdec)) if (ftdec->mBase->mQualIdent == fdec->mQualIdent)
{ {
Declaration* fpdec = ftdec->mParams; Declaration* fpdec = ftdec->mParams;
Declaration* tpdec = tdec->mTemplate->mParams; Declaration* tpdec = tdec->mTemplate->mParams;
while (fpdec) while (fpdec && tpdec)
{ {
if (tpdec->mBase->mType == DT_TYPE_TEMPLATE || tpdec->mBase->mType == DT_CONST_TEMPLATE) if (tpdec->mBase->mType == DT_TYPE_TEMPLATE || tpdec->mBase->mType == DT_CONST_TEMPLATE)
{ {
Declaration * pdec = mScope->Insert(tpdec->mIdent, fpdec->mBase); Declaration * pdec = mScope->Insert(tpdec->mBase->mIdent, fpdec->mBase);
if (pdec && !pdec->IsSame(fpdec->mBase)) if (pdec && !pdec->IsSame(fpdec->mBase))
return false; return false;
} }
else if (tpdec->mBase->mType == DT_PACK_TEMPLATE)
{
Declaration* tppack;
if (fpdec->mType == DT_PACK_TEMPLATE)
tppack = fpdec->mBase;
else
{
tppack = new Declaration(fpdec->mLocation, DT_PACK_TYPE);
Declaration* ppdec = nullptr;
while (fpdec)
{
if (fpdec->mType == DT_PACK_TEMPLATE)
{
if (ppdec)
ppdec->mNext = fpdec->mBase->mParams;
else
tppack->mParams = fpdec->mBase->mParams;
break;
}
Declaration* ndec = fpdec->mBase->Clone();
if (ppdec)
ppdec->mNext = ndec;
else
tppack->mParams = ndec;
ppdec = ndec;
fpdec = fpdec->mNext;
}
}
Declaration* pdec = mScope->Insert(tpdec->mBase->mIdent, tppack);
if (pdec && !pdec->IsSame(fpdec->mBase))
return false;
return true;
}
fpdec = fpdec->mNext; fpdec = fpdec->mNext;
tpdec = tpdec->mNext; tpdec = tpdec->mNext;
} }
return true; return !fpdec && !tpdec;
} }
ftdec = ftdec->mNext; ftdec = ftdec->mNext;
@ -1604,6 +1658,7 @@ Declaration* Declaration::ToConstType(void)
ndec->mQualIdent = mQualIdent; ndec->mQualIdent = mQualIdent;
ndec->mTemplate = mTemplate; ndec->mTemplate = mTemplate;
ndec->mDestructor = mDestructor;
ndec->mDefaultConstructor = mDefaultConstructor; ndec->mDefaultConstructor = mDefaultConstructor;
ndec->mCopyConstructor = mCopyConstructor; ndec->mCopyConstructor = mCopyConstructor;
ndec->mMoveConstructor = mMoveConstructor; ndec->mMoveConstructor = mMoveConstructor;
@ -1636,6 +1691,7 @@ Declaration* Declaration::ToMutableType(void)
ndec->mQualIdent = mQualIdent; ndec->mQualIdent = mQualIdent;
ndec->mTemplate = mTemplate; ndec->mTemplate = mTemplate;
ndec->mDestructor = mDestructor;
ndec->mDefaultConstructor = mDefaultConstructor; ndec->mDefaultConstructor = mDefaultConstructor;
ndec->mCopyConstructor = mCopyConstructor; ndec->mCopyConstructor = mCopyConstructor;
ndec->mMoveConstructor = mMoveConstructor; ndec->mMoveConstructor = mMoveConstructor;
@ -1659,6 +1715,8 @@ bool Declaration::IsSameTemplate(const Declaration* dec) const
if (mType == DT_CONST_FUNCTION) if (mType == DT_CONST_FUNCTION)
return mBase->IsSame(dec->mBase); return mBase->IsSame(dec->mBase);
else if (mType == DT_TYPE_STRUCT)
return true;
return false; return false;
} }
@ -1673,7 +1731,7 @@ bool Declaration::IsSubType(const Declaration* dec) const
if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY)
{ {
if (dec->mType == DT_TYPE_POINTER) if (dec->mType == DT_TYPE_POINTER || dec->mType == DT_TYPE_ARRAY)
return /*this->Stride() == dec->Stride() &&*/ mBase->IsSubType(dec->mBase); return /*this->Stride() == dec->Stride() &&*/ mBase->IsSubType(dec->mBase);
} }
@ -1906,7 +1964,7 @@ bool Declaration::IsSameParams(const Declaration* dec) const
} }
else if (mType == DT_PACK_TYPE && dec->mType == DT_PACK_TYPE) else if (mType == DT_PACK_TYPE && dec->mType == DT_PACK_TYPE)
{ {
Declaration* ld = mBase, * rd = dec->mBase; Declaration* ld = mParams, * rd = dec->mParams;
while (ld && rd) while (ld && rd)
{ {
if (!ld->IsSame(rd)) if (!ld->IsSame(rd))

View File

@ -222,7 +222,8 @@ enum ExpressionType
EX_CONSTRUCT, EX_CONSTRUCT,
EX_CLEANUP, EX_CLEANUP,
EX_RESULT, EX_RESULT,
EX_PACK EX_PACK,
EX_PACK_TYPE,
}; };
class Expression class Expression
@ -247,6 +248,7 @@ public:
bool IsSame(const Expression* exp) const; bool IsSame(const Expression* exp) const;
bool IsRValue(void) const; bool IsRValue(void) const;
bool IsLValue(void) const; bool IsLValue(void) const;
bool IsConstRef(void) const;
void Dump(int ident) const; void Dump(int ident) const;
}; };

View File

@ -557,7 +557,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec)
while (pdec) while (pdec)
{ {
pdec->mVarIndex += vi; pdec->mVarIndex += vi;
if (pdec->mBase->mType == DT_TYPE_REFERENCE && pdec->mBase->mBase->IsSimpleType() && !(pdec->mBase->mFlags & DTF_VAR_ADDRESS) && (pdec->mBase->mBase->mFlags & DTF_CONST)) if (pdec->mBase->mType == DT_TYPE_REFERENCE && pdec->mBase->mBase->IsSimpleType() && !(pdec->mFlags & DTF_VAR_ADDRESS) && (pdec->mBase->mBase->mFlags & DTF_CONST))
{ {
pdec->mBase = pdec->mBase->mBase; pdec->mBase = pdec->mBase->mBase;
pdec->mSize = pdec->mBase->mSize; pdec->mSize = pdec->mBase->mSize;
@ -884,6 +884,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
if (pex->mType == EX_CALL && IsStackParam(pex->mDecType) && !(pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF))) if (pex->mType == EX_CALL && IsStackParam(pex->mDecType) && !(pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF)))
ldec->mBase->mFlags |= DTF_STACKCALL; ldec->mBase->mFlags |= DTF_STACKCALL;
RegisterProc(Analyze(pex, procDec, pdec && pdec->mBase->IsReference()));
if (pdec) if (pdec)
pdec = pdec->mNext; pdec = pdec->mNext;
@ -892,7 +894,6 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
else else
rex = nullptr; rex = nullptr;
} }
RegisterProc(Analyze(exp->mRight, procDec, false));
} }
break; break;
case EX_LIST: case EX_LIST:
@ -901,7 +902,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
case EX_RETURN: case EX_RETURN:
if (exp->mLeft) if (exp->mLeft)
{ {
RegisterProc(Analyze(exp->mLeft, procDec, false)); RegisterProc(Analyze(exp->mLeft, procDec, procDec->mBase->mBase->IsReference()));
if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor) if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor)
{ {
if (procDec->mBase->mBase->mMoveConstructor) if (procDec->mBase->mBase->mMoveConstructor)
@ -1031,8 +1032,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
procDec->mComplexity += exp->mDecType->mSize * 10; procDec->mComplexity += exp->mDecType->mSize * 10;
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, false);
RegisterProc(Analyze(exp->mRight->mLeft, procDec, false)); RegisterProc(Analyze(exp->mRight->mLeft, procDec, lhs));
RegisterProc(Analyze(exp->mRight->mRight, procDec, false)); RegisterProc(Analyze(exp->mRight->mRight, procDec, lhs));
break; break;
} }

View File

@ -3679,6 +3679,34 @@ bool InterInstruction::RemoveUnusedStoreInstructions(const GrowingVariableArray&
} }
} }
} }
else if (mCode == IC_SELECT)
{
if (mDst.mType == IT_POINTER)
{
if (mSrc[1].mTemp < 0)
{
if (mSrc[1].mMemory == IM_LOCAL)
{
requiredVars += mSrc[1].mVarIndex;
}
else if (mSrc[1].mMemory == paramMemory)
{
requiredParams += mSrc[1].mVarIndex;
}
}
if (mSrc[2].mTemp < 0)
{
if (mSrc[2].mMemory == IM_LOCAL)
{
requiredVars += mSrc[2].mVarIndex;
}
else if (mSrc[2].mMemory == paramMemory)
{
requiredParams += mSrc[2].mVarIndex;
}
}
}
}
else if (mCode == IC_CONSTANT) else if (mCode == IC_CONSTANT)
{ {
if (mConst.mType == IT_POINTER) if (mConst.mType == IT_POINTER)
@ -3809,6 +3837,22 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(InterCodeBasicBlock*
} }
} }
} }
else if (mCode == IC_SELECT)
{
if (mDst.mType == IT_POINTER)
{
if (mSrc[1].mTemp < 0)
{
if (mSrc[1].mMemory == IM_GLOBAL && mSrc[1].mVarIndex >= 0)
requiredVars += mSrc[1].mVarIndex;
}
if (mSrc[2].mTemp < 0)
{
if (mSrc[2].mMemory == IM_GLOBAL && mSrc[2].mVarIndex >= 0)
requiredVars += mSrc[2].mVarIndex;
}
}
}
else if (mCode == IC_COPY || mCode == IC_STRCPY) else if (mCode == IC_COPY || mCode == IC_STRCPY)
{ {
requiredVars.Fill(); requiredVars.Fill();
@ -5241,12 +5285,11 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
break; break;
case IC_SELECT: case IC_SELECT:
for(int i=0; i<3; i++) for (int i = 0; i < 3; i++)
{ {
if (ins->mSrc[i].mTemp >= 0 && tvalue[ins->mSrc[i].mTemp] && tvalue[ins->mSrc[i].mTemp]->mCode == IC_CONSTANT) if (ins->mSrc[i].mTemp >= 0 && tvalue[ins->mSrc[i].mTemp] && tvalue[ins->mSrc[i].mTemp]->mCode == IC_CONSTANT && ins->mSrc[i].mType != IT_POINTER)
{ {
ins->mSrc[i] = tvalue[ins->mSrc[i].mTemp]->mConst; ins->mSrc[i] = tvalue[ins->mSrc[i].mTemp]->mConst;
ins->mSrc[i].mType = ins->mDst.mType;
ins->mSrc[i].mTemp = -1; ins->mSrc[i].mTemp = -1;
} }
} }
@ -16376,6 +16419,8 @@ void InterCodeProcedure::ResetVisited(void)
int InterCodeProcedure::AddTemporary(InterType type) int InterCodeProcedure::AddTemporary(InterType type)
{ {
assert(type != IT_NONE);
int temp = mTemporaries.Size(); int temp = mTemporaries.Size();
mTemporaries.Push(type); mTemporaries.Push(type);
return temp; return temp;
@ -17179,7 +17224,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "bv"); CheckFunc = !strcmp(mIdent->mString, "main");
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];

View File

@ -63,6 +63,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure*
ins->mSrc[0].mOperandSize = v.mReference == 1 ? v.mType->mSize : 2; ins->mSrc[0].mOperandSize = v.mReference == 1 ? v.mType->mSize : 2;
ins->mSrc[0].mStride = v.mReference == 1 ? v.mType->mStripe : 1; ins->mSrc[0].mStride = v.mReference == 1 ? v.mType->mStripe : 1;
if (ins->mDst.mType == IT_NONE)
{
mErrors->Error(exp->mLocation, EERR_INVALID_VALUE, "Not a simple type");
return v;
}
if (v.mReference == 1 && v.mType->mType == DT_TYPE_ENUM) if (v.mReference == 1 && v.mType->mType == DT_TYPE_ENUM)
{ {
ins->mDst.mRange.LimitMin(v.mType->mMinValue); ins->mDst.mRange.LimitMin(v.mType->mMinValue);
@ -1641,6 +1647,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
break; break;
case EX_PACK: case EX_PACK:
case EX_PACK_TYPE:
mErrors->Error(exp->mLocation, EERR_INVALID_PACK_USAGE, "Invalid pack usage"); mErrors->Error(exp->mLocation, EERR_INVALID_PACK_USAGE, "Invalid pack usage");
return ExValue(TheVoidTypeDeclaration); return ExValue(TheVoidTypeDeclaration);
@ -2032,7 +2039,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (exp->mToken == TK_ASSIGN || !(vl.mType->mType == DT_TYPE_POINTER && vr.mType->IsIntegerType() && (exp->mToken == TK_ASSIGN_ADD || exp->mToken == TK_ASSIGN_SUB))) if (exp->mToken == TK_ASSIGN || !(vl.mType->mType == DT_TYPE_POINTER && vr.mType->IsIntegerType() && (exp->mToken == TK_ASSIGN_ADD || exp->mToken == TK_ASSIGN_SUB)))
{ {
if (!vl.mType->CanAssign(vr.mType)) if (!vl.mType->CanAssign(vr.mType))
{
vl.mType->CanAssign(vr.mType);
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
}
} }
if (exp->mType != EX_INITIALIZATION && (vl.mType->mFlags & DTF_CONST)) if (exp->mType != EX_INITIALIZATION && (vl.mType->mFlags & DTF_CONST))
@ -3754,10 +3764,19 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
{ {
vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
if (vr.mType->IsReference())
{
vr.mReference++;
vr.mType = vr.mType->mBase;
}
vr = Dereference(proc, exp, block, vr, 1); vr = Dereference(proc, exp, block, vr, 1);
vr = CoerceType(proc, exp, block, vr, procType->mBase); vr = CoerceType(proc, exp, block, vr, procType->mBase);
if (vr.mReference == 0)
mErrors->Error(exp->mLocation, EERR_INVALID_VALUE, "Returning value as reference");
ins->mSrc[0].mType = IT_POINTER; ins->mSrc[0].mType = IT_POINTER;
ins->mSrc[0].mTemp = vr.mTemp; ins->mSrc[0].mTemp = vr.mTemp;
ins->mSrc[0].mMemory = IM_INDIRECT; ins->mSrc[0].mMemory = IM_INDIRECT;
@ -3766,18 +3785,28 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
{ {
if (inlineMapper->mResultExp) if (inlineMapper->mResultExp)
{ {
ins->mSrc[1].mType = IT_POINTER; if (inlineMapper->mResultExp->mType->IsReference())
ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp; {
ins->mSrc[1].mMemory = IM_INDIRECT; ins->mSrc[1].mType = IT_POINTER;
ins->mCode = IC_STORE; ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp;
ins->mSrc[1].mOperandSize = 2; ins->mSrc[1].mMemory = IM_INDIRECT;
ins->mNumOperands = 2; ins->mCode = IC_STORE;
ins->mSrc[1].mOperandSize = 2;
ins->mNumOperands = 2;
}
else
{
//bool moving = exp->mLeft->IsRValue() || exp->mLeft->mType == EX_VARIABLE && !(exp->mLeft->mDecValue->mFlags & (DTF_STATIC | DTF_GLOBAL)) && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE;
CopyStruct(proc, exp, block, *(inlineMapper->mResultExp), vr, inlineMapper, false);
ins->mCode = IC_NONE;
}
} }
else else
{ {
InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT);
ains->mDst.mType = IT_POINTER; ains->mDst.mType = IT_POINTER;
ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
ains->mConst.mType = IT_POINTER; ains->mConst.mType = IT_POINTER;
ains->mConst.mOperandSize = procType->mBase->mSize; ains->mConst.mOperandSize = procType->mBase->mSize;
ains->mConst.mIntConst = 0; ains->mConst.mIntConst = 0;
@ -4007,7 +4036,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
{ {
InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT);
ains->mDst.mType = IT_POINTER; ains->mDst.mType = IT_POINTER;
ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
ains->mConst.mType = IT_POINTER; ains->mConst.mType = IT_POINTER;
ains->mConst.mOperandSize = procType->mBase->mSize; ains->mConst.mOperandSize = procType->mBase->mSize;
ains->mConst.mIntConst = 0; ains->mConst.mIntConst = 0;
@ -4148,14 +4177,24 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
vc = Dereference(proc, exp, block, vc); vc = Dereference(proc, exp, block, vc);
int ttemp; int ttemp, tref = 0;
InterType ttype, stypel, styper; InterType ttype, stypel, styper;
stypel = InterTypeOf(vl.mType); stypel = InterTypeOf(vl.mType);
styper = InterTypeOf(vr.mType); styper = InterTypeOf(vr.mType);
Declaration* dtype; Declaration* dtype = exp->mDecType;
if (stypel == IT_POINTER || styper == IT_POINTER)
if (dtype->IsReference())
{
vl = Dereference(proc, exp, block, vl, 1);
vr = Dereference(proc, exp, block, vr, 1);
tref = 1;
dtype = dtype->mBase;
ttype = IT_POINTER;
}
else if (stypel == IT_POINTER || styper == IT_POINTER)
{ {
if (vl.mType->mType == DT_TYPE_ARRAY) if (vl.mType->mType == DT_TYPE_ARRAY)
vl = Dereference(proc, exp, block, vl, 1); vl = Dereference(proc, exp, block, vl, 1);
@ -4224,7 +4263,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
sins->mDst.mTemp = ttemp; sins->mDst.mTemp = ttemp;
block->Append(sins); block->Append(sins);
return ExValue(dtype, ttemp); return ExValue(dtype, ttemp, tref);
} }
else else
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -91,6 +91,7 @@ protected:
Declaration* ParseQualIdent(void); Declaration* ParseQualIdent(void);
void SkipStatement(void);
Expression* ParseStatement(void); Expression* ParseStatement(void);
Expression* ParseSwitchStatement(void); Expression* ParseSwitchStatement(void);
@ -109,6 +110,7 @@ protected:
void ParseTemplateDeclarationBody(Declaration* tdec, Declaration* pthis); void ParseTemplateDeclarationBody(Declaration* tdec, Declaration* pthis);
Declaration* FunctionAutoParamsToTemplate(Declaration* fdec); Declaration* FunctionAutoParamsToTemplate(Declaration* fdec);
int ExpansionDistance(Declaration* tdec, Declaration* spec);
Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd);
void CompleteTemplateExpansion(Declaration* tmpld); void CompleteTemplateExpansion(Declaration* tmpld);

View File

@ -148,6 +148,7 @@ const char* TokenNames[] =
"'#repeat'", "'#repeat'",
"'#until'", "'#until'",
"'#embed'", "'#embed'",
"'#for'",
"'##'", "'##'",
"'namespace'", "'namespace'",
@ -596,6 +597,84 @@ void Scanner::NextPreToken(void)
mPreprocessor->CloseSource(); mPreprocessor->CloseSource();
} }
} }
else if (mToken == TK_PREP_FOR)
{
NextRawToken();
if (mToken == TK_OPEN_PARENTHESIS)
{
NextRawToken();
Macro* macro = new Macro(Ident::Unique("@for"), nullptr);
if (mToken == TK_IDENT)
{
const Ident* loopindex = mTokenIdent;
NextRawToken();
if (mToken == TK_COMMA)
{
mPreprocessorMode = true;
NextToken();
int64 loopCount = PrepParseConditional();
mPreprocessorMode = false;
if (mToken == TK_CLOSE_PARENTHESIS)
{
int slen = mOffset;
bool quote = false;
while (mLine[slen] && (quote || mLine[slen] != '/' || mLine[slen + 1] != '/'))
{
if (mLine[slen] == '"')
quote = !quote;
slen++;
}
macro->SetString(mLine + mOffset, slen - mOffset);
mOffset = slen;
while (mLine[mOffset])
mOffset++;
if (loopCount > 0)
{
MacroExpansion* ex = new MacroExpansion();
MacroDict* scope = mDefineArguments;
mDefineArguments = new MacroDict();
Macro* arg = new Macro(loopindex, scope);
mDefineArguments->Insert(arg);
arg->SetString("0");
ex->mLine = mLine;
ex->mOffset = mOffset;
ex->mLink = mMacroExpansion;
ex->mChar = mTokenChar;
ex->mLoopCount = 0;
ex->mLoopIndex = arg;
ex->mLoopLimit = loopCount;
mMacroExpansion = ex;
mMacroExpansionDepth++;
if (mMacroExpansionDepth > 1024)
mErrors->Error(mLocation, EFATAL_MACRO_EXPANSION_DEPTH, "Maximum macro expansion depth exceeded", mTokenIdent);
mLine = macro->mString;
mOffset = 0;
NextChar();
}
}
else
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "')' expected in defined parameter list");
}
else
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "',' expected");
}
else
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "'loop index variable expected");
}
else
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "'('(' expected");
}
else if (mToken == TK_PREP_DEFINE) else if (mToken == TK_PREP_DEFINE)
{ {
NextRawToken(); NextRawToken();
@ -1313,6 +1392,8 @@ void Scanner::NextRawToken(void)
mToken = TK_PREP_UNTIL; mToken = TK_PREP_UNTIL;
else if (!strcmp(tkprep, "embed")) else if (!strcmp(tkprep, "embed"))
mToken = TK_PREP_EMBED; mToken = TK_PREP_EMBED;
else if (!strcmp(tkprep, "for"))
mToken = TK_PREP_FOR;
else else
mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "Invalid preprocessor command", tkprep); mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "Invalid preprocessor command", tkprep);
} }
@ -1912,6 +1993,19 @@ bool Scanner::NextChar(void)
{ {
if (mMacroExpansion) if (mMacroExpansion)
{ {
if (mMacroExpansion->mLoopIndex)
{
mMacroExpansion->mLoopCount++;
if (mMacroExpansion->mLoopCount < mMacroExpansion->mLoopLimit)
{
char buffer[20];
sprintf_s(buffer, "%d", int(mMacroExpansion->mLoopCount));
mMacroExpansion->mLoopIndex->SetString(buffer);
mOffset = 0;
continue;
}
}
MacroExpansion* mac = mMacroExpansion->mLink; MacroExpansion* mac = mMacroExpansion->mLink;
// delete mDefineArguments; // delete mDefineArguments;

View File

@ -146,6 +146,7 @@ enum Token
TK_PREP_REPEAT, TK_PREP_REPEAT,
TK_PREP_UNTIL, TK_PREP_UNTIL,
TK_PREP_EMBED, TK_PREP_EMBED,
TK_PREP_FOR,
TK_PREP_CONCAT, TK_PREP_CONCAT,
@ -284,7 +285,14 @@ protected:
const char * mLine; const char * mLine;
int mOffset; int mOffset;
char mChar; char mChar;
Macro * mLoopIndex;
int64 mLoopCount, mLoopLimit;
MacroDict* mDefinedArguments; MacroDict* mDefinedArguments;
MacroExpansion(void)
: mLink(nullptr), mLine(nullptr), mOffset(0), mChar(0), mLoopIndex(nullptr), mLoopCount(0), mLoopLimit(0), mDefinedArguments(nullptr)
{}
} * mMacroExpansion; } * mMacroExpansion;
int mMacroExpansionDepth; int mMacroExpansionDepth;