diff --git a/autotest/autotest.bat b/autotest/autotest.bat index c18d90d..16355f7 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -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 diff --git a/autotest/opp_streamtest.cpp b/autotest/opp_streamtest.cpp new file mode 100644 index 0000000..1a9bfc5 --- /dev/null +++ b/autotest/opp_streamtest.cpp @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include + +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; +} diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp index 01ad8ef..f069548 100644 --- a/include/opp/iostream.cpp +++ b/include/opp/iostream.cpp @@ -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') diff --git a/include/opp/sstream.cpp b/include/opp/sstream.cpp index ddf06ab..ca0ff9e 100644 --- a/include/opp/sstream.cpp +++ b/include/opp/sstream.cpp @@ -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; } diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index cc72866..5707d8a 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -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) { diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index d1f3d71..85c1f28 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -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 diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index d6ff5ea..72efbf4 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -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 diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index b939d3c..b5df555 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -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) { diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 4ececfa..c4175e0 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -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;