Add autotest for string stream

This commit is contained in:
drmortalwombat 2023-07-23 11:19:26 +02:00
parent fbde581475
commit 9b2d90ec58
9 changed files with 227 additions and 24 deletions

View File

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

View File

@ -0,0 +1,81 @@
#include <opp/string.h>
#include <stdlib.h>
#include <assert.h>
#include <opp/sstream.h>
#include <math.h>
float fdist(float a, float b)
{
float d = fabs(a - b);
a = fabs(a);
b = fabs(b);
return d / (a > b ? a : b);
}
int main(void)
{
ostringstream os;
for(int i=0; i<40; i++)
{
os << i << endl;
}
costream cout;
istringstream is(os.str());
int j = 0, k = 47;
#if 1
while (is >> k)
{
assert(k == j++);
}
assert(j == 40);
#endif
os.str(string());
#if 0
cout << "[" << os.str() << "]" << endl;
os << "HELLO";
cout << "[" << os.str() << "]" << endl;
#endif
#if 1
float f = 1.0, g = 1.0;
for(int i=0; i<10; i++)
{
os << f << " " << g << endl;
// cout << os.str();
f *= 5.1;
g *= 0.12;
}
is.str(os.str());
f = 1.0, g = 1.0;
float fr, gr;
j = 0;
while (is >> fr >> gr)
{
// cout << f << " " << fr << ", " << g << " " << gr << ", " << fdist(fr, f) << endl;
assert(fdist(fr, f) < 1.0e-5);
assert(fdist(gr, g) < 1.0e-5);
f *= 5.1;
g *= 0.12;
j++;
}
assert(j == 10);
#endif
return 0;
}

View File

@ -6,7 +6,7 @@ ios::ios(void)
: mFlags(0), mState(0), mWidth(0), mPrecision(6), mFill(' ')
{}
ios::~ios(void)
inline ios::~ios(void)
{
}
@ -177,7 +177,7 @@ ostream & operator<<(ostream & os, const iosetfill & s)
return os;
}
ostream::ostream(void)
inline ostream::ostream(void)
{}
@ -545,7 +545,7 @@ ostream & ostream::operator<<(const string & s)
return *this;
}
ostream & ostream::operator<<(manip m)
inline ostream & ostream::operator<<(manip m)
{
return m(*this);
}
@ -711,6 +711,8 @@ unsigned istream::getnum(void)
else if (ch == '+')
ch = get();
bool digits = false;
if (ch == '0')
{
if (bflags == 0)
@ -722,10 +724,13 @@ unsigned istream::getnum(void)
base = 16;
ch = get();
}
else
digits = true;
}
else
digits = true;
}
bool digits = false;
for(;;)
{
if (ch >= '0' && ch <= '9')

View File

@ -16,9 +16,9 @@ void ostringstream::bput(char ch)
{
if (!mBuffer)
{
mBSize = 16;
mBSize = 15;
mBFill = 0;
mBuffer = malloc(16);
mBuffer = malloc(15);
}
else if (mBFill == mBSize)
{
@ -63,6 +63,7 @@ string istringstream::str(void) const
void istringstream::str(const string & str)
{
mState = goodbit;
mString = str;
mSPos = 0;
}

View File

@ -3271,7 +3271,7 @@ ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const
cins.mRegisterFinal = ins->mSrc[1].mFinal;
mIns.Push(cins);
}
else if (ins->mSrc[0].mType == IT_INT8)
else if (ins->mSrc[0].mType == IT_INT8 || ins->mSrc[0].mType == IT_BOOL)
{
if (ins->mSrc[1].mTemp < 0)
{

View File

@ -28,7 +28,10 @@ static bool IsIntegerType(InterType type)
IntegerValueRange::IntegerValueRange(void)
: mMinState(S_UNKNOWN), mMaxState(S_UNKNOWN)
{}
{
mMinExpanded = 0;
mMaxExpanded = 0;
}
IntegerValueRange::~IntegerValueRange(void)
{}
@ -37,6 +40,8 @@ void IntegerValueRange::Reset(void)
{
mMinState = S_UNKNOWN;
mMaxState = S_UNKNOWN;
mMinExpanded = 0;
mMaxExpanded = 0;
}
@ -126,6 +131,34 @@ void IntegerValueRange::SetLimit(int64 minValue, int64 maxValue)
mMaxValue = maxValue;
}
void IntegerValueRange::Expand(const IntegerValueRange& range)
{
if (range.mMinState == S_BOUND && mMinState == S_BOUND && range.mMinValue < mMinValue)
{
mMinValue = range.mMinValue;
mMinExpanded++;
if (mMinExpanded >= 32)
mMinState = S_UNBOUND;
}
else
{
mMinState = range.mMinState;
mMinValue = range.mMinValue;
}
if (range.mMaxState == S_BOUND && mMaxState == S_BOUND && range.mMaxValue > mMaxValue)
{
mMaxValue = range.mMaxValue;
mMaxExpanded++;
if (mMaxExpanded >= 32)
mMaxState = S_UNBOUND;
}
else
{
mMaxState = range.mMaxState;
mMaxValue = range.mMaxValue;
}
}
bool IntegerValueRange::Merge(const IntegerValueRange& range, bool head, bool initial)
{
bool changed = false;
@ -4211,7 +4244,7 @@ void InterOperand::Disassemble(FILE* file)
}
}
void InterInstruction::Disassemble(FILE* file)
void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc)
{
if (this->mCode != IC_NONE)
{
@ -4352,8 +4385,20 @@ void InterInstruction::Disassemble(FILE* file)
if (this->mCode == IC_CONSTANT)
{
if (mDst.mType == IT_POINTER)
{
fprintf(file, "C%c%d(%d:%d)", memchars[mConst.mMemory], mConst.mOperandSize, mConst.mVarIndex, int(mConst.mIntConst));
{
const char* vname = "";
if (mConst.mMemory == IM_LOCAL)
{
if (!proc->mLocalVars[mConst.mVarIndex])
vname = "null";
else if (!proc->mLocalVars[mConst.mVarIndex]->mIdent)
vname = "";
else
vname = proc->mLocalVars[mConst.mVarIndex]->mIdent->mString;
}
fprintf(file, "C%c%d(%d:%d '%s')", memchars[mConst.mMemory], mConst.mOperandSize, mConst.mVarIndex, int(mConst.mIntConst), vname);
}
else if (mDst.mType == IT_FLOAT)
fprintf(file, "CF:%f", mConst.mFloatConst);
@ -4566,7 +4611,7 @@ void InterCodeBasicBlock::GenerateTraces(bool expand, bool compact)
mInPath = true;
// Limit number of contractions
for (int i=0; i<100; i++)
for (int i = 0; i < 100; i++)
{
if (mTrueJump && mTrueJump->mInstructions.Size() == 1 && mTrueJump->mInstructions[0]->mCode == IC_JUMP && !mTrueJump->mLoopHead && mTrueJump->mTraceIndex != mIndex)
{
@ -4610,6 +4655,27 @@ void InterCodeBasicBlock::GenerateTraces(bool expand, bool compact)
if (mFalseJump)
mFalseJump->mNumEntries++;
}
else if (
compact &&
mFalseJump &&
mInstructions.Size() > 0 &&
mInstructions.Last()->mCode == IC_BRANCH &&
mInstructions.Last()->mSrc[0].mTemp < 0)
{
int ns = mInstructions.Size();
if (mInstructions.Last()->mSrc[0].mIntConst)
mFalseJump->mNumEntries--;
else
{
mTrueJump->mNumEntries--;
mTrueJump = mFalseJump;
}
mFalseJump = nullptr;
mInstructions[ns - 1]->mCode = IC_JUMP;
mInstructions[ns - 1]->mNumOperands = 0;
}
else if (mTrueJump && !mFalseJump && ((expand && mTrueJump->mInstructions.Size() < 10 && mTrueJump->mInstructions.Size() > 1 && !mLoopHead) || mTrueJump->mNumEntries == 1) && !mTrueJump->mLoopHead && !IsInfiniteLoop(mTrueJump, mTrueJump))
{
mTrueJump->mNumEntries--;
@ -5462,6 +5528,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
if (ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT)
{
ins->mSrc[0].mIntConst = tvalue[ins->mSrc[0].mTemp]->mConst.mIntConst;
ins->mSrc[0].mMemory = tvalue[ins->mSrc[0].mTemp]->mConst.mMemory;
ins->mSrc[0].mTemp = -1;
}
break;
@ -5900,7 +5967,11 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void)
constFalse = true;
break;
case IA_CMPLU:
if (cins->mSrc[1].IsUnsigned() && cins->mSrc[0].IsUnsigned())
if (cins->mSrc[0].mTemp < 0 && cins->mSrc[0].mIntConst == 0)
{
constFalse = true;
}
else if (cins->mSrc[1].IsUnsigned() && cins->mSrc[0].IsUnsigned())
{
if (cins->mSrc[1].mRange.mMaxValue < cins->mSrc[0].mRange.mMinValue)
constTrue = true;
@ -5930,7 +6001,11 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void)
constFalse = true;
break;
case IA_CMPGU:
if (cins->mSrc[1].IsUnsigned() && cins->mSrc[0].IsUnsigned())
if (cins->mSrc[1].mTemp < 0 && cins->mSrc[1].mIntConst == 0)
{
constFalse = true;
}
else if (cins->mSrc[1].IsUnsigned() && cins->mSrc[0].IsUnsigned())
{
if (cins->mSrc[1].mRange.mMinValue > cins->mSrc[0].mRange.mMaxValue)
constTrue = true;
@ -6187,8 +6262,15 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(bool initial, const Growin
if (changed)
{
mEntryValueRange = mLocalValueRange;
mEntryParamValueRange = mLocalParamValueRange;
for (int i = 0; i < mLocalValueRange.Size(); i++)
mEntryValueRange[i].Expand(mLocalValueRange[i]);
for (int i = 0; i < mLocalParamValueRange.Size(); i++)
mEntryParamValueRange[i].Expand(mLocalParamValueRange[i]);
mLocalValueRange = mEntryValueRange;
mLocalParamValueRange = mEntryParamValueRange;
// mEntryValueRange = mLocalValueRange;
// mEntryParamValueRange = mLocalParamValueRange;
UpdateLocalIntegerRangeSets(localVars, paramVars);
@ -15267,7 +15349,11 @@ void InterCodeBasicBlock::Disassemble(FILE* file, bool dumpSets)
const char* s = mLoopHead ? "Head" : "";
fprintf(file, "L%d: <= D%d: (%d) %s P%d\n", mIndex, (mDominator ? mDominator->mIndex : -1), mNumEntries, s, (mLoopPrefix ? mLoopPrefix->mIndex : -1));
fprintf(file, "L%d: <= D%d: (%d) %s P%d", mIndex, (mDominator ? mDominator->mIndex : -1), mNumEntries, s, (mLoopPrefix ? mLoopPrefix->mIndex : -1));
if (mInstructions.Size())
fprintf(file, "%s\n", mInstructions[0]->mLocation.mFileName);
else
fprintf(file, "\n");
if (dumpSets)
{
@ -15295,8 +15381,8 @@ void InterCodeBasicBlock::Disassemble(FILE* file, bool dumpSets)
{
if (mInstructions[i]->mCode != IC_NONE)
{
fprintf(file, "%04x\t", i);
mInstructions[i]->Disassemble(file);
fprintf(file, "%04x (%4d)\t", i, mInstructions[i]->mLocation.mLine);
mInstructions[i]->Disassemble(file, mProc);
}
}
@ -16176,7 +16262,7 @@ void InterCodeProcedure::Close(void)
{
GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "string::find");
CheckFunc = !strcmp(mIdent->mString, "main");
mEntryBlock = mBlocks[0];
@ -16274,9 +16360,11 @@ void InterCodeProcedure::Close(void)
ResetVisited();
mEntryBlock->PerformMachineSpecificValueUsageCheck(mValueForwardingTable, tvalidSet, mModule->mGlobalVars, fsingleSet);
DisassembleDebug("machine value forwarding");
GlobalConstantPropagation();
DisassembleDebug("machine value forwarding");
DisassembleDebug("Global Constant Propagation");
//
// Now remove needless temporary moves, that appear due to

View File

@ -150,6 +150,7 @@ public:
void Reset(void);
int64 mMinValue, mMaxValue;
int mMinExpanded, mMaxExpanded;
enum State
{
@ -161,6 +162,7 @@ public:
bool Same(const IntegerValueRange& range) const;
bool Merge(const IntegerValueRange& range, bool head, bool initial);
void Expand(const IntegerValueRange& range);
void Limit(const IntegerValueRange& range);
void SetLimit(int64 minValue, int64 maxValue);
@ -341,7 +343,7 @@ public:
bool ConstantFolding(void);
bool ConstantFoldingRelationRange(void);
void Disassemble(FILE* file);
void Disassemble(FILE* file, InterCodeProcedure * proc);
};
class InterCodeBasicBlock

View File

@ -321,7 +321,13 @@ void InterCodeGenerator::InitLocalVariable(InterCodeProcedure* proc, Declaration
proc->mLocalVars[index]->mIdent = dec->mIdent;
proc->mLocalVars[index]->mDeclaration = dec;
}
else
{
assert(proc->mLocalVars[index]->mIdent == dec->mIdent);
assert(proc->mLocalVars[index]->mDeclaration == dec);
}
}
static const Ident* StructIdent(const Ident* base, const Ident* item)
{
if (base)
@ -1063,7 +1069,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro
}
}
vl = TranslateExpression(ftype, proc, block, fexp, destack, BranchTarget(), BranchTarget(), &nmapper);
DestructStack* idestack = nullptr;
vl = TranslateExpression(ftype, proc, block, fexp, idestack, BranchTarget(), BranchTarget(), &nmapper);
InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP);
block->Append(jins);
@ -1071,7 +1079,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro
block->Close(nmapper.mReturn, nullptr);
block = nmapper.mReturn;
UnwindDestructStack(ftype, proc, block, destack, nullptr, &nmapper);
// Unwind inner destruct stack
UnwindDestructStack(ftype, proc, block, idestack, nullptr, &nmapper);
// Uwind parameter passing stack
UnwindDestructStack(ftype, proc, block, destack, nullptr, inlineMapper);
if (rdec)
{

View File

@ -1706,6 +1706,7 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc)
void Parser::AddDefaultConstructors(Declaration* pthis)
{
bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true;
bool inlineDestructor = true;
bool inlineConstructor = true;
char dname[100];
@ -1750,7 +1751,11 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
while (bcdec)
{
if (bcdec->mBase->mDestructor)
{
if (!(bcdec->mBase->mDestructor->mBase->mFlags & DTF_REQUEST_INLINE))
inlineConstructor = false;
simpleDestructor = false;
}
if (bcdec->mBase->mDefaultConstructor)
{
simpleConstructor = false;
@ -1781,7 +1786,11 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
if (bdec->mType == DT_TYPE_STRUCT)
{
if (bdec->mDestructor)
{
simpleDestructor = false;
if (!(bdec->mDestructor->mBase->mFlags & DTF_REQUEST_INLINE))
inlineDestructor = false;
}
if (bdec->mDefaultConstructor)
{
simpleConstructor = false;
@ -1813,6 +1822,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
cdec->mBase = ctdec;
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
if (inlineDestructor)
cdec->mFlags |= DTF_REQUEST_INLINE;
cdec->mSection = mCodeSection;