From 9bcec5bf1791c96dc1a138eae6e3b1e1204760ba Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 21 Jun 2023 22:07:00 +0200 Subject: [PATCH 001/169] Destructors when leaving scopes the normal way --- include/c64/memmap.c | 8 +- oscar64/Declaration.cpp | 2 +- oscar64/Declaration.h | 5 +- oscar64/Errors.h | 1 + oscar64/GlobalAnalyzer.cpp | 12 ++ oscar64/InterCodeGenerator.cpp | 213 +++++++++++++++++++++++---------- oscar64/InterCodeGenerator.h | 11 +- oscar64/Parser.cpp | 132 ++++++++++++++++++-- 8 files changed, 305 insertions(+), 79 deletions(-) diff --git a/include/c64/memmap.c b/include/c64/memmap.c index 359a5d0..c2c061f 100644 --- a/include/c64/memmap.c +++ b/include/c64/memmap.c @@ -27,7 +27,7 @@ __asm IRQTrampoline tsx lda $0105, x pha - jmp ($fffa) + jmp ($fffe) } __asm NMITrampoline @@ -45,13 +45,13 @@ __asm NMITrampoline tsx lda $0105, x pha - jmp ($fffe) + jmp ($fffa) } void mmap_trampoline(void) { - *((void **)0xfffa) = IRQTrampoline; - *((void **)0xfffe) = NMITrampoline; + *((void **)0xfffa) = NMITrampoline; + *((void **)0xfffe) = IRQTrampoline; } #pragma native(mmap_trampoline) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index ee4bc30..3f0af85 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -17,7 +17,7 @@ DeclarationScope::~DeclarationScope(void) const Ident* DeclarationScope::Mangle(const Ident* ident) const { - if (mName) + if (mName && ident) { char buffer[200]; strcpy_s(buffer, mName->mString); diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index df00664..418c3fe 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -94,6 +94,7 @@ static const uint64 DTF_FPARAM_NOCONST = (1ULL << 41); static const uint64 DTF_FUNC_THIS = (1ULL << 42); static const uint64 DTF_FUNC_CONSTRUCTOR = (1ULL << 43); +static const uint64 DTF_FUNC_DESTRUCTOR = (1ULL << 44); static const uint64 DTF_VAR_ALIASING = (1ULL << 48); @@ -167,6 +168,7 @@ enum ExpressionType EX_ELSE, EX_FOR, EX_DO, + EX_SCOPE, EX_BREAK, EX_CONTINUE, EX_TYPE, @@ -181,7 +183,8 @@ enum ExpressionType EX_DEFAULT, EX_CONDITIONAL, EX_ASSUME, - EX_BANKOF + EX_BANKOF, + EX_CONSTRUCT }; class Expression diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 8e157ab..1e2333c 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -28,6 +28,7 @@ enum ErrorID EWARN_MISSING_RETURN_STATEMENT, EWARN_UNREACHABLE_CODE, EWARN_NULL_POINTER_DEREFERENCED, + EWARN_DESTRUCTOR_MISMATCH, EERR_GENERIC = 3000, EERR_FILE_NOT_FOUND, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index b51e40a..d944a59 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -744,6 +744,18 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo exp = exp->mRight; } while (exp); break; + + case EX_SCOPE: + Analyze(exp->mLeft, procDec, false); + break; + + case EX_CONSTRUCT: + if (exp->mLeft->mLeft) + Analyze(exp->mLeft->mLeft, procDec, false); + if (exp->mLeft->mRight) + Analyze(exp->mLeft->mRight, procDec, false); + return Analyze(exp->mRight, procDec, false); + case EX_WHILE: procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 70418cd..7f04894 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -856,8 +856,27 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e } } +void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack* bottom) +{ + while (stack && stack != bottom) + { + if (stack->mDestruct) + { + DestructStack* destack = nullptr; + TranslateExpression(procType, proc, block, stack->mDestruct, destack, nullptr, nullptr, nullptr); + } + + stack = stack->mNext; + } + + if (stack != bottom) + mErrors->Error(proc->mLocation, EWARN_DESTRUCTOR_MISMATCH, "Destructor sequence mismatch"); +} + InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr) { + DestructStack* destack = nullptr; + ExValue vl, vr; Declaration* fdec = exp->mLeft->mDecValue; @@ -922,7 +941,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro ExValue vp(pdec ? pdec->mBase : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); - vr = TranslateExpression(procType, proc, block, texp, breakBlock, continueBlock, inlineMapper, &vp); + vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, &vp); if (!(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) { @@ -1014,7 +1033,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro rdec->mSize = rdec->mBase->mSize; } - vl = TranslateExpression(ftype, proc, block, fexp, nullptr, nullptr, &nmapper); + vl = TranslateExpression(ftype, proc, block, fexp, destack, nullptr, nullptr, &nmapper); InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); block->Append(jins); @@ -1040,7 +1059,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro return ExValue(TheVoidTypeDeclaration); } -InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, ExValue* lrexp) +InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, ExValue* lrexp) { Declaration* dec; ExValue vl, vr; @@ -1054,11 +1073,27 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_SEQUENCE: case EX_LIST: - vr = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); exp = exp->mRight; if (!exp) return ExValue(TheVoidTypeDeclaration); break; + case EX_CONSTRUCT: + { + if (exp->mLeft->mLeft) + TranslateExpression(procType, proc, block, exp->mLeft->mLeft, destack, breakBlock, continueBlock, inlineMapper); + + if (exp->mLeft->mRight) + { + DestructStack* de = new DestructStack(); + de->mNext = destack; + de->mDestruct = exp->mLeft->mRight; + destack = de; + } + + exp = exp->mRight; + } + break; case EX_CONSTANT: dec = exp->mDecValue; switch (dec->mType) @@ -1182,7 +1217,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case DT_CONST_POINTER: { - vl = TranslateExpression(procType, proc, block, dec->mValue, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, dec->mValue, destack, breakBlock, continueBlock, inlineMapper); vl.mReference--; vl.mType = exp->mDecType; return vl; @@ -1341,19 +1376,19 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { if (exp->mLeft->mDecType && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT) { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); - vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper, &vl); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper, &vl); } else if (exp->mType == EX_INITIALIZATION && exp->mLeft->mDecType && exp->mLeft->mDecType->mType == DT_TYPE_REFERENCE) { - vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl.mType = exp->mLeft->mDecType; } else { - vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); } if (exp->mToken == TK_ASSIGN || !(vl.mType->mType == DT_TYPE_POINTER && vr.mType->IsIntegerType() && (exp->mToken == TK_ASSIGN_ADD || exp->mToken == TK_ASSIGN_SUB))) @@ -1600,8 +1635,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_INDEX: { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); - vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); int stride = vl.mType->Stride(); @@ -1657,7 +1692,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_QUALIFY: { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = Dereference(proc, exp, block, vl, 1); if (vl.mReference != 1) @@ -1684,8 +1719,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_BINARY: { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); - vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); vr = Dereference(proc, exp, block, vr); InterInstruction * ins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); @@ -1981,7 +2016,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_PREINCDEC: { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = Dereference(proc, exp, block, vl, 1); if (vl.mReference != 1) @@ -2042,7 +2077,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_POSTINCDEC: { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = Dereference(proc, exp, block, vl, 1); if (vl.mReference != 1) @@ -2101,7 +2136,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_PREFIX: { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); InterInstruction * ins = new InterInstruction(exp->mLocation, IC_UNARY_OPERATOR); @@ -2182,9 +2217,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_RELATIONAL: { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = Dereference(proc, exp, block, vl, vl.mType->mType == DT_TYPE_ARRAY ? 1 : 0); - vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); vr = Dereference(proc, exp, block, vr, vr.mType->mType == DT_TYPE_ARRAY ? 1 : 0); InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); @@ -2287,7 +2322,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!strcmp(iname->mString, "fabs")) { - vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); vr = Dereference(proc, exp, block, vr); if (decf->mBase->mParams->CanAssign(vr.mType)) @@ -2306,7 +2341,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else if (!strcmp(iname->mString, "floor")) { - vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); vr = Dereference(proc, exp, block, vr); if (decf->mBase->mParams->CanAssign(vr.mType)) @@ -2325,7 +2360,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else if (!strcmp(iname->mString, "ceil")) { - vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); vr = Dereference(proc, exp, block, vr); if (decf->mBase->mParams->CanAssign(vr.mType)) @@ -2350,13 +2385,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if ((tex->mDecType->mType == DT_TYPE_ARRAY && tex->mDecType->mSize <= 256) || (sex->mDecType->mType == DT_TYPE_ARRAY && sex->mDecType->mSize <= 256)) { - vl = TranslateExpression(procType, proc, block, tex, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, tex, destack, breakBlock, continueBlock, inlineMapper); if (vl.mType->mType == DT_TYPE_ARRAY) vl = Dereference(proc, exp, block, vl, 1); else vl = Dereference(proc, exp, block, vl); - vr = TranslateExpression(procType, proc, block, sex, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, sex, destack, breakBlock, continueBlock, inlineMapper); if (vr.mType->mType == DT_TYPE_ARRAY) vr = Dereference(proc, exp, block, vr, 1); else @@ -2387,13 +2422,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* Expression* tex = exp->mRight->mLeft, * sex = exp->mRight->mRight->mLeft, * nex = exp->mRight->mRight->mRight; if (nex && nex->mType == EX_CONSTANT && nex->mDecValue->mType == DT_CONST_INTEGER && nex->mDecValue->mInteger < 512) { - vl = TranslateExpression(procType, proc, block, tex, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, tex, destack, breakBlock, continueBlock, inlineMapper); if (vl.mType->mType == DT_TYPE_ARRAY) vl = Dereference(proc, exp, block, vl, 1); else vl = Dereference(proc, exp, block, vl); - vr = TranslateExpression(procType, proc, block, sex, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, sex, destack, breakBlock, continueBlock, inlineMapper); if (vr.mType->mType == DT_TYPE_ARRAY) vr = Dereference(proc, exp, block, vr, 1); else @@ -2478,7 +2513,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = Dereference(proc, exp, block, vl); int atotal = 0; @@ -2623,7 +2658,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ExValue vp(pdec ? pdec->mBase : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); - vr = TranslateExpression(procType, proc, block, texp, breakBlock, continueBlock, inlineMapper, &vp); + vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, &vp); if (!(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) { @@ -2879,7 +2914,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RETURN); if (exp->mLeft) { - vr = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); if (procType->mBase->mType == DT_TYPE_REFERENCE) { @@ -3090,7 +3125,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterCodeBasicBlock* tblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* fblock = new InterCodeBasicBlock(proc); - TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, inlineMapper); + TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, destack, inlineMapper); InterInstruction* ins = new InterInstruction(exp->mLocation, IC_UNREACHABLE); fblock->Append(ins); @@ -3102,7 +3137,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } case EX_LOGICAL_NOT: { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = Dereference(proc, exp, block, vl); InterInstruction * zins = new InterInstruction(exp->mLocation, IC_CONSTANT); @@ -3129,10 +3164,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* #if 1 if (!exp->mRight->mLeft->HasSideEffects() && !exp->mRight->mRight->HasSideEffects()) { - ExValue vc = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + ExValue vc = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - vl = TranslateExpression(procType, proc, block, exp->mRight->mLeft, breakBlock, continueBlock, inlineMapper); - vr = TranslateExpression(procType, proc, block, exp->mRight->mRight, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mRight->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight->mRight, destack, breakBlock, continueBlock, inlineMapper); vc = Dereference(proc, exp, block, vc); @@ -3224,10 +3259,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterCodeBasicBlock* fblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* eblock = new InterCodeBasicBlock(proc); - TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, inlineMapper); + TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, destack, inlineMapper); - vl = TranslateExpression(procType, proc, tblock, exp->mRight->mLeft, breakBlock, continueBlock, inlineMapper); - vr = TranslateExpression(procType, proc, fblock, exp->mRight->mRight, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, tblock, exp->mRight->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, fblock, exp->mRight->mRight, destack, breakBlock, continueBlock, inlineMapper); int ttemp; InterType ttype, stypel, styper; @@ -3322,7 +3357,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_TYPECAST: { - vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); @@ -3431,7 +3466,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterCodeBasicBlock* fblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* eblock = new InterCodeBasicBlock(proc); - TranslateLogic(procType, proc, block, tblock, fblock, exp, inlineMapper); + TranslateLogic(procType, proc, block, tblock, fblock, exp, destack, inlineMapper); int ttemp = proc->AddTemporary(IT_BOOL); @@ -3459,8 +3494,23 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } break; + case EX_SCOPE: + { + DestructStack* odestack = destack; + + TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + + UnwindDestructStack(procType, proc, block, destack, odestack); + destack = odestack; + + return ExValue(TheVoidTypeDeclaration); + + } break; + case EX_WHILE: { + DestructStack* odestack = destack; + InterInstruction * jins0 = new InterInstruction(exp->mLocation, IC_JUMP); InterInstruction* jins1 = new InterInstruction(exp->mLocation, IC_JUMP); @@ -3472,19 +3522,30 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block->Append(jins0); block->Close(cblock, nullptr); - TranslateLogic(procType, proc, cblock, bblock, eblock, exp->mLeft, inlineMapper); + TranslateLogic(procType, proc, cblock, bblock, eblock, exp->mLeft, destack, inlineMapper); + + DestructStack* idestack = destack; + + vr = TranslateExpression(procType, proc, bblock, exp->mRight, destack, eblock, lblock, inlineMapper); + + UnwindDestructStack(procType, proc, bblock, destack, idestack); + destack = idestack; - vr = TranslateExpression(procType, proc, bblock, exp->mRight, eblock, lblock, inlineMapper); bblock->Append(jins1); bblock->Close(lblock, nullptr); block = eblock; + UnwindDestructStack(procType, proc, block, destack, odestack); + destack = odestack; + return ExValue(TheVoidTypeDeclaration); } case EX_IF: { + DestructStack* odestack = destack; + InterInstruction * jins0 = new InterInstruction(exp->mLocation, IC_JUMP); InterInstruction* jins1 = new InterInstruction(exp->mLocation, IC_JUMP); @@ -3492,27 +3553,41 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterCodeBasicBlock* fblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* eblock = new InterCodeBasicBlock(proc); - TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, inlineMapper); + TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, destack, inlineMapper); + + DestructStack* itdestack = destack; + vr = TranslateExpression(procType, proc, tblock, exp->mRight->mLeft, destack, breakBlock, continueBlock, inlineMapper); + UnwindDestructStack(procType, proc, tblock, destack, itdestack); + destack = itdestack; - vr = TranslateExpression(procType, proc, tblock, exp->mRight->mLeft, breakBlock, continueBlock, inlineMapper); tblock->Append(jins0); tblock->Close(eblock, nullptr); if (exp->mRight->mRight) - vr = TranslateExpression(procType, proc, fblock, exp->mRight->mRight, breakBlock, continueBlock, inlineMapper); + { + DestructStack* ifdestack = destack; + vr = TranslateExpression(procType, proc, fblock, exp->mRight->mRight, destack, breakBlock, continueBlock, inlineMapper); + UnwindDestructStack(procType, proc, fblock, destack, ifdestack); + destack = ifdestack; + } fblock->Append(jins1); fblock->Close(eblock, nullptr); block = eblock; + UnwindDestructStack(procType, proc, block, destack, odestack); + destack = odestack; + return ExValue(TheVoidTypeDeclaration); } case EX_FOR: { + DestructStack* odestack = destack; + // assignment if (exp->mLeft->mRight) - TranslateExpression(procType, proc, block, exp->mLeft->mRight, breakBlock, continueBlock, inlineMapper); + TranslateExpression(procType, proc, block, exp->mLeft->mRight, destack, breakBlock, continueBlock, inlineMapper); InterInstruction* jins0 = new InterInstruction(exp->mLocation, IC_JUMP); InterInstruction* jins1 = new InterInstruction(exp->mLocation, IC_JUMP); @@ -3530,27 +3605,37 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* // condition if (exp->mLeft->mLeft->mLeft) - TranslateLogic(procType, proc, cblock, bblock, eblock, exp->mLeft->mLeft->mLeft, inlineMapper); + TranslateLogic(procType, proc, cblock, bblock, eblock, exp->mLeft->mLeft->mLeft, destack, inlineMapper); else { cblock->Append(jins1); cblock->Close(bblock, nullptr); } - vr = TranslateExpression(procType, proc, bblock, exp->mRight, eblock, iblock, inlineMapper); + // Body + + DestructStack* idestack = destack; + + vr = TranslateExpression(procType, proc, bblock, exp->mRight, destack, eblock, iblock, inlineMapper); + + UnwindDestructStack(procType, proc, bblock, destack, idestack); + destack = idestack; bblock->Append(jins2); bblock->Close(iblock, nullptr); // increment if (exp->mLeft->mLeft->mRight) - TranslateExpression(procType, proc, iblock, exp->mLeft->mLeft->mRight, breakBlock, continueBlock, inlineMapper); + TranslateExpression(procType, proc, iblock, exp->mLeft->mLeft->mRight, destack, breakBlock, continueBlock, inlineMapper); iblock->Append(jins3); iblock->Close(lblock, nullptr); block = eblock; + UnwindDestructStack(procType, proc, block, destack, odestack); + destack = odestack; + return ExValue(TheVoidTypeDeclaration); } @@ -3565,9 +3650,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block->Append(jins); block->Close(cblock, nullptr); - vr = TranslateExpression(procType, proc, cblock, exp->mRight, eblock, cblock, inlineMapper); + vr = TranslateExpression(procType, proc, cblock, exp->mRight, destack, eblock, cblock, inlineMapper); - TranslateLogic(procType, proc, cblock, lblock, eblock, exp->mLeft, inlineMapper); + TranslateLogic(procType, proc, cblock, lblock, eblock, exp->mLeft, destack, inlineMapper); block = eblock; @@ -3576,7 +3661,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_SWITCH: { - vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = Dereference(proc, exp, block, vl); vl = CoerceType(proc, exp, block, vl, TheSignedIntTypeDeclaration); @@ -3645,7 +3730,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } if (cexp->mRight) - TranslateExpression(procType, proc, block, cexp->mRight, eblock, continueBlock, inlineMapper); + TranslateExpression(procType, proc, block, cexp->mRight, destack, eblock, continueBlock, inlineMapper); sexp = sexp->mRight; } @@ -3809,30 +3894,30 @@ void InterCodeGenerator::BuildInitializer(InterCodeModule * mod, uint8* dp, int } } -void InterCodeGenerator::TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, InlineMapper* inlineMapper) +void InterCodeGenerator::TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper) { switch (exp->mType) { case EX_LOGICAL_NOT: - TranslateLogic(procType, proc, block, fblock, tblock, exp->mLeft, inlineMapper); + TranslateLogic(procType, proc, block, fblock, tblock, exp->mLeft, destack, inlineMapper); break; case EX_LOGICAL_AND: { InterCodeBasicBlock* ablock = new InterCodeBasicBlock(proc); - TranslateLogic(procType, proc, block, ablock, fblock, exp->mLeft, inlineMapper); - TranslateLogic(procType, proc, ablock, tblock, fblock, exp->mRight, inlineMapper); + TranslateLogic(procType, proc, block, ablock, fblock, exp->mLeft, destack, inlineMapper); + TranslateLogic(procType, proc, ablock, tblock, fblock, exp->mRight, destack, inlineMapper); break; } case EX_LOGICAL_OR: { InterCodeBasicBlock* oblock = new InterCodeBasicBlock(proc); - TranslateLogic(procType, proc, block, tblock, oblock, exp->mLeft, inlineMapper); - TranslateLogic(procType, proc, oblock, tblock, fblock, exp->mRight, inlineMapper); + TranslateLogic(procType, proc, block, tblock, oblock, exp->mLeft, destack, inlineMapper); + TranslateLogic(procType, proc, oblock, tblock, fblock, exp->mRight, destack, inlineMapper); break; } default: { - ExValue vr = TranslateExpression(procType, proc, block, exp, nullptr, nullptr, inlineMapper); + ExValue vr = TranslateExpression(procType, proc, block, exp, destack, nullptr, nullptr, inlineMapper); vr = Dereference(proc, exp, block, vr); if (!vr.mType->IsSimpleType()) @@ -3937,7 +4022,11 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod } #endif - TranslateExpression(dec->mBase, proc, exitBlock, exp, nullptr, nullptr, nullptr); + DestructStack* destack = nullptr; + + TranslateExpression(dec->mBase, proc, exitBlock, exp, destack, nullptr, nullptr, nullptr); + + UnwindDestructStack(dec->mBase, proc, exitBlock, destack, nullptr); } else mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent->mString); diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 870633c..9b5e7f5 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -11,6 +11,12 @@ public: InterCodeGenerator(Errors * errors, Linker * linker); ~InterCodeGenerator(void); + struct DestructStack + { + Expression * mDestruct; + DestructStack* mNext; + }; + struct ExValue { Declaration* mType; @@ -57,9 +63,10 @@ protected: ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level = 0); ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type, bool checkTrunc = true); - ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); - void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, InlineMapper* inlineMapper); + ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); + void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper); ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr); + void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom); void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable); }; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 762a34d..f37e49c 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -118,7 +118,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mCompilerOptions & COPT_NATIVE) mdec->mFlags |= DTF_NATIVE; - if (!(mdec->mFlags & DTF_FUNC_CONSTRUCTOR)) + if (!(mdec->mFlags & (DTF_FUNC_CONSTRUCTOR | DTF_FUNC_DESTRUCTOR))) { Declaration* pdec = dec->mScope->Insert(mdec->mIdent, mdec); @@ -1166,7 +1166,7 @@ void Parser::PrependThisArgument(Declaration* fdec, Declaration* pthis) Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis) { - bool definingType = false; + bool definingType = false, destructor = false; uint64 storageFlags = 0, typeFlags = 0; Declaration* bdec; @@ -1282,6 +1282,65 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } } + if ((mCompilerOptions & COPT_CPLUSPLUS) && pthis && mScanner->mToken == TK_BINARY_NOT) + { + // Destructor declaration + mScanner->NextToken(); + if (mScanner->mToken == TK_IDENT) + { + if (mScanner->mTokenIdent != pthis->mBase->mIdent) + mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Wrong class name for destructor", pthis->mIdent); + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + + Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); + + if (ctdec->mParams) + mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Destructor can't have parameter"); + + PrependThisArgument(ctdec, pthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_DESTRUCTOR; + + cdec->mSection = mCodeSection; + cdec->mBase->mFlags |= typeFlags; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + if (pthis->mBase->mDestructor) + mErrors->Error(ctdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate destrcutor definition"); + else + pthis->mBase->mDestructor = cdec; + + char dname[100]; + strcpy_s(dname, "~"); + strcat_s(dname, pthis->mBase->mIdent->mString); + cdec->mIdent = Ident::Unique(dname); + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + if (mScanner->mToken == TK_OPEN_BRACE) + { + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mValue = ParseFunction(cdec->mBase); + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + } + + return cdec; + } + bdec = ParseBaseTypeDeclaration(typeFlags); } @@ -1647,8 +1706,24 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex ResolveOverloadCall(cexp, fexp->mRight); - Expression* nexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - nexp->mLeft = fexp; + Expression* dexp = nullptr; + if (ndec->mBase->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = ndec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + nexp->mRight = vexp; nexp->mDecType = vexp->mDecType; @@ -1686,8 +1761,24 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex fexp->mRight = texp; - Expression* nexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - nexp->mLeft = fexp; + Expression* dexp = nullptr; + if (ndec->mBase->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = ndec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + nexp->mRight = vexp; nexp->mDecType = vexp->mDecType; } @@ -1755,7 +1846,7 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) { Expression* nexp; - if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mValue->mType == EX_SEQUENCE) + if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mValue->mType == EX_CONSTRUCT) { nexp = dec->mValue; @@ -2462,8 +2553,24 @@ Expression* Parser::ParsePostfixExpression(bool lhs) ResolveOverloadCall(cexp, fexp->mRight); - Expression* nexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - nexp->mLeft = fexp; + Expression* dexp = nullptr; + if (exp->mDecType->mBase->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = exp->mDecType->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + nexp->mRight = vexp; nexp->mDecType = vexp->mDecType; @@ -2981,6 +3088,8 @@ Expression* Parser::ParseStatement(void) mScanner->NextToken(); if (mScanner->mToken != TK_CLOSE_BRACE) { + Expression* sexp = new Expression(mScanner->mLocation, EX_SCOPE); + Expression* pexp = nullptr; do { @@ -3002,12 +3111,17 @@ Expression* Parser::ParseStatement(void) exp = nexp; } while (mScanner->mToken != TK_CLOSE_BRACE && mScanner->mToken != TK_EOF); + if (mScanner->mToken != TK_CLOSE_BRACE) mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "'}' expected"); exp->mEndLocation = mScanner->mLocation; mScope->End(mScanner->mLocation); mScanner->NextToken(); + + sexp->mLeft = exp; + + exp = sexp; } else { From 04eeedb0b9d5128214557a8c52bac7ffc69c39d2 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 21 Jun 2023 22:30:28 +0200 Subject: [PATCH 002/169] Object destruction on break, continue and return --- oscar64/InterCodeGenerator.cpp | 48 ++++++++++++++++++++++++---------- oscar64/InterCodeGenerator.h | 18 +++++++++++-- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 7f04894..f09ca7f 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -863,7 +863,7 @@ void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodePro if (stack->mDestruct) { DestructStack* destack = nullptr; - TranslateExpression(procType, proc, block, stack->mDestruct, destack, nullptr, nullptr, nullptr); + TranslateExpression(procType, proc, block, stack->mDestruct, destack, BranchTarget(), BranchTarget(), nullptr); } stack = stack->mNext; @@ -873,7 +873,7 @@ void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodePro mErrors->Error(proc->mLocation, EWARN_DESTRUCTOR_MISMATCH, "Destructor sequence mismatch"); } -InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr) +InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr) { DestructStack* destack = nullptr; @@ -1033,7 +1033,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro rdec->mSize = rdec->mBase->mSize; } - vl = TranslateExpression(ftype, proc, block, fexp, destack, nullptr, nullptr, &nmapper); + vl = TranslateExpression(ftype, proc, block, fexp, destack, BranchTarget(), BranchTarget(), &nmapper); InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); block->Append(jins); @@ -1059,7 +1059,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro return ExValue(TheVoidTypeDeclaration); } -InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, ExValue* lrexp) +InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, ExValue* lrexp) { Declaration* dec; ExValue vl, vr; @@ -3071,6 +3071,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mCode = IC_RETURN; } + UnwindDestructStack(procType, proc, block, destack, nullptr); + if (ins->mCode != IC_NONE) block->Append(ins); @@ -3089,12 +3091,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_BREAK: { - if (breakBlock) + if (breakBlock.mBlock) { + UnwindDestructStack(procType, proc, block, destack, breakBlock.mStack); InterInstruction * jins = new InterInstruction(exp->mLocation, IC_JUMP); block->Append(jins); - block->Close(breakBlock, nullptr); + block->Close(breakBlock.mBlock, nullptr); block = new InterCodeBasicBlock(proc); } else @@ -3105,12 +3108,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_CONTINUE: { - if (continueBlock) + if (continueBlock.mBlock) { + UnwindDestructStack(procType, proc, block, destack, continueBlock.mStack); InterInstruction * jins = new InterInstruction(exp->mLocation, IC_JUMP); block->Append(jins); - block->Close(continueBlock, nullptr); + block->Close(continueBlock.mBlock, nullptr); block = new InterCodeBasicBlock(proc); } else @@ -3526,7 +3530,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* DestructStack* idestack = destack; - vr = TranslateExpression(procType, proc, bblock, exp->mRight, destack, eblock, lblock, inlineMapper); + vr = TranslateExpression(procType, proc, bblock, exp->mRight, destack, BranchTarget(eblock, odestack), BranchTarget(lblock, idestack), inlineMapper); UnwindDestructStack(procType, proc, bblock, destack, idestack); destack = idestack; @@ -3616,7 +3620,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* DestructStack* idestack = destack; - vr = TranslateExpression(procType, proc, bblock, exp->mRight, destack, eblock, iblock, inlineMapper); + vr = TranslateExpression(procType, proc, bblock, exp->mRight, destack, BranchTarget(eblock, odestack), BranchTarget(iblock, idestack), inlineMapper); UnwindDestructStack(procType, proc, bblock, destack, idestack); destack = idestack; @@ -3641,6 +3645,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_DO: { + DestructStack* odestack = destack; + InterInstruction * jins = new InterInstruction(exp->mLocation, IC_JUMP); InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc); @@ -3650,17 +3656,27 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block->Append(jins); block->Close(cblock, nullptr); - vr = TranslateExpression(procType, proc, cblock, exp->mRight, destack, eblock, cblock, inlineMapper); + DestructStack* idestack = destack; + + vr = TranslateExpression(procType, proc, cblock, exp->mRight, destack, BranchTarget(eblock, odestack), BranchTarget(cblock, idestack), inlineMapper); + + UnwindDestructStack(procType, proc, cblock, destack, idestack); + destack = idestack; TranslateLogic(procType, proc, cblock, lblock, eblock, exp->mLeft, destack, inlineMapper); block = eblock; + UnwindDestructStack(procType, proc, block, destack, odestack); + destack = odestack; + return ExValue(TheVoidTypeDeclaration); } case EX_SWITCH: { + DestructStack* odestack = destack; + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = Dereference(proc, exp, block, vl); vl = CoerceType(proc, exp, block, vl, TheSignedIntTypeDeclaration); @@ -3730,7 +3746,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } if (cexp->mRight) - TranslateExpression(procType, proc, block, cexp->mRight, destack, eblock, continueBlock, inlineMapper); + TranslateExpression(procType, proc, block, cexp->mRight, destack, BranchTarget(eblock, odestack), continueBlock, inlineMapper); sexp = sexp->mRight; } @@ -3739,6 +3755,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (block) { + UnwindDestructStack(procType, proc, block, destack, odestack); + InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); block->Append(jins); @@ -3746,6 +3764,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } block = eblock; + + destack = odestack; return ExValue(TheVoidTypeDeclaration); } @@ -3917,7 +3937,7 @@ void InterCodeGenerator::TranslateLogic(Declaration* procType, InterCodeProcedur } default: { - ExValue vr = TranslateExpression(procType, proc, block, exp, destack, nullptr, nullptr, inlineMapper); + ExValue vr = TranslateExpression(procType, proc, block, exp, destack, BranchTarget(), BranchTarget(), inlineMapper); vr = Dereference(proc, exp, block, vr); if (!vr.mType->IsSimpleType()) @@ -4024,7 +4044,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod DestructStack* destack = nullptr; - TranslateExpression(dec->mBase, proc, exitBlock, exp, destack, nullptr, nullptr, nullptr); + TranslateExpression(dec->mBase, proc, exitBlock, exp, destack, BranchTarget(), BranchTarget(), nullptr); UnwindDestructStack(dec->mBase, proc, exitBlock, destack, nullptr); } diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 9b5e7f5..8a768d8 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -27,6 +27,20 @@ public: {} }; + struct BranchTarget + { + InterCodeBasicBlock* mBlock; + DestructStack* mStack; + + BranchTarget(void) + : mBlock(nullptr), mStack(nullptr) + {} + BranchTarget(InterCodeBasicBlock * block, DestructStack * stack) + : mBlock(block), mStack(stack) + {} + + }; + uint64 mCompilerOptions; InterCodeProcedure* TranslateProcedure(InterCodeModule* mod, Expression* exp, Declaration * dec); @@ -63,9 +77,9 @@ protected: ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level = 0); ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type, bool checkTrunc = true); - ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); + ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper); - ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, InterCodeBasicBlock* breakBlock, InterCodeBasicBlock* continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr); + ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr); void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom); void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable); From a854133f8eb63206ab377798ad5079a290792a99 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:04:18 +0200 Subject: [PATCH 003/169] Fix over eager global address progpagation --- README.md | 3 +- autotest/autotest.bat | 20 +++--- oscar64/Errors.h | 1 + oscar64/GlobalAnalyzer.cpp | 12 +++- oscar64/InterCodeGenerator.cpp | 6 +- oscar64/NativeCodeGenerator.cpp | 6 +- oscar64/Parser.cpp | 110 ++++++++++++++++++++++++++++++++ oscar64/Parser.h | 1 + oscar64/oscar64.cpp | 12 +++- 9 files changed, 152 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index b25ed93..7454ff7 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,8 @@ The compiler is command line driven, and creates an executable .prg file. * -rt : alternative runtime library, replaces the crt.c (or empty for none) * -e : execute the result in the integrated emulator * -ep : execute and profile the result in the integrated emulator -* -n : create pure native code for all functions +* -bc : create byte code for all functions +* -n : create pure native code for all functions (now default) * -d : define a symbol (e.g. NOFLOAT or NOLONG to avoid float/long code in printf) * -O1 or -O : default optimizations * -O0 : disable optimizations diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 7f5306e..adc8e42 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -172,31 +172,31 @@ echo Failed with error #%errorlevel%. exit /b %errorlevel% :test -..\release\oscar64 -e %~1 +..\release\oscar64 -e -bc %~1 @if %errorlevel% neq 0 goto :error ..\release\oscar64 -e -n %~1 @if %errorlevel% neq 0 goto :error -..\release\oscar64 -e -O2 %~1 +..\release\oscar64 -e -O2 -bc %~1 @if %errorlevel% neq 0 goto :error ..\release\oscar64 -e -O2 -n %~1 @if %errorlevel% neq 0 goto :error -..\release\oscar64 -e -O0 %~1 +..\release\oscar64 -e -O0 -bc %~1 @if %errorlevel% neq 0 goto :error ..\release\oscar64 -e -O0 -n %~1 @if %errorlevel% neq 0 goto :error -..\release\oscar64 -e -Os %~1 +..\release\oscar64 -e -Os -bc %~1 @if %errorlevel% neq 0 goto :error ..\release\oscar64 -e -Os -n %~1 @if %errorlevel% neq 0 goto :error -..\release\oscar64 -e -O3 %~1 +..\release\oscar64 -e -O3 -bc %~1 @if %errorlevel% neq 0 goto :error ..\release\oscar64 -e -O3 -n %~1 @@ -205,19 +205,19 @@ exit /b %errorlevel% @exit /b 0 :testb -..\release\oscar64 -e %~1 +..\release\oscar64 -e -bc %~1 @if %errorlevel% neq 0 goto :error -..\release\oscar64 -e -O2 %~1 +..\release\oscar64 -e -bc -O2 %~1 @if %errorlevel% neq 0 goto :error -..\release\oscar64 -e -O0 %~1 +..\release\oscar64 -e -bc -O0 %~1 @if %errorlevel% neq 0 goto :error -..\release\oscar64 -e -Os %~1 +..\release\oscar64 -e -bc -Os %~1 @if %errorlevel% neq 0 goto :error -..\release\oscar64 -e -O3 %~1 +..\release\oscar64 -e -bc -O3 %~1 @if %errorlevel% neq 0 goto :error @exit /b 0 diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 1e2333c..fb32c8b 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -29,6 +29,7 @@ enum ErrorID EWARN_UNREACHABLE_CODE, EWARN_NULL_POINTER_DEREFERENCED, EWARN_DESTRUCTOR_MISMATCH, + EWARN_NUMERIC_0_USED_AS_NULLPTR, EERR_GENERIC = 3000, EERR_FILE_NOT_FOUND, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index d944a59..185b6a6 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -739,9 +739,15 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo case EX_SEQUENCE: do { - if (exp->mLeft) - ldec = Analyze(exp->mLeft, procDec, false); - exp = exp->mRight; + if (exp->mType == EX_SEQUENCE) + { + if (exp->mLeft) + ldec = Analyze(exp->mLeft, procDec, false); + exp = exp->mRight; + } + else + return Analyze(exp, procDec, false); + } while (exp); break; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index f09ca7f..09c2406 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1073,7 +1073,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_SEQUENCE: case EX_LIST: - vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + if (exp->mLeft) + vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); exp = exp->mRight; if (!exp) return ExValue(TheVoidTypeDeclaration); @@ -2695,7 +2696,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION) vr = Dereference(proc, texp, block, vr, 1); else if (pdec && pdec->mBase->mType == DT_TYPE_POINTER && vr.mType->mType == DT_TYPE_INTEGER && texp->mType == EX_CONSTANT && texp->mDecValue->mType == DT_CONST_INTEGER && texp->mDecValue->mInteger == 0) + { + mErrors->Error(texp->mLocation, EWARN_NUMERIC_0_USED_AS_NULLPTR, "Numeric 0 used for nullptr"); vr = CoerceType(proc, texp, block, vr, pdec->mBase); + } else if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) vr = Dereference(proc, texp, block, vr, 1); else diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 21f4b70..d245355 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -21109,7 +21109,7 @@ bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(const NativeCodeBasicBlock* } else { - if (mExitRequiredRegs[reg]) +// if (mExitRequiredRegs[reg]) { if (mTrueJump && !mTrueJump->CheckPatchFailReg(block, reg)) return false; @@ -21122,7 +21122,7 @@ bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(const NativeCodeBasicBlock* } else { - if (mExitRequiredRegs[reg]) +// if (mExitRequiredRegs[reg]) { if (mTrueJump && !mTrueJump->CheckPatchFailReg(block, reg)) return false; @@ -39997,7 +39997,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "sprintf"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "mapTimeTick"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index f37e49c..87a6f3b 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -202,6 +202,11 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) dec->mParams = nullptr; dec->mFlags |= DTF_DEFINED; + + if (mCompilerOptions & COPT_CPLUSPLUS) + { + AppendMemberDestructor(pthis); + } } return dec; @@ -1141,6 +1146,111 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) return exp; } +void Parser::AppendMemberDestructor(Declaration* pthis) +{ + bool needDestructor = !pthis->mBase->mDestructor; + + Declaration* dec = pthis->mBase->mParams; + while (!needDestructor && dec) + { + if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + { + needDestructor = true; + break; + } + dec = dec->mNext; + } + + if (needDestructor) + { + if (!pthis->mBase->mDestructor) + { + Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); + + if (ctdec->mParams) + mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Destructor can't have parameter"); + + PrependThisArgument(ctdec, pthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_DESTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + if (pthis->mBase->mDestructor) + mErrors->Error(ctdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate destrcutor definition"); + else + pthis->mBase->mDestructor = cdec; + + char dname[100]; + strcpy_s(dname, "~"); + strcat_s(dname, pthis->mBase->mIdent->mString); + cdec->mIdent = Ident::Unique(dname); + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + } + + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); + pthisexp->mDecType = pthis; + pthisexp->mDecValue = pthis->mBase->mDestructor->mBase->mParams; + + Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); + thisexp->mToken = TK_MUL; + thisexp->mDecType = pthis->mBase; + thisexp->mLeft = pthisexp; + + dec = pthis->mBase->mParams; + while (dec) + { + if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + { + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; + qexp->mDecType = dec->mBase; + + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = qexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = dec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = pthis->mBase->mDestructor->mValue; + sexp->mRight = dexp; + + pthis->mBase->mDestructor->mValue = sexp; + } + + dec = dec->mNext; + } + } +} + void Parser::PrependThisArgument(Declaration* fdec, Declaration* pthis) { Declaration* adec = new Declaration(fdec->mLocation, DT_ARGUMENT); diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 44bcc7e..e218f01 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -40,6 +40,7 @@ protected: Declaration * ParseFunctionDeclaration(Declaration* bdec); void PrependThisArgument(Declaration* fdec, Declaration * pthis); + void AppendMemberDestructor(Declaration* sdec); Declaration* ParseBaseTypeDeclaration(uint64 flags); Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr); diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 1ad5bb6..455f79a 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -102,6 +102,8 @@ int main2(int argc, const char** argv) Compiler* compiler = new Compiler(); + compiler->mCompilerOptions |= COPT_NATIVE; + Location loc; GrowingArray dataFiles(nullptr); @@ -177,7 +179,10 @@ int main2(int argc, const char** argv) else if (arg[1] == 'n') { compiler->mCompilerOptions |= COPT_NATIVE; - compiler->AddDefine(Ident::Unique("OSCAR_NATIVE_ALL"), "1"); + } + else if (arg[1] == 'b' && arg[2] == 'c') + { + compiler->mCompilerOptions &= ~COPT_NATIVE; } else if (arg[1] == 'O') { @@ -261,6 +266,11 @@ int main2(int argc, const char** argv) } } + if (compiler->mCompilerOptions & COPT_NATIVE) + { + compiler->AddDefine(Ident::Unique("OSCAR_NATIVE_ALL"), "1"); + } + char basicStart[10]; strcpy_s(basicStart, "0x0801"); From 56740b630d03b2bc54ce7c17ed439c27585225ed Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 22 Jun 2023 19:17:45 +0200 Subject: [PATCH 004/169] Member constructor and destructor --- oscar64/Declaration.h | 1 + oscar64/Parser.cpp | 396 +++++++++++++++++++++++++++++++++++++----- oscar64/Parser.h | 6 +- 3 files changed, 363 insertions(+), 40 deletions(-) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 418c3fe..91d57b2 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -38,6 +38,7 @@ enum DecType DT_CONST_POINTER, DT_CONST_REFERENCE, DT_CONST_ASSEMBLER, + DT_CONST_CONSTRUCTOR, DT_VARIABLE, DT_ARGUMENT, diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 87a6f3b..3bf165a 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -205,6 +205,14 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mCompilerOptions & COPT_CPLUSPLUS) { + Declaration* cdec = pthis->mBase->mConstructor; + while (cdec) + { + if (cdec->mFlags & DTF_DEFINED) + PrependMemberConstructor(pthis, cdec); + cdec = cdec->mNext; + } + AppendMemberDestructor(pthis); } } @@ -1146,6 +1154,191 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) return exp; } +Expression* Parser::BuildMemberInitializer(Expression* vexp) +{ + if (vexp->mDecType->mType == DT_TYPE_STRUCT && vexp->mDecType->mConstructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = vexp->mDecType->mConstructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + + mScanner->NextToken(); + if (mScanner->mToken != TK_CLOSE_PARENTHESIS) + { + fexp->mRight = ParseListExpression(); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } + else + { + fexp->mRight = nullptr; + mScanner->NextToken(); + } + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = vexp->mDecType; + texp->mDecType->mSize = 2; + + if (fexp->mRight) + { + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = fexp->mRight; + fexp->mRight = lexp; + } + else + fexp->mRight = texp; + + ResolveOverloadCall(cexp, fexp->mRight); + + return fexp; + } + else + { + Expression* nexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + nexp->mToken = TK_ASSIGN; + nexp->mDecType = vexp->mDecType; + nexp->mLeft = vexp; + ConsumeToken(TK_OPEN_PARENTHESIS); + nexp->mRight = ParseRExpression(); + ConsumeToken(TK_CLOSE_PARENTHESIS); + + return nexp; + } +} + +void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) +{ + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); + pthisexp->mDecType = pthis; + pthisexp->mDecValue = pthis->mBase->mDestructor->mBase->mParams; + + Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); + thisexp->mToken = TK_MUL; + thisexp->mDecType = pthis->mBase; + thisexp->mLeft = pthisexp; + + Declaration* dec = pthis->mBase->mParams; + while (dec) + { + if (dec->mType == DT_ELEMENT) + { + Declaration* mfunc = cfunc->mScope ? cfunc->mScope->Lookup(dec->mIdent) : nullptr; + + if (mfunc) + { + Expression* sexp = new Expression(cfunc->mLocation, EX_SEQUENCE); + sexp->mLeft = mfunc->mValue; + sexp->mRight = cfunc->mValue; + cfunc->mValue = sexp; + } + else if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mConstructor) + { + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; + qexp->mDecType = dec->mBase; + + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = qexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; + + Declaration* mdec = dec->mBase->mConstructor; + while (mdec && mdec->mBase->mParams->mNext) + mdec = mdec->mNext; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + if (mdec) + { + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + } + else + mErrors->Error(dec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor"); + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = cfunc->mValue; + cfunc->mValue = sexp; + } + } + + dec = dec->mNext; + } +} + +void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc) +{ + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); + pthisexp->mDecType = pthis; + pthisexp->mDecValue = cfunc->mBase->mParams; + + Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); + thisexp->mToken = TK_MUL; + thisexp->mDecType = pthis->mBase; + thisexp->mLeft = pthisexp; + + cfunc->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS); + + DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_FUNCTION); + mScope = scope; + + Declaration* pdec = cfunc->mBase->mParams; + while (pdec) + { + if (pdec->mIdent) + scope->Insert(pdec->mIdent, pdec); + pdec = pdec->mNext; + } + Declaration* othis = mThisPointer; + mThisPointer = pthis; + + mScanner->NextToken(); + do { + if (ExpectToken(TK_IDENT)) + { + Declaration* dec = pthis->mBase->mScope->Lookup(mScanner->mTokenIdent); + if (dec && dec->mType == DT_ELEMENT) + { + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; + qexp->mDecType = dec->mBase; + + Declaration* dec = new Declaration(mScanner->mLocation, DT_CONST_CONSTRUCTOR); + dec->mIdent = mScanner->mTokenIdent; + + mScanner->NextToken(); + + dec->mValue = BuildMemberInitializer(qexp); + + cfunc->mScope->Insert(dec->mIdent, dec); + } + else + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Base class or member not found", mScanner->mTokenIdent); + } + + } while (ConsumeTokenIf(TK_COMMA)); + + mScope = mScope->mParent; + mThisPointer = othis; +} + void Parser::AppendMemberDestructor(Declaration* pthis) { bool needDestructor = !pthis->mBase->mDestructor; @@ -1203,50 +1396,53 @@ void Parser::AppendMemberDestructor(Declaration* pthis) cdec->mNumVars = mLocalIndex; } - Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); - pthisexp->mDecType = pthis; - pthisexp->mDecValue = pthis->mBase->mDestructor->mBase->mParams; - - Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); - thisexp->mToken = TK_MUL; - thisexp->mDecType = pthis->mBase; - thisexp->mLeft = pthisexp; - - dec = pthis->mBase->mParams; - while (dec) + if (pthis->mBase->mDestructor->mFlags & DTF_DEFINED) { - if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); + pthisexp->mDecType = pthis; + pthisexp->mDecValue = pthis->mBase->mDestructor->mBase->mParams; + + Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); + thisexp->mToken = TK_MUL; + thisexp->mDecType = pthis->mBase; + thisexp->mLeft = pthisexp; + + dec = pthis->mBase->mParams; + while (dec) { - Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); - qexp->mLeft = thisexp; - qexp->mDecValue = dec; - qexp->mDecType = dec->mBase; + if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + { + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; + qexp->mDecType = dec->mBase; - Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); - pexp->mLeft = qexp; - pexp->mToken = TK_BINARY_AND; - pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); - pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - pexp->mDecType->mBase = dec->mBase; - pexp->mDecType->mSize = 2; + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = qexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - cexp->mDecValue = dec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = dec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; - - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; - sexp->mLeft = pthis->mBase->mDestructor->mValue; - sexp->mRight = dexp; + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - pthis->mBase->mDestructor->mValue = sexp; + sexp->mLeft = pthis->mBase->mDestructor->mValue; + sexp->mRight = dexp; + + pthis->mBase->mDestructor->mValue = sexp; + } + + dec = dec->mNext; } - - dec = dec->mNext; } } } @@ -1262,7 +1458,7 @@ void Parser::PrependThisArgument(Declaration* fdec, Declaration* pthis) adec->mNext = fdec->mParams; adec->mIdent = adec->mQualIdent = Ident::Unique("this"); - Declaration* p = adec->mBase->mParams; + Declaration* p = fdec->mParams; while (p) { p->mVarIndex += 2; @@ -1399,7 +1595,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (mScanner->mToken == TK_IDENT) { if (mScanner->mTokenIdent != pthis->mBase->mIdent) - mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Wrong class name for destructor", pthis->mIdent); + mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Wrong class name for destructor", pthis->mBase->mIdent); mScanner->NextToken(); } else @@ -1518,6 +1714,12 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec->mIdent = pthis->mBase->mIdent; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + // Initializer list + if (mScanner->mToken == TK_COLON) + { + BuildMemberConstructor(pthis, cdec); + } + if (mScanner->mToken == TK_OPEN_BRACE) { if (cdec->mFlags & DTF_DEFINED) @@ -1536,6 +1738,105 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex return cdec; } + + if (bdec && bdec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON)) + { + if (mScanner->mToken == TK_IDENT && mScanner->mTokenIdent == bdec->mIdent) + { + mScanner->NextToken(); + + Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); + + Declaration * bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + bthis->mFlags |= DTF_CONST | DTF_DEFINED; + bthis->mBase = bdec; + bthis->mSize = 2; + + PrependThisArgument(ctdec, bthis); + + Declaration* cdec = bdec->mConstructor; + if (cdec) + { + while (cdec && !cdec->mBase->IsSameParams(ctdec)) + cdec = cdec->mNext; + } + + if (cdec) + { + // Initializer list + if (mScanner->mToken == TK_COLON) + { + BuildMemberConstructor(bthis, cdec); + } + + if (mScanner->mToken == TK_OPEN_BRACE) + { + if (cdec->mFlags & DTF_DEFINED) + mErrors->Error(cdec->mLocation, EERR_DUPLICATE_DEFINITION, "Function already has a body"); + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mValue = ParseFunction(cdec->mBase); + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + + PrependMemberConstructor(bthis, cdec); + } + + return cdec; + } + else + { + mErrors->Error(bdec->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor"); + return bdec; + } + } + + if (ConsumeTokenIf(TK_BINARY_NOT)) + { + if (mScanner->mToken == TK_IDENT) + { + if (mScanner->mTokenIdent != bdec->mIdent) + mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Wrong class name for destructor", bdec->mIdent); + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + + Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); + + if (ctdec->mParams) + mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Destructor can't have parameter"); + + if (bdec->mDestructor) + { + Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + bthis->mFlags |= DTF_CONST | DTF_DEFINED; + bthis->mBase = bdec; + bthis->mSize = 2; + + bdec->mDestructor->mCompilerOptions = mCompilerOptions; + bdec->mDestructor->mBase->mCompilerOptions = mCompilerOptions; + + bdec->mDestructor->mVarIndex = -1; + + bdec->mDestructor->mValue = ParseFunction(bdec->mDestructor->mBase); + + bdec->mDestructor->mFlags |= DTF_DEFINED; + bdec->mDestructor->mNumVars = mLocalIndex; + + AppendMemberDestructor(bthis); + } + else + mErrors->Error(ctdec->mLocation, EERR_DUPLICATE_DEFINITION, "Desctructor not declared", bdec->mIdent); + + return bdec->mDestructor; + } + } } for (;;) @@ -1840,7 +2141,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex ndec->mValue = nexp; } } - else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mBase->mConstructor) + else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mBase->mConstructor && ndec->mType == DT_VARIABLE && !pthis) { // Find default constructor @@ -1891,6 +2192,8 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex nexp->mRight = vexp; nexp->mDecType = vexp->mDecType; + + ndec->mValue = nexp; } else mErrors->Error(ndec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor for class", ndec->mBase->mIdent); @@ -4288,6 +4591,21 @@ Expression* Parser::ParseAssembler(void) return ifirst; } +bool Parser::ExpectToken(Token token) +{ + if (mScanner->mToken == token) + { + return true; + } + else + { + char buffer[100]; + sprintf_s(buffer, "%s expected", TokenNames[token]); + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, buffer); + return false; + } +} + bool Parser::ConsumeToken(Token token) { if (mScanner->mToken == token) diff --git a/oscar64/Parser.h b/oscar64/Parser.h index e218f01..2e0c661 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -23,6 +23,7 @@ public: void Parse(void); protected: + bool ExpectToken(Token token); bool ConsumeToken(Token token); bool ConsumeTokenIf(Token token); bool ConsumeIdentIf(const char* ident); @@ -40,7 +41,10 @@ protected: Declaration * ParseFunctionDeclaration(Declaration* bdec); void PrependThisArgument(Declaration* fdec, Declaration * pthis); - void AppendMemberDestructor(Declaration* sdec); + void AppendMemberDestructor(Declaration* pthis); + void BuildMemberConstructor(Declaration* pthis, Declaration* cfunc); + Expression* BuildMemberInitializer(Expression* vexp); + void PrependMemberConstructor(Declaration* pthis, Declaration* cfunc); Declaration* ParseBaseTypeDeclaration(uint64 flags); Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr); From 6b753c14184ce95d09fed824e86c524d1da2ee7c Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 25 Jun 2023 14:25:29 +0200 Subject: [PATCH 005/169] Destructor tracking of temporary variables --- autotest/autotest.bat | 6 + autotest/constructortest.cpp | 165 ++++++ autotest/copyconstructor.cpp | 216 +++++++ oscar64/Declaration.cpp | 162 +++++- oscar64/Declaration.h | 8 +- oscar64/Errors.h | 4 +- oscar64/GlobalAnalyzer.cpp | 29 +- oscar64/InterCode.cpp | 2 +- oscar64/InterCodeGenerator.cpp | 514 ++++++++++++++--- oscar64/InterCodeGenerator.h | 8 +- oscar64/NativeCodeGenerator.cpp | 40 +- oscar64/Parser.cpp | 989 ++++++++++++++++++++++++++------ oscar64/Parser.h | 9 + oscar64/Scanner.cpp | 11 + 14 files changed, 1898 insertions(+), 265 deletions(-) create mode 100644 autotest/constructortest.cpp create mode 100644 autotest/copyconstructor.cpp diff --git a/autotest/autotest.bat b/autotest/autotest.bat index adc8e42..2b2ddd1 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -1,5 +1,11 @@ rem @echo off +@call :test constructortest.cpp +@if %errorlevel% neq 0 goto :error + +@call :test copyconstructor.cpp +@if %errorlevel% neq 0 goto :error + @call :test stdlibtest.c @if %errorlevel% neq 0 goto :error diff --git a/autotest/constructortest.cpp b/autotest/constructortest.cpp new file mode 100644 index 0000000..1418277 --- /dev/null +++ b/autotest/constructortest.cpp @@ -0,0 +1,165 @@ +#include + +int t, n; + +struct C1 +{ + int a; + + C1(int x); + ~C1(void); +}; + +C1::C1(int x) : a(x) +{ + t += a; + n++; +} + +C1::~C1(void) +{ + t -= a; +} + +void test_base(void) +{ + n = 0; + + { + C1 x(2); + C1 y(1); + } + + assert(t == 0 && n == 2); +} + +void test_base_loop(void) +{ + n = 0; + + for(int i=0; i<10; i++) + { + C1 x(2); + C1 y(1); + } + + assert(t == 0 && n == 20); +} + +struct C2 +{ + C1 c, d; + + C2(void); +}; + +C2::C2(void) + : c(7), d(11) +{ + +} + +void test_member(void) +{ + n = 0; + + { + C2 x(); + C2 y(); + } + + assert(t == 0 && n == 4); +} + +void test_member_loop(void) +{ + n = 0; + + for(int i=0; i<10; i++) + { + C2 x(); + C2 y(); + } + + assert(t == 0 && n == 40); +} + +struct C3 +{ + C2 x, y; +}; + +void test_default(void) +{ + n = 0; + + { + C3 x(); + C3 y(); + } + + assert(t == 0 && n == 8); +} + +void test_default_loop(void) +{ + n = 0; + + for(int i=0; i<10; i++) + { + C3 x(); + C3 y(); + } + + assert(t == 0 && n == 80); +} + +inline void test_inline_x(void) +{ + C1 x(1), y(2); +} + +void test_inline(void) +{ + n = 0; + + test_inline_x(); + + assert(t == 0 && n == 2); +} + +inline void test_inline_xr(void) +{ + C1 x(1), y(2); + + { + C1 x(3); + return; + } +} + +void test_inline_return(void) +{ + n = 0; + + test_inline_xr(); + + assert(t == 0 && n == 3); +} + +int main(void) +{ + test_base(); + test_base_loop(); + + test_member(); + test_member_loop(); + + test_default(); + test_default_loop(); + + test_inline(); + test_inline_return(); + + return 0; +} diff --git a/autotest/copyconstructor.cpp b/autotest/copyconstructor.cpp new file mode 100644 index 0000000..c16f30b --- /dev/null +++ b/autotest/copyconstructor.cpp @@ -0,0 +1,216 @@ +#include + +int t, n; + +struct C0 +{ + int u; + + C0(int a); + ~C0(void); +}; + +C0::C0(int a) : u(a) +{ + t += u; + n++; +} + +C0::~C0(void) +{ + t -= u; +} + +struct C1 +{ + int u; + + C1(int a); + ~C1(void); + C1(const C1 & c); +}; + +C1::C1(int a) : u(a) +{ + t += u; + n++; +} + +C1::~C1(void) +{ + t -= u; +} + +C1::C1(const C1 & c) : u(c.u) +{ + t += u; + n++; +} + +void test_dcopy_init(void) +{ + n = 0; + + { + C0 x(4); + C0 y(x); + } + + assert(n == 1 && t == -4); + + t = 0; +} + +void test_copy_init(void) +{ + n = 0; + + { + C1 x(4); + C1 y(x); + } + + assert(n == 2 && t == 0); +} + +struct C2 +{ + C1 a, b; + + C2(void); +}; + +C2::C2(void) : a(1), b(3) +{} + +void test_minit(void) +{ + n = 0; + + { + C2 x; + } + + assert(n == 2 && t == 0); +} + +void test_minit_copy(void) +{ + n = 0; + + { + C2 x; + C2 y(x); + } + + assert(n == 4 && t == 0); +} + +int k; + +inline void test_param_fv(C2 c) +{ + k += c.a.u; +} + +void test_param_fr(C2 & c) +{ + k += c.a.u; +} + +void test_param_value(void) +{ + n = 0; + + { + C2 x; + test_param_fv(x); + } + + assert(n == 4 && t == 0); +} + +void test_param_ref(void) +{ + n = 0; + + { + C2 x; + test_param_fr(x); + } + + assert(n == 2 && t == 0); +} + +C2 test_ret_v(void) +{ + C2 c; + return c; +} + +C2 & test_ret_r(C2 & r) +{ + return r; +} + +void test_return_value(void) +{ + n = 0; + + { + C2 c(test_ret_v()); + } + + assert(n == 4 && t == 0); +} + +void test_return_reference(void) +{ + n = 0; + + { + C2 d; + C2 c(test_ret_r(d)); + } + + assert(n == 2 && t == 0); +} + +void test_retparam_value(void) +{ + n = 0; + + { + test_param_fv(test_ret_v()); + } + + assert(n == 4 && t == 0); +} + +void test_retparam_reference(void) +{ + n = 0; + + { + test_param_fr(test_ret_v()); + } + + assert(n == 4 && t == 0); +} + +int main(void) +{ +#if 0 + test_dcopy_init(); + test_copy_init(); + test_minit(); + test_minit_copy(); + test_param_value(); + test_param_ref(); + test_return_value(); +#endif + test_retparam_value(); +// test_retparam_reference(); + + return 0; +} \ No newline at end of file diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 3f0af85..aa04d09 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -123,7 +123,7 @@ void DeclarationScope::End(const Location& loc) } Expression::Expression(const Location& loc, ExpressionType type) - : mLocation(loc), mEndLocation(loc), mType(type), mLeft(nullptr), mRight(nullptr), mConst(false) + : mLocation(loc), mEndLocation(loc), mType(type), mLeft(nullptr), mRight(nullptr), mConst(false), mDecType(nullptr), mDecValue(nullptr) { } @@ -133,6 +133,148 @@ Expression::~Expression(void) } +void Expression::Dump(int ident) const +{ + for (int i = 0; i < ident; i++) + printf("| "); + + switch (mType) + { + case EX_ERROR: + printf("ERROR"); + break; + case EX_VOID: + printf("VOID"); + break; + case EX_CONSTANT: + printf("CONST"); + break; + case EX_VARIABLE: + printf("VAR"); + break; + case EX_ASSIGNMENT: + printf("ASSIGN<%s>", TokenNames[mToken]); + break; + case EX_INITIALIZATION: + printf("INIT"); + break; + case EX_BINARY: + printf("BINARY<%s>", TokenNames[mToken]); + break; + case EX_RELATIONAL: + printf("RELATIONAL<%s>", TokenNames[mToken]); + break; + case EX_PREINCDEC: + printf("PREOP<%s>", TokenNames[mToken]); + break; + case EX_PREFIX: + printf("PREFIX<%s>", TokenNames[mToken]); + break; + case EX_POSTFIX: + printf("POSTFIX<%s>", TokenNames[mToken]); + break; + case EX_POSTINCDEC: + printf("POSTOP<%s>", TokenNames[mToken]); + break; + case EX_INDEX: + printf("INDEX"); + break; + case EX_QUALIFY: + printf("QUALIFY"); + break; + case EX_CALL: + printf("CALL"); + break; + case EX_INLINE: + printf("INLINE"); + break; + case EX_LIST: + printf("LIST"); + break; + case EX_RETURN: + printf("RETURN"); + break; + case EX_SEQUENCE: + printf("SEQUENCE"); + break; + case EX_WHILE: + printf("WHILE"); + break; + case EX_IF: + printf("IF"); + break; + case EX_ELSE: + printf("ELSE"); + break; + case EX_FOR: + printf("FOR"); + break; + case EX_DO: + printf("DO"); + break; + case EX_SCOPE: + printf("SCOPE"); + break; + case EX_BREAK: + printf("BREAK"); + break; + case EX_CONTINUE: + printf("CONTINUE"); + break; + case EX_TYPE: + printf("TYPE"); + break; + case EX_TYPECAST: + printf("TYPECAST"); + break; + case EX_LOGICAL_AND: + printf("AND"); + break; + case EX_LOGICAL_OR: + printf("OR"); + break; + case EX_LOGICAL_NOT: + printf("NOT"); + break; + case EX_ASSEMBLER: + printf("ASSEMBLER"); + break; + case EX_UNDEFINED: + printf("UNDEFINED"); + break; + case EX_SWITCH: + printf("SWITCH"); + break; + case EX_CASE: + printf("CASE"); + break; + case EX_DEFAULT: + printf("DEFAULT"); + break; + case EX_CONDITIONAL: + printf("COND"); + break; + case EX_ASSUME: + printf("ASSUME"); + break; + case EX_BANKOF: + printf("BANKOF"); + break; + case EX_CONSTRUCT: + printf("CONSTRUCT"); + break; + case EX_CLEANUP: + printf("CLEANUP"); + break; + } + printf("\n"); + + if (mLeft) + mLeft->Dump(ident + 1); + if (mRight) + mRight->Dump(ident + 1); +} + bool Expression::HasSideEffects(void) const { switch (mType) @@ -635,8 +777,8 @@ Expression* Expression::ConstantFold(Errors * errors) Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), - mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mConst(nullptr), - mConstructor(nullptr), mDestructor(nullptr), + mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), + mConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), mCompilerOptions(0), mUseCount(0) @@ -653,6 +795,18 @@ int Declaration::Stride(void) const return mStride > 0 ? mStride : mBase->mSize; } +Declaration* Declaration::Last(void) +{ + mPrev = nullptr; + Declaration* p = this; + while (p->mNext) + { + p->mNext->mPrev = p; + p = p->mNext; + } + return p; +} + Declaration* Declaration::Clone(void) { Declaration* ndec = new Declaration(mLocation, mType); @@ -945,6 +1099,8 @@ bool Declaration::IsSame(const Declaration* dec) const return mIdent == dec->mIdent; else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) return this->Stride() == dec->Stride() && mBase->IsSame(dec->mBase); + else if (mType == DT_TYPE_REFERENCE) + return mBase->IsSame(dec->mBase); else if (mType == DT_TYPE_STRUCT) return mScope == dec->mScope || (mIdent == dec->mIdent && mSize == dec->mSize); else if (mType == DT_TYPE_FUNCTION) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 91d57b2..6f49477 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -185,7 +185,8 @@ enum ExpressionType EX_CONDITIONAL, EX_ASSUME, EX_BANKOF, - EX_CONSTRUCT + EX_CONSTRUCT, + EX_CLEANUP, }; class Expression @@ -208,6 +209,8 @@ public: bool HasSideEffects(void) const; bool IsSame(const Expression* exp) const; + + void Dump(int ident) const; }; class Declaration @@ -219,7 +222,7 @@ public: Location mLocation, mEndLocation; DecType mType; Token mToken; - Declaration* mBase, *mParams, * mNext, * mConst, * mConstructor, * mDestructor; + Declaration* mBase, *mParams, * mNext, * mPrev, * mConst, * mConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; Expression* mValue; DeclarationScope* mScope; int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe; @@ -249,6 +252,7 @@ public: Declaration* ToStriped(int stripe); Declaration* ToStriped(Errors* errors); Declaration* Clone(void); + Declaration* Last(void); int Stride(void) const; }; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index fb32c8b..8d7f14d 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -14,7 +14,7 @@ class Ident; enum ErrorID { EINFO_GENERIC = 1000, - + EWARN_GENERIC = 2000, EWARN_CONSTANT_TRUNCATED, EWARN_UNKNOWN_PRAGMA, @@ -78,6 +78,8 @@ enum ErrorID ERRO_NO_MATCHING_FUNCTION_CALL, ERRO_AMBIGUOUS_FUNCTION_CALL, EERR_NO_DEFAULT_CONSTRUCTOR, + EERR_INVALID_OPERATOR, + EERR_MISSING_TEMP, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 185b6a6..f299058 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -429,6 +429,14 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) mFunctions.Push(dec); + Declaration* pdec = dec->mBase->mParams; + while (pdec) + { + if (pdec->mBase->mType == DT_TYPE_STRUCT && (pdec->mBase->mCopyConstructor || pdec->mBase->mDestructor)) + dec->mBase->mFlags |= DTF_STACKCALL; + pdec = pdec->mNext; + } + dec->mFlags |= DTF_ANALYZED; dec->mFlags |= DTF_FUNC_INTRSAVE; @@ -679,7 +687,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo if (pdec && !(ldec->mBase->mFlags & DTF_VARIADIC) && !(ldec->mFlags & (DTF_INTRINSIC | DTF_FUNC_ASSEMBLER))) { -#if 1 +#if 0 if (mCompilerOptions & COPT_OPTIMIZE_BASIC) { if (!(pdec->mFlags & DTF_FPARAM_NOCONST)) @@ -714,8 +722,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo } #endif } + + if (pdec && pdec->mBase->mType == DT_TYPE_STRUCT && pdec->mBase->mCopyConstructor) + { + AnalyzeProcedure(pdec->mBase->mCopyConstructor->mValue, pdec->mBase->mCopyConstructor); + RegisterCall(procDec, pdec->mBase->mCopyConstructor); + } - if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT) + if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT && !(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE)) ldec->mBase->mFlags |= DTF_STACKCALL; if (pdec) @@ -734,7 +748,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo return Analyze(exp->mRight, procDec, false); case EX_RETURN: if (exp->mLeft) + { RegisterProc(Analyze(exp->mLeft, procDec, false)); + if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor) + { + AnalyzeProcedure(procDec->mBase->mBase->mCopyConstructor->mValue, procDec->mBase->mBase->mCopyConstructor); + RegisterCall(procDec, procDec->mBase->mBase->mCopyConstructor); + } + } break; case EX_SEQUENCE: do @@ -761,6 +782,10 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo if (exp->mLeft->mRight) Analyze(exp->mLeft->mRight, procDec, false); return Analyze(exp->mRight, procDec, false); + + case EX_CLEANUP: + Analyze(exp->mRight, procDec, false); + return Analyze(exp->mLeft, procDec, lhs); case EX_WHILE: procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 3e8963b..9517e7d 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16017,7 +16017,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "test_retparam_value"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 09c2406..13bd34f 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -856,14 +856,14 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e } } -void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack* bottom) +void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack* bottom, InlineMapper* inlineMapper) { while (stack && stack != bottom) { if (stack->mDestruct) { DestructStack* destack = nullptr; - TranslateExpression(procType, proc, block, stack->mDestruct, destack, BranchTarget(), BranchTarget(), nullptr); + TranslateExpression(procType, proc, block, stack->mDestruct, destack, BranchTarget(), BranchTarget(), inlineMapper); } stack = stack->mNext; @@ -873,7 +873,7 @@ void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodePro mErrors->Error(proc->mLocation, EWARN_DESTRUCTOR_MISMATCH, "Destructor sequence mismatch"); } -InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr) +InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp) { DestructStack* destack = nullptr; @@ -1024,13 +1024,20 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro Declaration* rdec = nullptr; if (ftype->mBase->mType != DT_TYPE_VOID) { - int nindex = proc->mNumLocals++; - nmapper.mResult = nindex; + if (lrexp) + { + nmapper.mResultExp = lrexp; + } + else + { + int nindex = proc->mNumLocals++; + nmapper.mResult = nindex; - rdec = new Declaration(ftype->mLocation, DT_VARIABLE); - rdec->mVarIndex = nindex; - rdec->mBase = ftype->mBase; - rdec->mSize = rdec->mBase->mSize; + rdec = new Declaration(ftype->mLocation, DT_VARIABLE); + rdec->mVarIndex = nindex; + rdec->mBase = ftype->mBase; + rdec->mSize = rdec->mBase->mSize; + } } vl = TranslateExpression(ftype, proc, block, fexp, destack, BranchTarget(), BranchTarget(), &nmapper); @@ -1041,6 +1048,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro block->Close(nmapper.mReturn, nullptr); block = nmapper.mReturn; + UnwindDestructStack(ftype, proc, block, destack, nullptr, &nmapper); + if (rdec) { InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT); @@ -1055,10 +1064,214 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro return ExValue(rdec->mBase, ins->mDst.mTemp, 1); } + else if (lrexp) + { + return *lrexp; + } else return ExValue(TheVoidTypeDeclaration); } +void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper) +{ + if (vl.mType->mCopyConstructor) + { + Declaration* ccdec = vl.mType->mCopyConstructor; + if (!ccdec->mLinkerObject) + this->TranslateProcedure(proc->mModule, ccdec->mValue, ccdec); + + bool canInline = (mCompilerOptions & COPT_OPTIMIZE_INLINE) && !(inlineMapper && inlineMapper->mDepth > 10); + bool doInline = false; + + if (canInline) + { + if (ccdec->mFlags & DTF_INLINE) + { + if ((ccdec->mFlags & DTF_REQUEST_INLINE) || (mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE)) + { + if (proc->mNativeProcedure || !(ccdec->mFlags & DTF_NATIVE)) + doInline = true; + } + } + } + + if (doInline) + { + DestructStack* destack = nullptr; + + Expression* fexp = ccdec->mValue; + Declaration* ftype = ccdec->mBase; + + InlineMapper nmapper; + nmapper.mReturn = new InterCodeBasicBlock(proc); + nmapper.mVarIndex = proc->mNumLocals; + nmapper.mConstExpr = false; + proc->mNumLocals += ccdec->mNumVars; + if (inlineMapper) + nmapper.mDepth = inlineMapper->mDepth + 1; + + Declaration* pdec = ftype->mParams; + int nindex = proc->mNumLocals++; + Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); + ains->mConst.mMemory = IM_LOCAL; + ains->mConst.mVarIndex = nindex; + + if (!(pdec->mFlags & DTF_FPARAM_CONST)) + nmapper.mParams[pdec->mVarIndex] = nindex; + + vdec->mVarIndex = nindex; + vdec->mBase = pdec->mBase; + ains->mConst.mOperandSize = 2; + vdec->mSize = ains->mConst.mOperandSize; + vdec->mIdent = pdec->mIdent; + vdec->mQualIdent = pdec->mQualIdent; + block->Append(ains); + + InterInstruction* wins = new InterInstruction(exp->mLocation, IC_STORE); + wins->mSrc[1].mMemory = IM_INDIRECT; + wins->mSrc[0].mType = InterTypeOf(vl.mType);; + wins->mSrc[0].mTemp = vl.mTemp; + wins->mSrc[1].mType = IT_POINTER; + wins->mSrc[1].mTemp = ains->mDst.mTemp; + wins->mSrc[1].mOperandSize = 2; + if (!(pdec->mFlags & DTF_FPARAM_CONST)) + block->Append(wins); + + pdec = pdec->mNext; + + nindex = proc->mNumLocals++; + vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); + ains->mConst.mMemory = IM_LOCAL; + ains->mConst.mVarIndex = nindex; + + if (!(pdec->mFlags & DTF_FPARAM_CONST)) + nmapper.mParams[pdec->mVarIndex] = nindex; + + vdec->mVarIndex = nindex; + vdec->mBase = pdec->mBase; + ains->mConst.mOperandSize = 2; + vdec->mSize = ains->mConst.mOperandSize; + vdec->mIdent = pdec->mIdent; + vdec->mQualIdent = pdec->mQualIdent; + block->Append(ains); + + wins = new InterInstruction(exp->mLocation, IC_STORE); + wins->mSrc[1].mMemory = IM_INDIRECT; + wins->mSrc[0].mType = InterTypeOf(vr.mType);; + wins->mSrc[0].mTemp = vr.mTemp; + wins->mSrc[1].mType = IT_POINTER; + wins->mSrc[1].mTemp = ains->mDst.mTemp; + wins->mSrc[1].mOperandSize = 2; + if (!(pdec->mFlags & DTF_FPARAM_CONST)) + block->Append(wins); + + TranslateExpression(ftype, proc, block, fexp, destack, BranchTarget(), BranchTarget(), &nmapper); + + InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + block->Append(jins); + + block->Close(nmapper.mReturn, nullptr); + block = nmapper.mReturn; + } + else if (ccdec->mBase->mFlags & DTF_FASTCALL) + { + InterInstruction* psins = new InterInstruction(exp->mLocation, IC_CONSTANT); + psins->mDst.mType = IT_POINTER; + psins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + psins->mConst.mVarIndex = 0; + psins->mConst.mIntConst = 0; + psins->mConst.mOperandSize = 2; + if (ccdec->mBase->mFlags & DTF_FASTCALL) + { + psins->mConst.mMemory = IM_FFRAME; + psins->mConst.mVarIndex += ccdec->mBase->mFastCallBase; + } + else + psins->mConst.mMemory = IM_FRAME; + block->Append(psins); + + InterInstruction* ssins = new InterInstruction(exp->mLocation, IC_STORE); + ssins->mSrc[0].mType = IT_POINTER; + ssins->mSrc[0].mTemp = vl.mTemp; + ssins->mSrc[0].mMemory = IM_INDIRECT; + ssins->mSrc[0].mOperandSize = 2; + ssins->mSrc[1] = psins->mDst; + block->Append(ssins); + + InterInstruction* plins = new InterInstruction(exp->mLocation, IC_CONSTANT); + plins->mDst.mType = IT_POINTER; + plins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + plins->mConst.mVarIndex = 2; + plins->mConst.mIntConst = 0; + plins->mConst.mOperandSize = 2; + if (ccdec->mBase->mFlags & DTF_FASTCALL) + { + plins->mConst.mMemory = IM_FFRAME; + plins->mConst.mVarIndex += ccdec->mBase->mFastCallBase; + } + else + plins->mConst.mMemory = IM_FRAME; + block->Append(plins); + + InterInstruction* slins = new InterInstruction(exp->mLocation, IC_STORE); + slins->mSrc[0].mType = IT_POINTER; + slins->mSrc[0].mTemp = vr.mTemp; + slins->mSrc[0].mMemory = IM_INDIRECT; + slins->mSrc[0].mOperandSize = 2; + slins->mSrc[1] = plins->mDst; + block->Append(slins); + + proc->AddCalledFunction(proc->mModule->mProcedures[ccdec->mVarIndex]); + + InterInstruction* pcins = new InterInstruction(exp->mLocation, IC_CONSTANT); + pcins->mDst.mType = IT_POINTER; + pcins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + pcins->mConst.mType = IT_POINTER; + pcins->mConst.mVarIndex = ccdec->mVarIndex; + pcins->mConst.mIntConst = 0; + pcins->mConst.mOperandSize = 2; + pcins->mConst.mMemory = IM_GLOBAL; + pcins->mConst.mLinkerObject = ccdec->mLinkerObject; + block->Append(pcins); + + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CALL); + if (ccdec->mFlags & DTF_NATIVE) + cins->mCode = IC_CALL_NATIVE; + else + cins->mCode = IC_CALL; + cins->mSrc[0] = pcins->mDst; + cins->mNumOperands = 1; + + block->Append(cins); + } + } + else + { + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + cins->mSrc[0].mType = IT_POINTER; + cins->mSrc[0].mTemp = vr.mTemp; + cins->mSrc[0].mMemory = IM_INDIRECT; + cins->mSrc[0].mOperandSize = vr.mType->mSize; + cins->mSrc[0].mStride = vr.mType->mStripe; + + cins->mSrc[1].mOperandSize = vl.mType->mSize; + cins->mSrc[1].mType = IT_POINTER; + cins->mSrc[1].mTemp = vl.mTemp; + cins->mSrc[1].mMemory = IM_INDIRECT; + + cins->mConst.mOperandSize = vl.mType->mSize; + block->Append(cins); + } +} + InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, ExValue* lrexp) { Declaration* dec; @@ -1079,6 +1292,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!exp) return ExValue(TheVoidTypeDeclaration); break; + case EX_CONSTRUCT: { if (exp->mLeft->mLeft) @@ -1095,6 +1309,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* exp = exp->mRight; } break; + + case EX_CLEANUP: + { + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); + return vl; + } + case EX_CONSTANT: dec = exp->mDecValue; switch (dec->mType) @@ -2510,7 +2732,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (doInline) { - return TranslateInline(procType, proc, block, exp, breakBlock, continueBlock, inlineMapper, inlineConstexpr); + return TranslateInline(procType, proc, block, exp, breakBlock, continueBlock, inlineMapper, inlineConstexpr, lrexp); } else { @@ -2659,6 +2881,31 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ExValue vp(pdec ? pdec->mBase : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); + if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE && texp->mType == EX_CALL) + { + mErrors->Error(texp->mLocation, EERR_MISSING_TEMP, "Missing temporary variable"); +#if 0 + int nindex = proc->mNumLocals++; + + Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + vdec->mVarIndex = nindex; + vdec->mBase = pdec->mBase->mBase; + vdec->mSize = pdec->mBase->mBase->mSize; + + InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); + vins->mDst.mType = IT_POINTER; + vins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + vins->mConst.mMemory = IM_LOCAL; + vins->mConst.mVarIndex = nindex; + vins->mConst.mOperandSize = vdec->mSize; + block->Append(vins); + + vp.mType = pdec->mBase->mBase; + vp.mTemp = vins->mDst.mTemp; +#endif + } + vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, &vp); if (!(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) @@ -2673,6 +2920,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vp.mTemp != vr.mTemp) { + CopyStruct(proc, exp, block, vp, vr, inlineMapper); +#if 0 InterInstruction* cins = new InterInstruction(texp->mLocation, IC_COPY); cins->mSrc[0].mType = IT_POINTER; cins->mSrc[0].mTemp = vr.mTemp; @@ -2687,6 +2936,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* cins->mConst.mOperandSize = vp.mType->mSize; block->Append(cins); +#endif } atotal += vr.mType->mSize; @@ -2932,21 +3182,33 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (inlineMapper) { - InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); - ains->mDst.mType = IT_POINTER; - ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); - ains->mConst.mOperandSize = procType->mBase->mSize; - ains->mConst.mIntConst = 0; - ains->mConst.mVarIndex = inlineMapper->mResult;; - ains->mConst.mMemory = IM_LOCAL; - block->Append(ains); + if (inlineMapper->mResultExp) + { + ins->mSrc[1].mType = IT_POINTER; + ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mCode = IC_STORE; + ins->mSrc[1].mOperandSize = 2; + ins->mNumOperands = 2; + } + else + { + InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ains->mConst.mOperandSize = procType->mBase->mSize; + ains->mConst.mIntConst = 0; + ains->mConst.mVarIndex = inlineMapper->mResult;; + ains->mConst.mMemory = IM_LOCAL; + block->Append(ains); - ins->mSrc[1].mType = ains->mDst.mType; - ins->mSrc[1].mTemp = ains->mDst.mTemp; - ins->mSrc[1].mMemory = IM_INDIRECT; - ins->mCode = IC_STORE; - ins->mSrc[1].mOperandSize = ains->mConst.mOperandSize; - ins->mNumOperands = 2; + ins->mSrc[1].mType = ains->mDst.mType; + ins->mSrc[1].mTemp = ains->mDst.mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mCode = IC_STORE; + ins->mSrc[1].mOperandSize = ains->mConst.mOperandSize; + ins->mNumOperands = 2; + } } else { @@ -2969,14 +3231,21 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (inlineMapper) { - ains->mCode = IC_CONSTANT; - ains->mDst.mType = IT_POINTER; - ains->mDst.mTemp = proc->AddTemporary(IT_POINTER); - ains->mConst.mOperandSize = procType->mBase->mSize; - ains->mConst.mIntConst = 0; - ains->mConst.mVarIndex = inlineMapper->mResult; - ains->mConst.mMemory = IM_LOCAL; - block->Append(ains); + if (inlineMapper->mResultExp) + { + ains->mDst.mTemp = inlineMapper->mResultExp->mTemp; + } + else + { + ains->mCode = IC_CONSTANT; + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(IT_POINTER); + ains->mConst.mOperandSize = procType->mBase->mSize; + ains->mConst.mIntConst = 0; + ains->mConst.mVarIndex = inlineMapper->mResult; + ains->mConst.mMemory = IM_LOCAL; + block->Append(ains); + } ins->mCode = IC_NONE; } @@ -3009,20 +3278,102 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mCode = IC_RETURN; } - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); - cins->mSrc[0].mType = IT_POINTER; - cins->mSrc[0].mTemp = vr.mTemp; - cins->mSrc[0].mMemory = IM_INDIRECT; - cins->mSrc[0].mOperandSize = procType->mBase->mSize; - cins->mSrc[0].mStride = vr.mType->mStripe; + CopyStruct(proc, exp, block, ExValue(procType->mBase, ains->mDst.mTemp), vr, inlineMapper); +#if 0 + if (procType->mBase->mCopyConstructor) + { + Declaration* ccdec = procType->mBase->mCopyConstructor; + if (ccdec->mBase->mFlags & DTF_FASTCALL) + { + if (!ccdec->mLinkerObject) + this->TranslateProcedure(proc->mModule, ccdec->mValue, ccdec); - cins->mSrc[1].mOperandSize = procType->mBase->mSize; - cins->mSrc[1].mType = IT_POINTER; - cins->mSrc[1].mTemp = ains->mDst.mTemp; - cins->mSrc[1].mMemory = IM_INDIRECT; + InterInstruction* psins = new InterInstruction(exp->mLocation, IC_CONSTANT); + psins->mDst.mType = IT_POINTER; + psins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + psins->mConst.mVarIndex = 0; + psins->mConst.mIntConst = 0; + psins->mConst.mOperandSize = 2; + if (procType->mFlags & DTF_FASTCALL) + { + psins->mConst.mMemory = IM_FPARAM; + psins->mConst.mVarIndex += ccdec->mBase->mFastCallBase; + } + else + psins->mConst.mMemory = IM_PARAM; + block->Append(psins); - cins->mConst.mOperandSize = procType->mBase->mSize; - block->Append(cins); + InterInstruction* ssins = new InterInstruction(exp->mLocation, IC_STORE); + ssins->mSrc[0] = ains->mDst; + ssins->mSrc[1] = psins->mDst; + block->Append(ssins); + + InterInstruction* plins = new InterInstruction(exp->mLocation, IC_CONSTANT); + plins->mDst.mType = IT_POINTER; + plins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + plins->mConst.mVarIndex = 2; + plins->mConst.mIntConst = 0; + plins->mConst.mOperandSize = 2; + if (procType->mFlags & DTF_FASTCALL) + { + plins->mConst.mMemory = IM_FPARAM; + plins->mConst.mVarIndex += ccdec->mBase->mFastCallBase; + } + else + plins->mConst.mMemory = IM_PARAM; + block->Append(plins); + + InterInstruction* slins = new InterInstruction(exp->mLocation, IC_STORE); + slins->mSrc[0].mType = IT_POINTER; + slins->mSrc[0].mTemp = vr.mTemp; + slins->mSrc[0].mMemory = IM_INDIRECT; + slins->mSrc[0].mOperandSize = procType->mBase->mSize; + slins->mSrc[0].mStride = vr.mType->mStripe; + slins->mSrc[1] = plins->mDst; + block->Append(slins); + + proc->AddCalledFunction(proc->mModule->mProcedures[ccdec->mVarIndex]); + + InterInstruction* pcins = new InterInstruction(exp->mLocation, IC_CONSTANT); + pcins->mDst.mType = IT_POINTER; + pcins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + pcins->mConst.mType = IT_POINTER; + pcins->mConst.mVarIndex = ccdec->mVarIndex; + pcins->mConst.mIntConst = 0; + pcins->mConst.mOperandSize = 2; + pcins->mConst.mMemory = IM_GLOBAL; + pcins->mConst.mLinkerObject = ccdec->mLinkerObject; + block->Append(pcins); + + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CALL); + if (ccdec->mFlags & DTF_NATIVE) + cins->mCode = IC_CALL_NATIVE; + else + cins->mCode = IC_CALL; + cins->mSrc[0] = pcins->mDst; + cins->mNumOperands = 1; + + block->Append(cins); + } + } + else + { + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + cins->mSrc[0].mType = IT_POINTER; + cins->mSrc[0].mTemp = vr.mTemp; + cins->mSrc[0].mMemory = IM_INDIRECT; + cins->mSrc[0].mOperandSize = procType->mBase->mSize; + cins->mSrc[0].mStride = vr.mType->mStripe; + + cins->mSrc[1].mOperandSize = procType->mBase->mSize; + cins->mSrc[1].mType = IT_POINTER; + cins->mSrc[1].mTemp = ains->mDst.mTemp; + cins->mSrc[1].mMemory = IM_INDIRECT; + + cins->mConst.mOperandSize = procType->mBase->mSize; + block->Append(cins); + } +#endif } else { @@ -3040,21 +3391,33 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (inlineMapper) { - InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); - ains->mDst.mType = IT_POINTER; - ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); - ains->mConst.mOperandSize = procType->mBase->mSize; - ains->mConst.mIntConst = 0; - ains->mConst.mVarIndex = inlineMapper->mResult;; - ains->mConst.mMemory = IM_LOCAL; - block->Append(ains); + if (inlineMapper->mResultExp) + { + ins->mSrc[1].mType = IT_POINTER; + ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mCode = IC_STORE; + ins->mSrc[1].mOperandSize = procType->mBase->mSize; + ins->mNumOperands = 2; + } + else + { + InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ains->mConst.mOperandSize = procType->mBase->mSize; + ains->mConst.mIntConst = 0; + ains->mConst.mVarIndex = inlineMapper->mResult;; + ains->mConst.mMemory = IM_LOCAL; + block->Append(ains); - ins->mSrc[1].mType = ains->mDst.mType; - ins->mSrc[1].mTemp = ains->mDst.mTemp; - ins->mSrc[1].mMemory = IM_INDIRECT; - ins->mCode = IC_STORE; - ins->mSrc[1].mOperandSize = ains->mConst.mOperandSize; - ins->mNumOperands = 2; + ins->mSrc[1].mType = ains->mDst.mType; + ins->mSrc[1].mTemp = ains->mDst.mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mCode = IC_STORE; + ins->mSrc[1].mOperandSize = ains->mConst.mOperandSize; + ins->mNumOperands = 2; + } } else { @@ -3075,7 +3438,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mCode = IC_RETURN; } - UnwindDestructStack(procType, proc, block, destack, nullptr); + UnwindDestructStack(procType, proc, block, destack, nullptr, inlineMapper); if (ins->mCode != IC_NONE) block->Append(ins); @@ -3097,7 +3460,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { if (breakBlock.mBlock) { - UnwindDestructStack(procType, proc, block, destack, breakBlock.mStack); + UnwindDestructStack(procType, proc, block, destack, breakBlock.mStack, inlineMapper); InterInstruction * jins = new InterInstruction(exp->mLocation, IC_JUMP); block->Append(jins); @@ -3114,7 +3477,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { if (continueBlock.mBlock) { - UnwindDestructStack(procType, proc, block, destack, continueBlock.mStack); + UnwindDestructStack(procType, proc, block, destack, continueBlock.mStack, inlineMapper); InterInstruction * jins = new InterInstruction(exp->mLocation, IC_JUMP); block->Append(jins); @@ -3508,7 +3871,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); destack = odestack; return ExValue(TheVoidTypeDeclaration); @@ -3536,7 +3899,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = TranslateExpression(procType, proc, bblock, exp->mRight, destack, BranchTarget(eblock, odestack), BranchTarget(lblock, idestack), inlineMapper); - UnwindDestructStack(procType, proc, bblock, destack, idestack); + UnwindDestructStack(procType, proc, bblock, destack, idestack, inlineMapper); destack = idestack; bblock->Append(jins1); @@ -3544,7 +3907,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block = eblock; - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); destack = odestack; return ExValue(TheVoidTypeDeclaration); @@ -3565,7 +3928,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* DestructStack* itdestack = destack; vr = TranslateExpression(procType, proc, tblock, exp->mRight->mLeft, destack, breakBlock, continueBlock, inlineMapper); - UnwindDestructStack(procType, proc, tblock, destack, itdestack); + UnwindDestructStack(procType, proc, tblock, destack, itdestack, inlineMapper); destack = itdestack; tblock->Append(jins0); @@ -3575,7 +3938,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { DestructStack* ifdestack = destack; vr = TranslateExpression(procType, proc, fblock, exp->mRight->mRight, destack, breakBlock, continueBlock, inlineMapper); - UnwindDestructStack(procType, proc, fblock, destack, ifdestack); + UnwindDestructStack(procType, proc, fblock, destack, ifdestack, inlineMapper); destack = ifdestack; } fblock->Append(jins1); @@ -3583,7 +3946,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block = eblock; - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); destack = odestack; return ExValue(TheVoidTypeDeclaration); @@ -3626,7 +3989,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = TranslateExpression(procType, proc, bblock, exp->mRight, destack, BranchTarget(eblock, odestack), BranchTarget(iblock, idestack), inlineMapper); - UnwindDestructStack(procType, proc, bblock, destack, idestack); + UnwindDestructStack(procType, proc, bblock, destack, idestack, inlineMapper); destack = idestack; bblock->Append(jins2); @@ -3641,7 +4004,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block = eblock; - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); destack = odestack; return ExValue(TheVoidTypeDeclaration); @@ -3664,14 +4027,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = TranslateExpression(procType, proc, cblock, exp->mRight, destack, BranchTarget(eblock, odestack), BranchTarget(cblock, idestack), inlineMapper); - UnwindDestructStack(procType, proc, cblock, destack, idestack); + UnwindDestructStack(procType, proc, cblock, destack, idestack, inlineMapper); destack = idestack; TranslateLogic(procType, proc, cblock, lblock, eblock, exp->mLeft, destack, inlineMapper); block = eblock; - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); destack = odestack; return ExValue(TheVoidTypeDeclaration); @@ -3759,7 +4122,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (block) { - UnwindDestructStack(procType, proc, block, destack, odestack); + UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); @@ -3962,6 +4325,11 @@ 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)); +#if 0 + if (proc->mIdent && !strcmp(proc->mIdent->mString, "test_retparam_value")) + exp->Dump(0); +#endif + uint64 outerCompilerOptions = mCompilerOptions; mCompilerOptions = dec->mCompilerOptions; @@ -4050,7 +4418,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod TranslateExpression(dec->mBase, proc, exitBlock, exp, destack, BranchTarget(), BranchTarget(), nullptr); - UnwindDestructStack(dec->mBase, proc, exitBlock, destack, nullptr); + UnwindDestructStack(dec->mBase, proc, exitBlock, destack, nullptr, nullptr); } else mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent->mString); diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 8a768d8..4088beb 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -59,9 +59,10 @@ protected: InterCodeBasicBlock * mReturn; int mResult, mDepth, mVarIndex; bool mConstExpr; + ExValue * mResultExp; InlineMapper(void) - : mParams(-1), mResult(-1), mDepth(0) + : mParams(-1), mResult(-1), mDepth(0), mResultExp(nullptr) {} }; @@ -79,8 +80,9 @@ protected: ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type, bool checkTrunc = true); ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper); - ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr); + ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp); + void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper); - void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom); + void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom, InlineMapper* inlineMapper); void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable); }; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index d245355..2226e4e 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -34621,6 +34621,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; progress = true; } + else if ( mIns[i + 0].mType == ASMIT_INX && mIns[i + 1].mType == ASMIT_DEX && !(mIns[i + 1].mLive & LIVE_CPU_REG_Z)) @@ -34654,6 +34655,39 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_LDX && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_DEX) + { + mIns[i + 0].mAddress = (mIns[i + 0].mAddress - 1) & 255; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_LDX && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_INX) + { + mIns[i + 0].mAddress = (mIns[i + 0].mAddress + 1) & 255; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_DEY) + { + mIns[i + 0].mAddress = (mIns[i + 0].mAddress - 1) & 255; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_INY) + { + mIns[i + 0].mAddress = (mIns[i + 0].mAddress + 1) & 255; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + progress = true; + } + else if ( mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_IMMEDIATE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ABSOLUTE_X) && mIns[i + 1].mType == ASMIT_TAY && !(mIns[i + 1].mLive & LIVE_CPU_REG_A)) @@ -34952,7 +34986,10 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass if (FindPageStartAddress(i, mIns[i + 1].mAddress, addr)) { if (mIns[i + 1].mLive & LIVE_CPU_REG_Y) + { mIns.Insert(i + 2, mIns[i + 0]); + mIns[i + 2].mLive |= mIns[i + 1].mLive; + } int absaddr = addr + mIns[i + 0].mAddress; @@ -39997,7 +40034,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "mapTimeTick"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "Y::Y"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41273,7 +41310,6 @@ void NativeCodeProcedure::Optimize(void) } while (changed); - #if 1 ResetVisited(); mEntryBlock->ReduceLocalYPressure(); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 3bf165a..7ac9e9c 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -205,6 +205,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mCompilerOptions & COPT_CPLUSPLUS) { + AddDefaultConstructors(pthis); + Declaration* cdec = pthis->mBase->mConstructor; while (cdec) { @@ -1225,60 +1227,64 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) thisexp->mLeft = pthisexp; Declaration* dec = pthis->mBase->mParams; - while (dec) + if (dec) { - if (dec->mType == DT_ELEMENT) + dec = dec->Last(); + while (dec) { - Declaration* mfunc = cfunc->mScope ? cfunc->mScope->Lookup(dec->mIdent) : nullptr; - - if (mfunc) + if (dec->mType == DT_ELEMENT) { - Expression* sexp = new Expression(cfunc->mLocation, EX_SEQUENCE); - sexp->mLeft = mfunc->mValue; - sexp->mRight = cfunc->mValue; - cfunc->mValue = sexp; - } - else if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mConstructor) - { - Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); - qexp->mLeft = thisexp; - qexp->mDecValue = dec; - qexp->mDecType = dec->mBase; + Declaration* mfunc = cfunc->mScope ? cfunc->mScope->Lookup(dec->mIdent) : nullptr; - Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); - pexp->mLeft = qexp; - pexp->mToken = TK_BINARY_AND; - pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); - pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - pexp->mDecType->mBase = dec->mBase; - pexp->mDecType->mSize = 2; - - Declaration* mdec = dec->mBase->mConstructor; - while (mdec && mdec->mBase->mParams->mNext) - mdec = mdec->mNext; - - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - if (mdec) + if (mfunc) { - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* sexp = new Expression(cfunc->mLocation, EX_SEQUENCE); + sexp->mLeft = mfunc->mValue; + sexp->mRight = cfunc->mValue; + cfunc->mValue = sexp; } - else - mErrors->Error(dec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor"); + else if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mConstructor) + { + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; + qexp->mDecType = dec->mBase; - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = qexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + Declaration* mdec = dec->mBase->mConstructor; + while (mdec && mdec->mBase->mParams->mNext) + mdec = mdec->mNext; - sexp->mLeft = dexp; - sexp->mRight = cfunc->mValue; - cfunc->mValue = sexp; + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + if (mdec) + { + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + } + else + mErrors->Error(dec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor"); + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = cfunc->mValue; + cfunc->mValue = sexp; + } } - } - dec = dec->mNext; + dec = dec->mPrev; + } } } @@ -1339,29 +1345,32 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc) mThisPointer = othis; } -void Parser::AppendMemberDestructor(Declaration* pthis) +void Parser::AddDefaultConstructors(Declaration* pthis) { - bool needDestructor = !pthis->mBase->mDestructor; + bool simpleDestructor = true, simpleAssignment = true; Declaration* dec = pthis->mBase->mParams; - while (!needDestructor && dec) + while (dec) { - if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT) { - needDestructor = true; - break; + if (dec->mBase->mDestructor) + simpleDestructor = false; + if (dec->mBase->mCopyAssignment) + simpleAssignment = false; } dec = dec->mNext; } - if (needDestructor) + if (!simpleDestructor) { if (!pthis->mBase->mDestructor) { - Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); - - if (ctdec->mParams) - mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Destructor can't have parameter"); + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; PrependThisArgument(ctdec, pthis); @@ -1376,10 +1385,7 @@ void Parser::AppendMemberDestructor(Declaration* pthis) if (mCompilerOptions & COPT_NATIVE) cdec->mFlags |= DTF_NATIVE; - if (pthis->mBase->mDestructor) - mErrors->Error(ctdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate destrcutor definition"); - else - pthis->mBase->mDestructor = cdec; + pthis->mBase->mDestructor = cdec; char dname[100]; strcpy_s(dname, "~"); @@ -1394,8 +1400,319 @@ void Parser::AppendMemberDestructor(Declaration* pthis) cdec->mFlags |= DTF_DEFINED; cdec->mNumVars = mLocalIndex; + + cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); } + if (!pthis->mBase->mConstructor) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + PrependThisArgument(ctdec, pthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + pthis->mBase->mConstructor = cdec; + + cdec->mIdent = pthis->mBase->mIdent; + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + + cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); + } + + if (!pthis->mBase->mCopyConstructor) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 0; + adec->mOffset = 0; + adec->mBase = new Declaration(mScanner->mLocation, DT_TYPE_REFERENCE); + adec->mBase->mSize = 2; + adec->mBase->mBase = pthis->mBase; + adec->mBase->mFlags |= DTF_CONST | DTF_DEFINED; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("_"); + + ctdec->mParams = adec; + + PrependThisArgument(ctdec, pthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + pthis->mBase->mCopyConstructor = cdec; + cdec->mNext = pthis->mBase->mConstructor; + pthis->mBase->mConstructor = cdec; + + cdec->mIdent = pthis->mBase->mIdent; + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); + + // Now add all the copying + + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); + pthisexp->mDecType = pthis; + pthisexp->mDecValue = cdec->mBase->mParams; + + Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); + thisexp->mToken = TK_MUL; + thisexp->mDecType = pthis->mBase; + thisexp->mLeft = pthisexp; + + Expression* thatexp = new Expression(pthis->mLocation, EX_VARIABLE); + thatexp->mDecType = adec->mBase; + thatexp->mDecValue = cdec->mBase->mParams->mNext; + + cdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS); + + Declaration* dec = pthis->mBase->mParams; + while (dec) + { + if (dec->mType == DT_ELEMENT) + { + Expression* lexp = new Expression(pthis->mLocation, EX_QUALIFY); + lexp->mLeft = thisexp; + lexp->mDecValue = dec; + lexp->mDecType = dec->mBase; + + Expression* rexp = new Expression(pthis->mLocation, EX_QUALIFY); + rexp->mLeft = thatexp; + rexp->mDecValue = dec; + rexp->mDecType = dec->mBase; + + Expression* mexp; + + if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mCopyConstructor) + { + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = lexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; + + Declaration* mdec = dec->mBase->mCopyConstructor; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + mexp = new Expression(mScanner->mLocation, EX_CALL); + mexp->mLeft = cexp; + mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mLeft = pexp; + mexp->mRight->mRight = rexp; + } + else + { + mexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + mexp->mLeft = lexp; + mexp->mRight = rexp; + mexp->mDecType = lexp->mDecType; + } + + Declaration* mcdec = new Declaration(mScanner->mLocation, DT_CONST_CONSTRUCTOR); + mcdec->mIdent = mScanner->mTokenIdent; + mcdec->mValue = mexp; + + cdec->mScope->Insert(dec->mIdent, mcdec); + } + + dec = dec->mNext; + } + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + } + } + + if (!simpleAssignment) + { + // Copy assignment operator + if (!pthis->mBase->mCopyAssignment) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + ctdec->mBase = new Declaration(mScanner->mLocation, DT_TYPE_REFERENCE); + ctdec->mBase->mSize = 2; + ctdec->mBase->mBase = pthis->mBase; + ctdec->mBase->mFlags |= DTF_DEFINED; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 0; + adec->mOffset = 0; + adec->mBase = new Declaration(mScanner->mLocation, DT_TYPE_REFERENCE); + adec->mBase->mSize = 2; + adec->mBase->mBase = pthis->mBase; + adec->mBase->mFlags |= DTF_CONST | DTF_DEFINED; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("_"); + + ctdec->mParams = adec; + + PrependThisArgument(ctdec, pthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + cdec->mIdent = Ident::Unique("operator="); + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + pthis->mBase->mCopyAssignment = cdec; + Declaration* pdec = pthis->mBase->mScope->Insert(cdec->mIdent, cdec); + if (pdec) + { + cdec->mNext = pdec->mNext; + pdec->mNext = cdec; + } + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); + pthisexp->mDecType = pthis; + pthisexp->mDecValue = cdec->mBase->mParams; + + Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); + thisexp->mToken = TK_MUL; + thisexp->mDecType = pthis->mBase; + thisexp->mLeft = pthisexp; + + cdec->mValue = new Expression(mScanner->mLocation, EX_RETURN); + cdec->mValue->mLeft = thisexp; + cdec->mValue->mDecType = cdec->mBase; + + // Now add all the copying + + Expression* thatexp = new Expression(pthis->mLocation, EX_VARIABLE); + thatexp->mDecType = adec->mBase; + thatexp->mDecValue = cdec->mBase->mParams->mNext; + + cdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS); + + Declaration* dec = pthis->mBase->mParams; + if (dec) + { + dec = dec->Last(); + while (dec) + { + if (dec->mType == DT_ELEMENT) + { + Expression* lexp = new Expression(pthis->mLocation, EX_QUALIFY); + lexp->mLeft = thisexp; + lexp->mDecValue = dec; + lexp->mDecType = dec->mBase; + + Expression* rexp = new Expression(pthis->mLocation, EX_QUALIFY); + rexp->mLeft = thatexp; + rexp->mDecValue = dec; + rexp->mDecType = dec->mBase; + + Expression* mexp; + + if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mCopyAssignment) + { + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = lexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; + + Declaration* mdec = dec->mBase->mCopyAssignment; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + mexp = new Expression(mScanner->mLocation, EX_CALL); + mexp->mLeft = cexp; + mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mLeft = pexp; + mexp->mRight->mRight = rexp; + } + else + { + mexp = new Expression(mScanner->mLocation, EX_ASSIGNMENT); + mexp->mToken = TK_ASSIGN; + mexp->mLeft = lexp; + mexp->mRight = rexp; + mexp->mDecType = lexp->mDecType; + } + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + sexp->mLeft = mexp; + sexp->mRight = cdec->mValue; + cdec->mValue = sexp; + } + + dec = dec->mPrev; + } + } + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + + } + } +} + +void Parser::AppendMemberDestructor(Declaration* pthis) +{ + if (pthis->mBase->mDestructor) + { if (pthis->mBase->mDestructor->mFlags & DTF_DEFINED) { Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); @@ -1407,41 +1724,45 @@ void Parser::AppendMemberDestructor(Declaration* pthis) thisexp->mDecType = pthis->mBase; thisexp->mLeft = pthisexp; - dec = pthis->mBase->mParams; - while (dec) + Declaration * dec = pthis->mBase->mParams; + if (dec) { - if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + dec = dec->Last(); + while (dec) { - Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); - qexp->mLeft = thisexp; - qexp->mDecValue = dec; - qexp->mDecType = dec->mBase; + if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + { + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; + qexp->mDecType = dec->mBase; - Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); - pexp->mLeft = qexp; - pexp->mToken = TK_BINARY_AND; - pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); - pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - pexp->mDecType->mBase = dec->mBase; - pexp->mDecType->mSize = 2; + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = qexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - cexp->mDecValue = dec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = dec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - sexp->mLeft = pthis->mBase->mDestructor->mValue; - sexp->mRight = dexp; + sexp->mLeft = pthis->mBase->mDestructor->mValue; + sexp->mRight = dexp; - pthis->mBase->mDestructor->mValue = sexp; + pthis->mBase->mDestructor->mValue = sexp; + } + + dec = dec->mPrev; } - - dec = dec->mNext; } } } @@ -1470,6 +1791,208 @@ void Parser::PrependThisArgument(Declaration* fdec, Declaration* pthis) fdec->mFlags |= DTF_FUNC_THIS; } +static Expression* ConcatExpression(Expression* e1, Expression* e2) +{ + if (e1) + { + if (e2) + { + Expression* seq = new Expression(e1->mLocation, EX_SEQUENCE); + seq->mLeft = e1; + seq->mRight = e2; + return seq; + } + return e1; + } + else + return e2; +} + +Expression* Parser::CleanupExpression(Expression* exp) +{ + if (exp) + { + Expression* xexp = AddFunctionCallRefReturned(exp); + if (xexp) + { + Expression* cexp = new Expression(exp->mLocation, EX_CLEANUP); + cexp->mLeft = exp; + cexp->mRight = xexp; + return cexp; + } + } + return exp; +} + +Expression* Parser::AddFunctionCallRefReturned(Expression* exp) +{ + Expression* lexp = nullptr, * rexp = nullptr; + + if (exp->mType == EX_CALL) + { + lexp = AddFunctionCallRefReturned(exp->mLeft); + if (exp->mRight) + { + Declaration* pdec = exp->mLeft->mDecType->mParams; + Expression* rex = exp->mRight; + + while (pdec && rex) + { + Expression* pex = rex->mType == EX_LIST ? rex->mLeft : rex; + if (rex->mType == EX_LIST) + rex = rex->mRight; + else + rex = nullptr; + + rexp = ConcatExpression(rexp, AddFunctionCallRefReturned(pex)); + + if (pdec->mBase->mType == DT_TYPE_REFERENCE && pex->mDecType->mType != DT_TYPE_REFERENCE && pex->mType == EX_CALL) + { + // Returning a value object for pass as reference + // add a temporary variable + + int nindex = mLocalIndex++; + + Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + vdec->mVarIndex = nindex; + vdec->mBase = pdec->mBase->mBase; + vdec->mSize = pdec->mBase->mBase->mSize; + + Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE); + vexp->mDecType = pdec->mBase->mBase; + vexp->mDecValue = vdec; + + Expression* cexp = new Expression(pex->mLocation, pex->mType); + cexp->mDecType = pex->mDecType; + cexp->mDecValue = pex->mDecValue; + cexp->mLeft = pex->mLeft; + cexp->mRight = pex->mRight; + cexp->mToken = pex->mToken; + + pex->mType = EX_INITIALIZATION; + pex->mLeft = vexp; + pex->mRight = cexp; + pex->mDecValue = nullptr; + pex->mDecType = vdec->mBase; + + if (vdec->mBase->mDestructor) + { + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = vdec->mBase; + texp->mDecType->mSize = 2; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = vdec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression * dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + + rexp = ConcatExpression(rexp, dexp); + } + } + + pdec = pdec->mNext; + } + } + } + else + { + if (exp->mLeft) + lexp = AddFunctionCallRefReturned(exp->mLeft); + if (exp->mRight) + rexp = AddFunctionCallRefReturned(exp->mRight); + } + + return ConcatExpression(lexp, rexp); +} + +void Parser::ParseVariableInit(Declaration* ndec) +{ + Expression* pexp = nullptr; + + mScanner->NextToken(); + if (mScanner->mToken != TK_CLOSE_PARENTHESIS) + { + pexp = ParseListExpression(); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } + else + mScanner->NextToken(); + + if (pexp && pexp->mType != EX_LIST && ndec->mBase->CanAssign(pexp->mDecType)) + { + ndec->mValue = pexp; + } + else if (ndec->mBase->mConstructor) + { + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = ndec->mBase; + vexp->mDecValue = ndec; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = ndec->mBase->mConstructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = pexp; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = ndec->mBase; + texp->mDecType->mSize = 2; + + if (fexp->mRight) + { + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = fexp->mRight; + fexp->mRight = lexp; + } + else + fexp->mRight = texp; + + ResolveOverloadCall(cexp, fexp->mRight); + + Expression* dexp = nullptr; + if (ndec->mBase->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = ndec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + ndec->mValue = nexp; + } + else + { + ndec->mValue = pexp; + } +} + Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis) { bool definingType = false, destructor = false; @@ -1658,9 +2181,14 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + + if (ctdec->mParams && !ctdec->mParams->mNext && ctdec->mParams->mBase->mType == DT_TYPE_REFERENCE && + pthis->mBase->IsConstSame(ctdec->mParams->mBase->mBase)) + pthis->mBase->mCopyConstructor = cdec; + PrependThisArgument(ctdec, pthis); - Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); @@ -1763,6 +2291,8 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (cdec) { + cdec->mFlags |= storageFlags & DTF_REQUEST_INLINE; + // Initializer list if (mScanner->mToken == TK_COLON) { @@ -1814,6 +2344,8 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (bdec->mDestructor) { + bdec->mDestructor->mFlags |= storageFlags & DTF_REQUEST_INLINE; + Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); bthis->mFlags |= DTF_CONST | DTF_DEFINED; bthis->mBase = bdec; @@ -1880,7 +2412,16 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) { + if (ndec->mIdent == Ident::Unique("operator==")) + { + if (ndec->mBase->mParams && ndec->mBase->mParams->mBase->mType == DT_TYPE_REFERENCE && ndec->mBase->mParams->mBase->mBase->IsSame(pthis->mBase)) + { + pthis->mBase->mCopyAssignment = ndec; + } + } + PrependThisArgument(ndec->mBase, pthis); + } if (variable) @@ -2072,74 +2613,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else if (mScanner->mToken == TK_OPEN_PARENTHESIS && (mCompilerOptions & COPT_CPLUSPLUS)) { - if (ndec->mBase->mConstructor) - { - Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); - vexp->mDecType = ndec->mBase; - vexp->mDecValue = ndec; - - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = ndec->mBase->mConstructor; - cexp->mDecType = cexp->mDecValue->mBase; - - Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); - fexp->mLeft = cexp; - - mScanner->NextToken(); - if (mScanner->mToken != TK_CLOSE_PARENTHESIS) - { - fexp->mRight = ParseListExpression(); - ConsumeToken(TK_CLOSE_PARENTHESIS); - } - else - { - fexp->mRight = nullptr; - mScanner->NextToken(); - } - - Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); - texp->mToken = TK_BINARY_AND; - texp->mLeft = vexp; - texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); - texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = ndec->mBase; - texp->mDecType->mSize = 2; - - if (fexp->mRight) - { - Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); - lexp->mLeft = texp; - lexp->mRight = fexp->mRight; - fexp->mRight = lexp; - } - else - fexp->mRight = texp; - - ResolveOverloadCall(cexp, fexp->mRight); - - Expression* dexp = nullptr; - if (ndec->mBase->mDestructor) - { - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = ndec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; - - dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = texp; - } - - Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); - - nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); - nexp->mLeft->mLeft = fexp; - nexp->mLeft->mRight = dexp; - - nexp->mRight = vexp; - nexp->mDecType = vexp->mDecType; - - ndec->mValue = nexp; - } + ParseVariableInit(ndec); } else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mBase->mConstructor && ndec->mType == DT_VARIABLE && !pthis) { @@ -2269,6 +2743,63 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) vdec->mDecValue = dec; } } + else if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mBase->mDestructor) + { + Expression* vexp = new Expression(pdec->mLocation, EX_VARIABLE); + vexp->mDecType = dec->mBase; + vexp->mDecValue = dec; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = pdec->mBase; + texp->mDecType->mSize = 2; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = dec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + + Expression* aexp; + + if (dec->mBase->mCopyConstructor && !(dec->mValue->mType == EX_CALL && dec->mValue->mDecType->mType == DT_TYPE_STRUCT)) + { + Declaration* mdec = dec->mBase->mCopyConstructor; + + Expression* cexp = new Expression(dec->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + aexp = new Expression(mScanner->mLocation, EX_CALL); + aexp->mLeft = cexp; + aexp->mRight = new Expression(dec->mLocation, EX_LIST); + aexp->mRight->mLeft = texp; + aexp->mRight->mRight = dec->mValue; + } + else + { + aexp = new Expression(dec->mValue->mLocation, EX_INITIALIZATION); + aexp->mToken = TK_ASSIGN; + aexp->mLeft = new Expression(dec->mLocation, EX_VARIABLE); + aexp->mLeft->mDecValue = dec; + aexp->mLeft->mDecType = dec->mBase; + aexp->mDecType = aexp->mLeft->mDecType; + aexp->mRight = dec->mValue; + } + + nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = aexp; + nexp->mLeft->mRight = dexp; + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + } else { nexp = new Expression(dec->mValue->mLocation, EX_INITIALIZATION); @@ -2914,7 +3445,23 @@ Expression* Parser::ParsePostfixExpression(bool lhs) { if (exp->mType == EX_TYPE) { - if (exp->mDecType->mConstructor) + Expression * pexp = nullptr; + + mScanner->NextToken(); + if (mScanner->mToken != TK_CLOSE_PARENTHESIS) + { + pexp = ParseListExpression(); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } + else + mScanner->NextToken(); + + if (pexp && pexp->mType != EX_LIST && pexp->mDecType->IsSame(exp->mDecType)) + { + // Simple copy + exp = pexp; + } + else if (exp->mDecType->mConstructor) { Declaration* tdec = new Declaration(mScanner->mLocation, DT_VARIABLE); @@ -2934,17 +3481,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); fexp->mLeft = cexp; - mScanner->NextToken(); - if (mScanner->mToken != TK_CLOSE_PARENTHESIS) - { - fexp->mRight = ParseListExpression(); - ConsumeToken(TK_CLOSE_PARENTHESIS); - } - else - { - fexp->mRight = nullptr; - mScanner->NextToken(); - } + fexp->mRight = pexp; Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); texp->mToken = TK_BINARY_AND; @@ -2994,9 +3531,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; nexp->mLeft = exp; - mScanner->NextToken(); - nexp->mRight = ParseListExpression(); - ConsumeToken(TK_CLOSE_PARENTHESIS); + nexp->mRight = pexp; exp = nexp->ConstantFold(mErrors); } } @@ -3414,6 +3949,55 @@ Expression* Parser::ParseParenthesisExpression(void) return exp; } +Expression* Parser::CheckOperatorOverload(Expression* exp) +{ + if (mCompilerOptions & COPT_CPLUSPLUS) + { + if (exp->mType == EX_ASSIGNMENT) + { + Declaration* tdec = exp->mLeft->mDecType; + if (tdec->mType == DT_TYPE_STRUCT) + { + if (exp->mToken == TK_ASSIGN) + { + Declaration* mdec = tdec->mScope->Lookup(Ident::Unique("operator=")); + if (mdec) + { + Expression * nexp = new Expression(mScanner->mLocation, EX_CALL); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + nexp->mRight = exp->mRight; + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp->mLeft; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = exp->mDecType; + texp->mDecType->mSize = 2; + + Expression* lexp = new Expression(nexp->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = nexp->mRight; + nexp->mRight = lexp; + + ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + + exp = nexp; + } + } + } + } + } + + return exp; +} + Expression* Parser::ParseAssignmentExpression(bool lhs) { Expression* exp = ParseConditionalExpression(lhs); @@ -3426,7 +4010,9 @@ Expression* Parser::ParseAssignmentExpression(bool lhs) mScanner->NextToken(); nexp->mRight = ParseAssignmentExpression(false); nexp->mDecType = exp->mDecType; - exp = nexp; + + exp = CheckOperatorOverload(nexp); + assert(exp->mDecType); } @@ -3475,6 +4061,53 @@ Expression* Parser::ParseFunction(Declaration * dec) Expression * exp = ParseStatement(); + if (mCompilerOptions & COPT_CPLUSPLUS) + { + // Add destructors for parameters + Declaration* pdec = dec->mParams; + + while (pdec) + { + if (pdec->mBase->mType == DT_TYPE_STRUCT && pdec->mBase->mDestructor) + { + Expression* vexp = new Expression(pdec->mLocation, EX_VARIABLE); + vexp->mDecType = pdec->mBase; + vexp->mDecValue = pdec; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = pdec->mBase; + texp->mDecType->mSize = 2; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = pdec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression * dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = nullptr; + nexp->mLeft->mRight = dexp; + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + sexp->mLeft = nexp; + sexp->mRight = exp; + exp = sexp; + } + + pdec = pdec->mNext; + } + } + mScope->End(mScanner->mLocation); mScope = mScope->mParent; @@ -3552,7 +4185,7 @@ Expression* Parser::ParseStatement(void) case TK_IF: mScanner->NextToken(); exp = new Expression(mScanner->mLocation, EX_IF); - exp->mLeft = ParseParenthesisExpression(); + exp->mLeft = CleanupExpression(ParseParenthesisExpression()); exp->mRight = new Expression(mScanner->mLocation, EX_ELSE); exp->mRight->mLeft = ParseStatement(); if (mScanner->mToken == TK_ELSE) @@ -3571,7 +4204,7 @@ Expression* Parser::ParseStatement(void) mScope = scope; exp = new Expression(mScanner->mLocation, EX_WHILE); - exp->mLeft = ParseParenthesisExpression(); + exp->mLeft = CleanupExpression(ParseParenthesisExpression()); exp->mRight = ParseStatement(); mScope->End(mScanner->mLocation); @@ -3585,7 +4218,7 @@ Expression* Parser::ParseStatement(void) if (mScanner->mToken == TK_WHILE) { mScanner->NextToken(); - exp->mLeft = ParseParenthesisExpression(); + exp->mLeft = CleanupExpression(ParseParenthesisExpression()); ConsumeToken(TK_SEMICOLON); } else @@ -3611,7 +4244,7 @@ Expression* Parser::ParseStatement(void) // Assignment if (mScanner->mToken != TK_SEMICOLON) - initExp = ParseExpression(true); + initExp = CleanupExpression(ParseExpression(true)); if (mScanner->mToken == TK_SEMICOLON) mScanner->NextToken(); else @@ -3619,7 +4252,7 @@ Expression* Parser::ParseStatement(void) // Condition if (mScanner->mToken != TK_SEMICOLON) - conditionExp = ParseExpression(false); + conditionExp = CleanupExpression(ParseExpression(false)); if (mScanner->mToken == TK_SEMICOLON) mScanner->NextToken(); @@ -3628,7 +4261,7 @@ Expression* Parser::ParseStatement(void) // Iteration if (mScanner->mToken != TK_CLOSE_PARENTHESIS) - iterateExp = ParseExpression(false); + iterateExp = CleanupExpression(ParseExpression(false)); if (mScanner->mToken == TK_CLOSE_PARENTHESIS) mScanner->NextToken(); else @@ -3804,7 +4437,7 @@ Expression* Parser::ParseStatement(void) mScanner->NextToken(); exp = new Expression(mScanner->mLocation, EX_RETURN); if (mScanner->mToken != TK_SEMICOLON) - exp->mLeft = ParseRExpression(); + exp->mLeft = CleanupExpression(ParseRExpression()); ConsumeToken(TK_SEMICOLON); break; case TK_BREAK: @@ -3846,7 +4479,7 @@ Expression* Parser::ParseStatement(void) break; default: - exp = ParseListExpression(); + exp = CleanupExpression(ParseListExpression()); ConsumeToken(TK_SEMICOLON); } } @@ -3863,7 +4496,7 @@ Expression* Parser::ParseSwitchStatement(void) if (mScanner->mToken == TK_OPEN_PARENTHESIS) { mScanner->NextToken(); - sexp->mLeft = ParseRExpression(); + sexp->mLeft = CleanupExpression(ParseRExpression()); if (mScanner->mToken == TK_CLOSE_PARENTHESIS) mScanner->NextToken(); else diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 2e0c661..e889bce 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -46,6 +46,13 @@ protected: Expression* BuildMemberInitializer(Expression* vexp); void PrependMemberConstructor(Declaration* pthis, Declaration* cfunc); + void AddDefaultConstructors(Declaration* pthis); + + void ParseVariableInit(Declaration* ndec); + + Expression * AddFunctionCallRefReturned(Expression * exp); + Expression* CleanupExpression(Expression* exp); + Declaration* ParseBaseTypeDeclaration(uint64 flags); Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr); Declaration* ParseStructDeclaration(uint64 flags, DecType dt); @@ -65,6 +72,8 @@ protected: Expression* ParseAssemblerAddOperand(Declaration* pcasm, int pcoffset); Expression* ParseAssemblerOperand(Declaration * pcasm, int pcoffset); + Expression* CheckOperatorOverload(Expression* exp); + void AddAssemblerRegister(const Ident* ident, int value); Declaration* ParseQualIdent(void); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 923167c..28905ef 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1394,6 +1394,17 @@ void Scanner::NextRawToken(void) mToken = TK_USING; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "this")) mToken = TK_THIS; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) + { + NextRawToken(); + if (mToken == TK_ASSIGN) + { + mToken = TK_IDENT; + mTokenIdent = Ident::Unique("operator="); + } + else + mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "Invalid operator token"); + } else { mToken = TK_IDENT; From 0f67f7150f8d009c02c527bba9bab1acf0ee5899 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 25 Jun 2023 16:16:26 +0200 Subject: [PATCH 006/169] Fix linux build --- autotest/autotest.bat | 3 + autotest/copyassign.cpp | 126 +++++++++++++++++++++++++++++++++++ autotest/copyconstructor.cpp | 2 +- oscar64/Parser.cpp | 20 +++--- 4 files changed, 141 insertions(+), 10 deletions(-) create mode 100644 autotest/copyassign.cpp diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 2b2ddd1..26e10c4 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -6,6 +6,9 @@ rem @echo off @call :test copyconstructor.cpp @if %errorlevel% neq 0 goto :error +@call :test copyassign.cpp +@if %errorlevel% neq 0 goto :error + @call :test stdlibtest.c @if %errorlevel% neq 0 goto :error diff --git a/autotest/copyassign.cpp b/autotest/copyassign.cpp new file mode 100644 index 0000000..886a321 --- /dev/null +++ b/autotest/copyassign.cpp @@ -0,0 +1,126 @@ +#include + +int t, n; + +struct C0 +{ + int u; + + C0(int a); + ~C0(void); +}; + +C0::C0(int a) : u(a) +{ + t += u; + n++; +} + +C0::~C0(void) +{ + t -= u; +} + +struct C1 +{ + int u; + + C1(int a); + ~C1(void); + C1(const C1 & c); + C1 & operator=(const C1 & c); +}; + +C1::C1(int a) : u(a) +{ + t += u; + n++; +} + +C1::~C1(void) +{ + t -= u; +} + +C1::C1(const C1 & c) : u(c.u) +{ + t += u; + n++; +} + +C1 & C1::operator=(const C1 & c) +{ + t -= u; + u = c.u; + t += u; + return *this; +} + +void test_assign(void) +{ + n = 0; + + { + C1 c(4); + C1 d(5); + c = d; + } + + assert(n == 2 && t == 0); +} + +struct C2 +{ + C1 a, b; + + C2(int x, int y) : a(x), b(y) + {} +}; + +void test_assign_deflt(void) +{ + n = 0; + + { + C2 c(2, 3); + C2 d(5, 10); + c = d; + } + + assert(n == 4 && t == 0); +} + +int k; + +C2 test_ret_v(void) +{ + C2 c(5, 10); + return c; +} + +C2 & test_ret_r(C2 & r) +{ + return r; +} + +void test_assign_return_value(void) +{ + n = 0; + + { + C2 c(2, 3); + c = test_ret_v(); + } + + assert(n == 6 && t == 0); +} + + +int main(void) +{ + test_assign(); + test_assign_deflt(); + test_assign_return_value(); + + return 0; +} diff --git a/autotest/copyconstructor.cpp b/autotest/copyconstructor.cpp index c16f30b..71f3d0f 100644 --- a/autotest/copyconstructor.cpp +++ b/autotest/copyconstructor.cpp @@ -108,7 +108,7 @@ void test_minit_copy(void) int k; -inline void test_param_fv(C2 c) +void test_param_fv(C2 c) { k += c.a.u; } diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 7ac9e9c..94863ce 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2412,9 +2412,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) { - if (ndec->mIdent == Ident::Unique("operator==")) + if (ndec->mIdent == Ident::Unique("operator=")) { - if (ndec->mBase->mParams && ndec->mBase->mParams->mBase->mType == DT_TYPE_REFERENCE && ndec->mBase->mParams->mBase->mBase->IsSame(pthis->mBase)) + if (ndec->mBase->mParams && ndec->mBase->mParams->mBase->mType == DT_TYPE_REFERENCE && ndec->mBase->mParams->mBase->mBase->IsConstSame(pthis->mBase)) { pthis->mBase->mCopyAssignment = ndec; } @@ -3308,6 +3308,8 @@ Expression* Parser::ParseQualify(Expression* exp) return exp; } +static const int NOOVERLOAD = 0x7fffffff; + int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) { Declaration* pdec = fdec->mParams; @@ -3352,17 +3354,17 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) if (ext) { if ((etype->mFlags & DTF_CONST) && !(ptype->mBase->mFlags & DTF_CONST)) - return INT_MAX; + return NOOVERLOAD; dist += 16 * ncast; } else - return INT_MAX; + return NOOVERLOAD; } else if (ptype->IsSubType(ex->mDecType)) dist += 256; else - return INT_MAX; + return NOOVERLOAD; pdec = pdec->mNext; } @@ -3372,11 +3374,11 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) break; } else - return INT_MAX; + return NOOVERLOAD; } if (pdec) - return INT_MAX; + return NOOVERLOAD; return dist; } @@ -3389,7 +3391,7 @@ void Parser::ResolveOverloadCall(Expression* cexp, Expression* pexp) if (fdec->mType == DT_CONST_FUNCTION && fdec->mNext) { Declaration* dbest = nullptr; - int ibest = INT_MAX, nbest = 0; + int ibest = NOOVERLOAD, nbest = 0; while (fdec) { @@ -3405,7 +3407,7 @@ void Parser::ResolveOverloadCall(Expression* cexp, Expression* pexp) fdec = fdec->mNext; } - if (ibest == INT_MAX) + if (ibest == NOOVERLOAD) mErrors->Error(cexp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call"); else if (nbest > 1) mErrors->Error(cexp->mLocation, ERRO_AMBIGUOUS_FUNCTION_CALL, "Ambiguous function call"); From 0b1b4a7d9b87ea1abf64078bf0a4c37303ee24fb Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 25 Jun 2023 22:24:13 +0200 Subject: [PATCH 007/169] Array constructors --- README.md | 17 +- autotest/arrayconstruct.cpp | 151 ++++++ autotest/autotest.bat | 3 + oscar64/Declaration.cpp | 3 +- oscar64/Declaration.h | 5 +- oscar64/InterCode.cpp | 2 +- oscar64/InterCodeGenerator.cpp | 7 + oscar64/NativeCodeGenerator.cpp | 1 + oscar64/Parser.cpp | 857 ++++++++++++++++++++++++++------ 9 files changed, 901 insertions(+), 145 deletions(-) create mode 100644 autotest/arrayconstruct.cpp diff --git a/README.md b/README.md index 7454ff7..5d18225 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The goal was also to implement the C99 standard and not some subset for performa After extensive optimizations it turns out, that the interpreted code is not significantly smaller than the native code in most scenarios (although there are cases where the difference is significant). - + ## Limits and Errors There are still several open areas, but most targets have been reached. The current Dhrystone performance is 94 iterations per second with byte code (11696) and 395 iterations with native code (10425 Bytes). This clearly shows that Dhrystone is not a valid benchmark for optimizing compilers, because it puts the 6502 on par with a 4MHz 8088 or 68k, which it clearly is not. @@ -48,6 +48,18 @@ There are still several open areas, but most targets have been reached. The cur ### Native code generation +### C++ support level + +The compiler will most likely not support a current C++ standard in the near future, but several C++ features are already implemented. The compiler can be switched into C++ mode with the command line option -pp or by providing a source file with a .cpp extension. + +Supported Features: + +* namespaces +* reference types +* member functions +* constructors and destructors +* operator overloading (assignment) + ## Installation and Usage ### Installing on windows @@ -62,7 +74,7 @@ The compiler can also be built using MSVC or GCC. A visual studio project and a The compiler is command line driven, and creates an executable .prg file. - oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=format] [-tm=machine] [-e] [-n] [-dSYMBOL[=value]] {source.c} + oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=format] [-tm=machine] [-e] [-n] [-dSYMBOL[=value]] {source.c|source.cpp} * -v : verbose output for diagnostics * -v2 : more verbose output @@ -90,6 +102,7 @@ The compiler is command line driven, and creates an executable .prg file. * -fz : add a compressed binary file to the disk image * -xz : extended zero page usage, more zero page space, but no return to basic * -cid : cartridge type ID, used by vice emulator +* -pp : compile in C++ mode A list of source files can be provided. diff --git a/autotest/arrayconstruct.cpp b/autotest/arrayconstruct.cpp new file mode 100644 index 0000000..845a9bb --- /dev/null +++ b/autotest/arrayconstruct.cpp @@ -0,0 +1,151 @@ +#include + +int t, n, m, k; + +struct C1 +{ + int a; + + C1(void); + ~C1(void); + C1(const C1 & c); + C1 & operator=(const C1 & c); +}; + +struct C2 +{ + C1 nc[10], mc[20]; +}; + +C1::C1(void) +{ + a = 1; + n++; + t++; +} + +C1::C1(const C1 & c) +{ + a = c.a; + k++; + t++; +} + +C1 & C1::operator=(const C1 & c) +{ + a = c.a; + m++; + return *this; +} + +C1::~C1(void) +{ + t--; +} + +void test_local_init(void) +{ + n = 0; + + { + C1 c[10]; + } + + assert(n == 10 && t == 0); +} + +void test_member_init(void) +{ + n = 0; + + { + C2 d; + } + + assert(n == 30 && t == 0); +} + +void test_member_array_init(void) +{ + n = 0; + + { + C2 d[5]; + } + + assert(n == 150 && t == 0); +} + +void test_local_copy(void) +{ + n = 0; + k = 0; + + { + C1 c[10]; + C1 d(c[4]); + } + + assert(n == 10 && k == 1 && t == 0); +} + +void test_member_copy(void) +{ + n = 0; + k = 0; + + { + C2 d; + C2 e(d); + } + + assert(n == 30 && k == 30 && t == 0); +} + +void test_local_assign(void) +{ + n = 0; + k = 0; + m = 0; + + { + C1 c[10]; + C1 d[5]; + + d[4] = c[2]; + } + + assert(n == 15 && k == 0 && m == 1 && t == 0); +} + +void test_member_assign(void) +{ + n = 0; + k = 0; + m = 0; + + { + C2 d; + C2 e; + e = d; + } + + assert(n == 60 && k == 0 && m == 30 && t == 0); +} + + +int main(void) +{ + test_local_init(); + test_member_init(); + test_member_array_init(); + + test_local_copy(); + test_member_copy(); + + test_local_assign(); + test_member_assign(); + + return 0; +} + diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 26e10c4..4ec42d3 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -9,6 +9,9 @@ rem @echo off @call :test copyassign.cpp @if %errorlevel% neq 0 goto :error +@call :test arrayconstruct.cpp +@if %errorlevel% neq 0 goto :error + @call :test stdlibtest.c @if %errorlevel% neq 0 goto :error diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index aa04d09..8f180ec 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -778,7 +778,8 @@ Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), - mConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), + mConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), + mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), mCompilerOptions(0), mUseCount(0) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 6f49477..cf2b6b1 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -222,7 +222,10 @@ public: Location mLocation, mEndLocation; DecType mType; Token mToken; - Declaration* mBase, *mParams, * mNext, * mPrev, * mConst, * mConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; + Declaration * mBase, * mParams, * mNext, * mPrev, * mConst; + Declaration * mConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; + Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; + Expression* mValue; DeclarationScope* mScope; int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 9517e7d..a8e199d 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16017,7 +16017,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "test_retparam_value"); + CheckFunc = !strcmp(mIdent->mString, "test"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 13bd34f..2017ad3 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -4329,6 +4329,13 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod if (proc->mIdent && !strcmp(proc->mIdent->mString, "test_retparam_value")) exp->Dump(0); #endif +#if 0 + if (proc->mIdent) + { + printf("TRANS %s\n", proc->mIdent->mString); + exp->Dump(0); + } +#endif uint64 outerCompilerOptions = mCompilerOptions; mCompilerOptions = dec->mCompilerOptions; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 2226e4e..7d1d0fd 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -36463,6 +36463,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mType == ASMIT_ORA && mIns[i + 3].SameEffectiveAddress(mIns[i + 0]) && mIns[i + 3].mMode != ASMIM_IMMEDIATE) { + mIns[i + 1].mLive |= LIVE_CPU_REG_A; mIns[i + 2].mType = ASMIT_ORA; mIns[i + 2].mLive |= mIns[i + 3].mLive & LIVE_CPU_REG_Z; mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 94863ce..c05812d 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1243,43 +1243,79 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) sexp->mRight = cfunc->mValue; cfunc->mValue = sexp; } - else if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mConstructor) + else { - Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); - qexp->mLeft = thisexp; - qexp->mDecValue = dec; - qexp->mDecType = dec->mBase; + Declaration* bdec = dec->mBase; + while (bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->mBase; - Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); - pexp->mLeft = qexp; - pexp->mToken = TK_BINARY_AND; - pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); - pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - pexp->mDecType->mBase = dec->mBase; - pexp->mDecType->mSize = 2; - - Declaration* mdec = dec->mBase->mConstructor; - while (mdec && mdec->mBase->mParams->mNext) - mdec = mdec->mNext; - - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - if (mdec) + if (bdec->mType == DT_TYPE_STRUCT && bdec->mConstructor) { - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; + + Expression* dexp; + + if (dec->mSize == bdec->mSize) + { + qexp->mDecType = bdec; + + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = qexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = bdec; + pexp->mDecType->mSize = 2; + + Declaration* mdec = bdec->mConstructor; + while (mdec && mdec->mBase->mParams->mNext) + mdec = mdec->mNext; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + if (mdec) + { + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + } + else + mErrors->Error(dec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor"); + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + } + else + { + qexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + qexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + qexp->mDecType->mBase = bdec; + qexp->mDecType->mSize = 2; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorConstructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = dec->mSize / bdec->mSize; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + dexp->mRight->mLeft = qexp; + dexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + dexp->mRight->mRight->mDecType = ncdec->mBase; + dexp->mRight->mRight->mDecValue = ncdec; + } + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = cfunc->mValue; + cfunc->mValue = sexp; } - else - mErrors->Error(dec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor"); - - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; - - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - - sexp->mLeft = dexp; - sexp->mRight = cfunc->mValue; - cfunc->mValue = sexp; } } @@ -1352,12 +1388,21 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Declaration* dec = pthis->mBase->mParams; while (dec) { - if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT) + if (dec->mType == DT_ELEMENT) { - if (dec->mBase->mDestructor) - simpleDestructor = false; - if (dec->mBase->mCopyAssignment) - simpleAssignment = false; + Declaration* bdec = dec->mBase; + int nitems = 1; + + while (bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->mBase; + + if (bdec->mType == DT_TYPE_STRUCT) + { + if (bdec->mDestructor) + simpleDestructor = false; + if (bdec->mCopyAssignment) + simpleAssignment = false; + } } dec = dec->mNext; } @@ -1521,27 +1566,65 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* mexp; - if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mCopyConstructor) + Declaration* bdec = dec->mBase; + while (bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->mBase; + + if (bdec->mType == DT_TYPE_STRUCT && bdec->mCopyConstructor) { - Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); - pexp->mLeft = lexp; - pexp->mToken = TK_BINARY_AND; - pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); - pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - pexp->mDecType->mBase = dec->mBase; - pexp->mDecType->mSize = 2; + if (dec->mSize == bdec->mSize) + { + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = lexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; - Declaration* mdec = dec->mBase->mCopyConstructor; + Declaration* mdec = dec->mBase->mCopyConstructor; - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; - mexp = new Expression(mScanner->mLocation, EX_CALL); - mexp->mLeft = cexp; - mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); - mexp->mRight->mLeft = pexp; - mexp->mRight->mRight = rexp; + mexp = new Expression(mScanner->mLocation, EX_CALL); + mexp->mLeft = cexp; + mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mLeft = pexp; + mexp->mRight->mRight = rexp; + } + else + { + lexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + lexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + lexp->mDecType->mBase = bdec; + lexp->mDecType->mSize = 2; + + rexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + rexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + rexp->mDecType->mBase = bdec; + rexp->mDecType->mSize = 2; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorCopyConstructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = dec->mSize / bdec->mSize; + + mexp = new Expression(mScanner->mLocation, EX_CALL); + mexp->mLeft = cexp; + mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mLeft = lexp; + mexp->mRight->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mRight->mLeft = rexp; + mexp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + mexp->mRight->mRight->mRight->mDecType = ncdec->mBase; + mexp->mRight->mRight->mRight->mDecValue = ncdec; + + } } else { @@ -1661,27 +1744,64 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* mexp; - if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mCopyAssignment) + Declaration* bdec = dec->mBase; + while (bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->mBase; + + if (bdec->mType == DT_TYPE_STRUCT && bdec->mCopyAssignment) { - Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); - pexp->mLeft = lexp; - pexp->mToken = TK_BINARY_AND; - pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); - pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - pexp->mDecType->mBase = dec->mBase; - pexp->mDecType->mSize = 2; + if (dec->mSize == bdec->mSize) + { + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = lexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = dec->mBase; + pexp->mDecType->mSize = 2; - Declaration* mdec = dec->mBase->mCopyAssignment; + Declaration* mdec = bdec->mCopyAssignment; - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; - mexp = new Expression(mScanner->mLocation, EX_CALL); - mexp->mLeft = cexp; - mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); - mexp->mRight->mLeft = pexp; - mexp->mRight->mRight = rexp; + mexp = new Expression(mScanner->mLocation, EX_CALL); + mexp->mLeft = cexp; + mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mLeft = pexp; + mexp->mRight->mRight = rexp; + } + else + { + lexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + lexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + lexp->mDecType->mBase = bdec; + lexp->mDecType->mSize = 2; + + rexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + rexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + rexp->mDecType->mBase = bdec; + rexp->mDecType->mSize = 2; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorCopyAssignment; + cexp->mDecType = cexp->mDecValue->mBase; + + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = dec->mSize / bdec->mSize; + + mexp = new Expression(mScanner->mLocation, EX_CALL); + mexp->mLeft = cexp; + mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mLeft = lexp; + mexp->mRight->mRight = new Expression(mScanner->mLocation, EX_LIST); + mexp->mRight->mRight->mLeft = rexp; + mexp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + mexp->mRight->mRight->mRight->mDecType = ncdec->mBase; + mexp->mRight->mRight->mRight->mDecValue = ncdec; + } } else { @@ -1707,6 +1827,373 @@ void Parser::AddDefaultConstructors(Declaration* pthis) } } + + Declaration* dcons = pthis->mBase->mConstructor; + while (dcons && dcons->mBase->mParams->mNext) + dcons = dcons->mNext; + + if (dcons && !pthis->mBase->mVectorConstructor) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 0; + adec->mOffset = 0; + adec->mBase = TheUnsignedIntTypeDeclaration; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("n"); + + ctdec->mParams = adec; + + Declaration* vthis = pthis->Clone(); + vthis->mFlags &= ~DTF_CONST; + PrependThisArgument(ctdec, vthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + pthis->mBase->mVectorConstructor = cdec; + + cdec->mIdent = pthis->mBase->mIdent; + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + + Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); + pexp->mDecType = vthis; + pexp->mDecValue = ctdec->mParams; + + Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE); + aexp->mDecType = TheUnsignedIntTypeDeclaration; + aexp->mDecValue = adec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + iexp->mToken = TK_INC; + iexp->mLeft = pexp; + + Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + dexp->mToken = TK_DEC; + dexp->mLeft = aexp; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); + fexp->mDecValue = dcons; + fexp->mDecType = fexp->mDecValue->mBase; + + Expression*cexp = new Expression(mScanner->mLocation, EX_CALL); + cexp->mLeft = fexp; + cexp->mRight = iexp; + + Expression * wexp = new Expression(mScanner->mLocation, EX_WHILE); + wexp->mLeft = aexp; + wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + wexp->mRight->mLeft = cexp; + wexp->mRight->mRight = dexp; + + cdec->mValue = wexp; + } + + if (pthis->mBase->mDestructor && !pthis->mBase->mVectorDestructor) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 0; + adec->mOffset = 0; + adec->mBase = TheUnsignedIntTypeDeclaration; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("n"); + + ctdec->mParams = adec; + + Declaration* vthis = pthis->Clone(); + vthis->mFlags &= ~DTF_CONST; + PrependThisArgument(ctdec, vthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + pthis->mBase->mVectorDestructor = cdec; + + char dname[100]; + strcpy_s(dname, "~"); + strcat_s(dname, pthis->mBase->mIdent->mString); + cdec->mIdent = Ident::Unique(dname); + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + + Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); + pexp->mDecType = vthis; + pexp->mDecValue = ctdec->mParams; + + Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE); + aexp->mDecType = TheUnsignedIntTypeDeclaration; + aexp->mDecValue = adec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + iexp->mToken = TK_INC; + iexp->mLeft = pexp; + + Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + dexp->mToken = TK_DEC; + dexp->mLeft = aexp; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); + fexp->mDecValue = pthis->mBase->mDestructor; + fexp->mDecType = fexp->mDecValue->mBase; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CALL); + cexp->mLeft = fexp; + cexp->mRight = iexp; + + Expression* wexp = new Expression(mScanner->mLocation, EX_WHILE); + wexp->mLeft = aexp; + wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + wexp->mRight->mLeft = cexp; + wexp->mRight->mRight = dexp; + + cdec->mValue = wexp; + } + + if (pthis->mBase->mCopyConstructor && !pthis->mBase->mVectorCopyConstructor) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* sdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + sdec->mVarIndex = 0; + sdec->mOffset = 0; + sdec->mBase = pthis->Clone(); + sdec->mBase->mFlags &= ~DTF_CONST; + sdec->mSize = sdec->mBase->mSize; + sdec->mIdent = sdec->mQualIdent = Ident::Unique("_"); + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 2; + adec->mOffset = 0; + adec->mBase = TheUnsignedIntTypeDeclaration; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("n"); + + sdec->mNext = adec; + ctdec->mParams = sdec; + + Declaration* vthis = pthis->Clone(); + vthis->mFlags &= ~DTF_CONST; + PrependThisArgument(ctdec, vthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + pthis->mBase->mVectorCopyConstructor = cdec; + + cdec->mIdent = pthis->mBase->mIdent; + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + + Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); + pexp->mDecType = vthis; + pexp->mDecValue = ctdec->mParams; + + Expression* psexp = new Expression(mScanner->mLocation, EX_VARIABLE); + psexp->mDecType = vthis; + psexp->mDecValue = sdec; + + Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE); + aexp->mDecType = TheUnsignedIntTypeDeclaration; + aexp->mDecValue = adec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + iexp->mToken = TK_INC; + iexp->mLeft = pexp; + + Expression* isexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + isexp->mToken = TK_INC; + isexp->mLeft = psexp; + + Expression* disexp = new Expression(mScanner->mLocation, EX_PREFIX); + disexp->mToken = TK_MUL; + disexp->mLeft = isexp; + disexp->mDecType = vthis->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + dexp->mToken = TK_DEC; + dexp->mLeft = aexp; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); + fexp->mDecValue = pthis->mBase->mCopyConstructor; + fexp->mDecType = fexp->mDecValue->mBase; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CALL); + cexp->mLeft = fexp; + cexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + cexp->mRight->mLeft = iexp; + cexp->mRight->mRight = disexp; + + Expression* wexp = new Expression(mScanner->mLocation, EX_WHILE); + wexp->mLeft = aexp; + wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + wexp->mRight->mLeft = cexp; + wexp->mRight->mRight = dexp; + + cdec->mValue = wexp; + } + + if (pthis->mBase->mCopyAssignment && !pthis->mBase->mVectorCopyAssignment) + { + Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); + ctdec->mSize = 0; + Declaration* pdec = nullptr; + ctdec->mBase = TheVoidTypeDeclaration; + ctdec->mFlags |= DTF_DEFINED; + + Declaration* sdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + sdec->mVarIndex = 0; + sdec->mOffset = 0; + sdec->mBase = pthis->Clone(); + sdec->mBase->mFlags &= ~DTF_CONST; + sdec->mSize = sdec->mBase->mSize; + sdec->mIdent = sdec->mQualIdent = Ident::Unique("_"); + + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + adec->mVarIndex = 2; + adec->mOffset = 0; + adec->mBase = TheUnsignedIntTypeDeclaration; + adec->mSize = adec->mBase->mSize; + adec->mIdent = adec->mQualIdent = Ident::Unique("n"); + + sdec->mNext = adec; + ctdec->mParams = sdec; + + Declaration* vthis = pthis->Clone(); + vthis->mFlags &= ~DTF_CONST; + PrependThisArgument(ctdec, vthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; + + cdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + pthis->mBase->mVectorCopyAssignment = cdec; + + cdec->mIdent = pthis->mBase->mIdent; + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + + Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); + pexp->mDecType = vthis; + pexp->mDecValue = ctdec->mParams; + + Expression* psexp = new Expression(mScanner->mLocation, EX_VARIABLE); + psexp->mDecType = vthis; + psexp->mDecValue = sdec; + + Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE); + aexp->mDecType = TheUnsignedIntTypeDeclaration; + aexp->mDecValue = adec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + iexp->mToken = TK_INC; + iexp->mLeft = pexp; + + Expression* isexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + isexp->mToken = TK_INC; + isexp->mLeft = psexp; + + Expression* disexp = new Expression(mScanner->mLocation, EX_PREFIX); + disexp->mToken = TK_MUL; + disexp->mLeft = isexp; + disexp->mDecType = vthis->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); + dexp->mToken = TK_DEC; + dexp->mLeft = aexp; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); + fexp->mDecValue = pthis->mBase->mCopyAssignment; + fexp->mDecType = fexp->mDecValue->mBase; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CALL); + cexp->mLeft = fexp; + cexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + cexp->mRight->mLeft = iexp; + cexp->mRight->mRight = disexp; + + Expression* wexp = new Expression(mScanner->mLocation, EX_WHILE); + wexp->mLeft = aexp; + wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + wexp->mRight->mLeft = cexp; + wexp->mRight->mRight = dexp; + + cdec->mValue = wexp; + } } void Parser::AppendMemberDestructor(Declaration* pthis) @@ -1730,35 +2217,71 @@ void Parser::AppendMemberDestructor(Declaration* pthis) dec = dec->Last(); while (dec) { - if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor) + if (dec->mType == DT_ELEMENT) { - Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); - qexp->mLeft = thisexp; - qexp->mDecValue = dec; - qexp->mDecType = dec->mBase; + Declaration* bdec = dec->mBase; + while (bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->mBase; - Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); - pexp->mLeft = qexp; - pexp->mToken = TK_BINARY_AND; - pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); - pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - pexp->mDecType->mBase = dec->mBase; - pexp->mDecType->mSize = 2; + if (bdec->mType == DT_TYPE_STRUCT && bdec->mConstructor) + { + Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); + qexp->mLeft = thisexp; + qexp->mDecValue = dec; - Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); - cexp->mDecValue = dec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* dexp; - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; + if (dec->mSize == bdec->mSize) + { + qexp->mDecType = bdec; - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); + pexp->mLeft = qexp; + pexp->mToken = TK_BINARY_AND; + pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + pexp->mDecType->mBase = bdec; + pexp->mDecType->mSize = 2; - sexp->mLeft = pthis->mBase->mDestructor->mValue; - sexp->mRight = dexp; + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; - pthis->mBase->mDestructor->mValue = sexp; + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + } + else + { + qexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); + qexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + qexp->mDecType->mBase = bdec; + qexp->mDecType->mSize = 2; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = dec->mSize / bdec->mSize; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + dexp->mRight->mLeft = qexp; + dexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + dexp->mRight->mRight->mDecType = ncdec->mBase; + dexp->mRight->mRight->mDecValue = ncdec; + } + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = pthis->mBase->mDestructor->mValue; + sexp->mRight = dexp; + + pthis->mBase->mDestructor->mValue = sexp; + } } dec = dec->mPrev; @@ -2615,62 +3138,116 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { ParseVariableInit(ndec); } - else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mBase->mConstructor && ndec->mType == DT_VARIABLE && !pthis) + else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mType == DT_VARIABLE && !pthis) { // Find default constructor - Declaration* cdec = ndec->mBase->mConstructor; - while (cdec && cdec->mBase->mParams->mNext) - cdec = cdec->mNext; + Declaration* bdec = ndec->mBase; + while (bdec && bdec->mType == DT_TYPE_ARRAY) + bdec = bdec->mBase; - if (cdec) + if (bdec && bdec->mConstructor) { - Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE); - vexp->mDecType = ndec->mBase; - vexp->mDecValue = ndec; + Declaration* cdec = bdec->mConstructor; + while (cdec && cdec->mBase->mParams->mNext) + cdec = cdec->mNext; - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = cdec; - cexp->mDecType = cexp->mDecValue->mBase; - - Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); - fexp->mLeft = cexp; - - Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); - texp->mToken = TK_BINARY_AND; - texp->mLeft = vexp; - texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); - texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = ndec->mBase; - texp->mDecType->mSize = 2; - - fexp->mRight = texp; - - Expression* dexp = nullptr; - if (ndec->mBase->mDestructor) + if (cdec) { - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = ndec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; + Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE); + vexp->mDecType = ndec->mBase; + vexp->mDecValue = ndec; - dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = texp; + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_DEFINED; + texp->mDecType->mBase = bdec; + texp->mDecType->mSize = 2; + + if (bdec->mSize == ndec->mBase->mSize) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = cdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = texp; + + Expression* dexp = nullptr; + if (ndec->mBase->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = ndec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + ndec->mValue = nexp; + } + else + { + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = ndec->mSize / bdec->mSize; + + Expression * ncexp = new Expression(mScanner->mLocation, EX_CONSTANT); + ncexp->mDecType = ncdec->mBase; + ncexp->mDecValue = ncdec; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorConstructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + fexp->mRight->mLeft = vexp; + fexp->mRight->mRight = ncexp; + + Expression* dexp = nullptr; + if (bdec->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + dexp->mRight->mLeft = vexp; + dexp->mRight->mRight = ncexp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + ndec->mValue = nexp; + } } - - Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); - - nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); - nexp->mLeft->mLeft = fexp; - nexp->mLeft->mRight = dexp; - - nexp->mRight = vexp; - nexp->mDecType = vexp->mDecType; - - ndec->mValue = nexp; + else + mErrors->Error(ndec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor for class", ndec->mBase->mIdent); } - else - mErrors->Error(ndec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor for class", ndec->mBase->mIdent); } if (storageFlags & DTF_EXPORT) From 6de38be2078581db7be75e753f72885af90c6ab0 Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 26 Jun 2023 12:08:47 +0200 Subject: [PATCH 008/169] Added multithreading hint --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d18225..b03eeb6 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ The compressed files can be loaded into memory and decompressed using the oscar_ The windows installer puts the samples into the users documents folder, using the directory "%userprofile%\documents\oscar64\samples". A batch file *make.bat* is also placed into this directory which invokes the compiler and builds all samples. It invokes a second batch file in "%userprofile%\documents\oscar64\bin\oscar64.bat" that calls the compiler. -On a linux installation one can build the samples invoking the *build.sh* shell script in the samples directory. +On a linux installation one can build the samples invoking the *build.sh* shell script in the samples directory, for multithreading use *make -C samples -j*. ### Debugging From 8f39d736d5b27596c70e6ab17b84ceff1d94bb0f Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 27 Jun 2023 08:12:20 +0200 Subject: [PATCH 009/169] Fixing member functions with includes --- oscar64/Declaration.cpp | 15 +- oscar64/Declaration.h | 6 +- oscar64/InterCode.cpp | 5 +- oscar64/InterCodeGenerator.cpp | 13 +- oscar64/Parser.cpp | 765 +++++++++++++++++++-------------- oscar64/Parser.h | 1 + oscar64/Scanner.cpp | 28 +- 7 files changed, 496 insertions(+), 337 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 8f180ec..bd4f610 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -148,9 +148,13 @@ void Expression::Dump(int ident) const break; case EX_CONSTANT: printf("CONST"); + if (mDecValue->mIdent) + printf(" '%s'", mDecValue->mIdent->mString); break; case EX_VARIABLE: printf("VAR"); + if (mDecValue->mIdent) + printf(" '%s'", mDecValue->mIdent->mString); break; case EX_ASSIGNMENT: printf("ASSIGN<%s>", TokenNames[mToken]); @@ -777,8 +781,8 @@ Expression* Expression::ConstantFold(Errors * errors) Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), - mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), - mConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), + mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), + mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), @@ -1207,11 +1211,18 @@ bool Declaration::IsNumericType(void) const return mType == DT_TYPE_INTEGER || mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_ENUM; } + bool Declaration::IsSimpleType(void) const { return mType == DT_TYPE_INTEGER || mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_ENUM || mType == DT_TYPE_POINTER; } +void Declaration::SetDefined(void) +{ + mFlags |= DTF_DEFINED; + if (mConst) + mConst->mFlags |= DTF_DEFINED; +} Declaration* TheVoidTypeDeclaration, * TheConstVoidTypeDeclaration, * TheSignedIntTypeDeclaration, * TheUnsignedIntTypeDeclaration, * TheConstCharTypeDeclaration, * TheCharTypeDeclaration, * TheSignedCharTypeDeclaration, * TheUnsignedCharTypeDeclaration; Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheConstVoidPointerTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index cf2b6b1..5672068 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -94,8 +94,6 @@ static const uint64 DTF_FPARAM_CONST = (1ULL << 40); static const uint64 DTF_FPARAM_NOCONST = (1ULL << 41); static const uint64 DTF_FUNC_THIS = (1ULL << 42); -static const uint64 DTF_FUNC_CONSTRUCTOR = (1ULL << 43); -static const uint64 DTF_FUNC_DESTRUCTOR = (1ULL << 44); static const uint64 DTF_VAR_ALIASING = (1ULL << 48); @@ -223,7 +221,7 @@ public: DecType mType; Token mToken; Declaration * mBase, * mParams, * mNext, * mPrev, * mConst; - Declaration * mConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; + Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; Expression* mValue; @@ -251,6 +249,8 @@ public: bool IsNumericType(void) const; bool IsSimpleType(void) const; + void SetDefined(void); + Declaration* ToConstType(void); Declaration* ToStriped(int stripe); Declaration* ToStriped(Errors* errors); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index a8e199d..802dc43 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -12026,10 +12026,7 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) block->mInstructions[j++] = ins; } } -#ifdef _DEBUG - if (j != block->mInstructions.Size()) - printf("Moved %d %d\n", mIndex, block->mInstructions.Size() - j); -#endif + block->mInstructions.SetSize(j); } #endif diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 2017ad3..9fe9cf9 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1854,7 +1854,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } } - return vr; + return vl; case EX_INDEX: { @@ -2761,6 +2761,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } Declaration * decResult = nullptr; + GrowingArray defins(nullptr); if (ftype->mBase->mType == DT_TYPE_STRUCT) { @@ -2816,7 +2817,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* wins->mSrc[1].mType = IT_POINTER; wins->mSrc[1].mTemp = ains->mDst.mTemp; wins->mSrc[1].mOperandSize = 2; - block->Append(wins); + + if (ftype->mFlags & DTF_FASTCALL) + defins.Push(wins); + else + block->Append(wins); atotal = 2; } @@ -2826,8 +2831,6 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else proc->CallsFunctionPointer(); - GrowingArray defins(nullptr); - Declaration* pdec = ftype->mParams; Expression* pex = exp->mRight; while (pex) @@ -4326,7 +4329,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)); #if 0 - if (proc->mIdent && !strcmp(proc->mIdent->mString, "test_retparam_value")) + if (proc->mIdent && !strcmp(proc->mIdent->mString, "test_member")) exp->Dump(0); #endif #if 0 diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index c05812d..1992d83 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -28,6 +28,34 @@ Parser::~Parser(void) } +void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec) +{ + Declaration* gdec = mCompilationUnits->mScope->Insert(mdec->mQualIdent, mdec); + if (gdec) + { + if (gdec->mType == DT_CONST_FUNCTION) + { + Declaration* pcdec = nullptr; + Declaration* pdec = gdec; + + while (pdec && !mdec->mBase->IsSameParams(pdec->mBase)) + { + pcdec = pdec; + pdec = pdec->mNext; + } + + if (!pdec) + pcdec->mNext = mdec; + + dec->mScope->Insert(mdec->mIdent, gdec); + } + else + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + } + else + dec->mScope->Insert(mdec->mIdent, mdec); +} + Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) { const Ident* structName = nullptr; @@ -118,36 +146,10 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mCompilerOptions & COPT_NATIVE) mdec->mFlags |= DTF_NATIVE; - if (!(mdec->mFlags & (DTF_FUNC_CONSTRUCTOR | DTF_FUNC_DESTRUCTOR))) - { - Declaration* pdec = dec->mScope->Insert(mdec->mIdent, mdec); - - if (pdec) - { - if (pdec->mType == DT_CONST_FUNCTION) - { - Declaration* pcdec = nullptr; - - while (pdec && !mdec->mBase->IsSameParams(pdec->mBase)) - { - pcdec = pdec; - pdec = pdec->mNext; - } - - if (!pdec) - pcdec->mNext = mdec; - else - mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); - } - else - mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); - } - else if (mCompilationUnits->mScope->Insert(mdec->mQualIdent, mdec)) - mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); - } - if (!(mdec->mFlags & DTF_DEFINED)) ConsumeToken(TK_SEMICOLON); + + AddMemberFunction(dec, mdec); } else { @@ -201,13 +203,14 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) else dec->mParams = nullptr; - dec->mFlags |= DTF_DEFINED; + dec->SetDefined(); - if (mCompilerOptions & COPT_CPLUSPLUS) + if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mType == DT_TYPE_STRUCT && dec->mIdent) { AddDefaultConstructors(pthis); - Declaration* cdec = pthis->mBase->mConstructor; + // Lookup constructors, have same name as class + Declaration* cdec = dec->mScope->Lookup(dec->mIdent); while (cdec) { if (cdec->mFlags & DTF_DEFINED) @@ -347,15 +350,20 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) } else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) { - Declaration* ndec = new Declaration(dec->mLocation, dec->mType); - ndec->mFlags = dec->mFlags | flags; - ndec->mSize = dec->mSize; - ndec->mBase = dec->mBase; - ndec->mScope = dec->mScope; - ndec->mParams = dec->mParams; - ndec->mIdent = dec->mIdent; - ndec->mQualIdent = dec->mQualIdent; - dec = ndec; + if ((flags & ~dec->mFlags) == DTF_CONST) + dec = dec->ToConstType(); + else + { + Declaration* ndec = new Declaration(dec->mLocation, dec->mType); + ndec->mFlags = dec->mFlags | flags; + ndec->mSize = dec->mSize; + ndec->mBase = dec->mBase; + ndec->mScope = dec->mScope; + ndec->mParams = dec->mParams; + ndec->mIdent = dec->mIdent; + ndec->mQualIdent = dec->mQualIdent; + dec = ndec; + } } mScanner->NextToken(); } @@ -1158,10 +1166,12 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) Expression* Parser::BuildMemberInitializer(Expression* vexp) { - if (vexp->mDecType->mType == DT_TYPE_STRUCT && vexp->mDecType->mConstructor) + Declaration* fcons = (vexp->mDecType->mType == DT_TYPE_STRUCT && vexp->mDecType->mScope) ? vexp->mDecType->mScope->Lookup(vexp->mDecType->mIdent) : nullptr; + + if (fcons) { Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = vexp->mDecType->mConstructor; + cexp->mDecValue = fcons; cexp->mDecType = cexp->mDecValue->mBase; Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); @@ -1249,7 +1259,7 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) while (bdec->mType == DT_TYPE_ARRAY) bdec = bdec->mBase; - if (bdec->mType == DT_TYPE_STRUCT && bdec->mConstructor) + if (bdec->mType == DT_TYPE_STRUCT && bdec->mDefaultConstructor) { Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); qexp->mLeft = thisexp; @@ -1269,9 +1279,7 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) pexp->mDecType->mBase = bdec; pexp->mDecType->mSize = 2; - Declaration* mdec = bdec->mConstructor; - while (mdec && mdec->mBase->mParams->mNext) - mdec = mdec->mNext; + Declaration* mdec = bdec->mDefaultConstructor; Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); if (mdec) @@ -1385,6 +1393,44 @@ void Parser::AddDefaultConstructors(Declaration* pthis) { bool simpleDestructor = true, simpleAssignment = true; + char dname[100]; + strcpy_s(dname, "~"); + strcat_s(dname, pthis->mBase->mIdent->mString); + + const Ident * dtorident = Ident::Unique(dname); + + // Extract constructor and destructor from scope + + Declaration* cdec = pthis->mBase->mScope->Lookup(pthis->mBase->mIdent); + while (cdec) + { + Declaration* ctdec = cdec->mBase; + Declaration* tparam = ctdec->mParams->mNext; + + if (!tparam) + pthis->mBase->mDefaultConstructor = cdec; + else if (!tparam->mNext && tparam->mBase->mType == DT_TYPE_REFERENCE && pthis->mBase->IsConstSame(tparam->mBase->mBase)) + pthis->mBase->mCopyConstructor = cdec; + + cdec = cdec->mNext; + } + + Declaration* ddec = pthis->mBase->mScope->Lookup(dtorident); + if (ddec) + pthis->mBase->mDestructor = ddec; + + Declaration* adec = pthis->mBase->mScope->Lookup(Ident::Unique("operator=")); + while (adec) + { + Declaration* atdec = adec->mBase; + Declaration* tparam = atdec->mParams->mNext; + + if (!tparam->mNext && tparam->mBase->mType == DT_TYPE_REFERENCE && pthis->mBase->IsConstSame(tparam->mBase->mBase)) + pthis->mBase->mCopyAssignment = adec; + + adec = adec->mNext; + } + Declaration* dec = pthis->mBase->mParams; while (dec) { @@ -1423,7 +1469,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - cdec->mFlags |= DTF_FUNC_DESTRUCTOR; cdec->mSection = mCodeSection; @@ -1432,10 +1477,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) pthis->mBase->mDestructor = cdec; - char dname[100]; - strcpy_s(dname, "~"); - strcat_s(dname, pthis->mBase->mIdent->mString); - cdec->mIdent = Ident::Unique(dname); + cdec->mIdent = dtorident; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); cdec->mCompilerOptions = mCompilerOptions; @@ -1449,7 +1491,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); } - if (!pthis->mBase->mConstructor) + if (!pthis->mBase->mDefaultConstructor) { Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); ctdec->mSize = 0; @@ -1463,18 +1505,19 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; cdec->mSection = mCodeSection; if (mCompilerOptions & COPT_NATIVE) cdec->mFlags |= DTF_NATIVE; - pthis->mBase->mConstructor = cdec; + pthis->mBase->mDefaultConstructor = cdec; cdec->mIdent = pthis->mBase->mIdent; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + AddMemberFunction(pthis->mBase, cdec); + cdec->mCompilerOptions = mCompilerOptions; cdec->mBase->mCompilerOptions = mCompilerOptions; @@ -1511,7 +1554,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; cdec->mSection = mCodeSection; @@ -1519,12 +1561,12 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mFlags |= DTF_NATIVE; pthis->mBase->mCopyConstructor = cdec; - cdec->mNext = pthis->mBase->mConstructor; - pthis->mBase->mConstructor = cdec; cdec->mIdent = pthis->mBase->mIdent; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + AddMemberFunction(pthis->mBase, cdec); + cdec->mCompilerOptions = mCompilerOptions; cdec->mBase->mCompilerOptions = mCompilerOptions; @@ -1680,7 +1722,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; cdec->mSection = mCodeSection; @@ -1691,16 +1732,12 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); pthis->mBase->mCopyAssignment = cdec; - Declaration* pdec = pthis->mBase->mScope->Insert(cdec->mIdent, cdec); - if (pdec) - { - cdec->mNext = pdec->mNext; - pdec->mNext = cdec; - } cdec->mCompilerOptions = mCompilerOptions; cdec->mBase->mCompilerOptions = mCompilerOptions; + AddMemberFunction(pthis->mBase, cdec); + cdec->mVarIndex = -1; Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); @@ -1828,11 +1865,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) } } - Declaration* dcons = pthis->mBase->mConstructor; - while (dcons && dcons->mBase->mParams->mNext) - dcons = dcons->mNext; - - if (dcons && !pthis->mBase->mVectorConstructor) + if (pthis->mBase->mDefaultConstructor && !pthis->mBase->mVectorConstructor) { Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); ctdec->mSize = 0; @@ -1857,7 +1890,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; cdec->mSection = mCodeSection; @@ -1894,7 +1926,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) dexp->mLeft = aexp; Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); - fexp->mDecValue = dcons; + fexp->mDecValue = pthis->mBase->mDefaultConstructor; fexp->mDecType = fexp->mDecValue->mBase; Expression*cexp = new Expression(mScanner->mLocation, EX_CALL); @@ -1935,7 +1967,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; cdec->mSection = mCodeSection; @@ -2025,7 +2056,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; cdec->mSection = mCodeSection; @@ -2127,7 +2157,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; cdec->mSection = mCodeSection; @@ -2223,7 +2252,7 @@ void Parser::AppendMemberDestructor(Declaration* pthis) while (bdec->mType == DT_TYPE_ARRAY) bdec = bdec->mBase; - if (bdec->mType == DT_TYPE_STRUCT && bdec->mConstructor) + if (bdec->mType == DT_TYPE_STRUCT && bdec->mDestructor) { Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); qexp->mLeft = thisexp; @@ -2295,7 +2324,11 @@ void Parser::PrependThisArgument(Declaration* fdec, Declaration* pthis) { Declaration* adec = new Declaration(fdec->mLocation, DT_ARGUMENT); - adec->mVarIndex = 0; + if (fdec->mBase->mType == DT_TYPE_STRUCT) + adec->mVarIndex = 2; + else + adec->mVarIndex = 0; + adec->mOffset = 0; adec->mBase = pthis; adec->mSize = adec->mBase->mSize; @@ -2351,7 +2384,58 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) { Expression* lexp = nullptr, * rexp = nullptr; - if (exp->mType == EX_CALL) + if (exp->mType == EX_PREFIX && exp->mToken == TK_BINARY_AND && exp->mLeft->mType == EX_CALL) + { + lexp = AddFunctionCallRefReturned(exp->mLeft); + + // Returning a value object for pass by address + // add a temporary variable + + int nindex = mLocalIndex++; + + Declaration* rtdec = exp->mLeft->mDecType; + + Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + vdec->mVarIndex = nindex; + vdec->mBase = rtdec; + vdec->mSize = rtdec->mSize; + + Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE); + vexp->mDecType = rtdec; + vexp->mDecValue = vdec; + + Expression * pex = new Expression(exp->mLocation, EX_INITIALIZATION); + pex->mToken = TK_ASSIGN; + pex->mLeft = vexp; + pex->mRight = exp->mLeft; + pex->mDecValue = nullptr; + pex->mDecType = vdec->mBase; + + exp->mLeft = pex; + + if (rtdec->mDestructor) + { + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = vdec->mBase; + texp->mDecType->mSize = 2; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = rtdec->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + + rexp = ConcatExpression(rexp, dexp); + } + } + else if (exp->mType == EX_CALL) { lexp = AddFunctionCallRefReturned(exp->mLeft); if (exp->mRight) @@ -2453,66 +2537,71 @@ void Parser::ParseVariableInit(Declaration* ndec) { ndec->mValue = pexp; } - else if (ndec->mBase->mConstructor) - { - Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); - vexp->mDecType = ndec->mBase; - vexp->mDecValue = ndec; - - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = ndec->mBase->mConstructor; - cexp->mDecType = cexp->mDecValue->mBase; - - Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); - fexp->mLeft = cexp; - fexp->mRight = pexp; - - Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); - texp->mToken = TK_BINARY_AND; - texp->mLeft = vexp; - texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); - texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = ndec->mBase; - texp->mDecType->mSize = 2; - - if (fexp->mRight) - { - Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); - lexp->mLeft = texp; - lexp->mRight = fexp->mRight; - fexp->mRight = lexp; - } - else - fexp->mRight = texp; - - ResolveOverloadCall(cexp, fexp->mRight); - - Expression* dexp = nullptr; - if (ndec->mBase->mDestructor) - { - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = ndec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; - - dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = texp; - } - - Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); - - nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); - nexp->mLeft->mLeft = fexp; - nexp->mLeft->mRight = dexp; - - nexp->mRight = vexp; - nexp->mDecType = vexp->mDecType; - - ndec->mValue = nexp; - } else { - ndec->mValue = pexp; + Declaration* fcons = ndec->mBase->mScope ? ndec->mBase->mScope->Lookup(ndec->mBase->mIdent) : nullptr; + + if (fcons) + { + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = ndec->mBase; + vexp->mDecValue = ndec; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = fcons; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = pexp; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = ndec->mBase; + texp->mDecType->mSize = 2; + + if (fexp->mRight) + { + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = fexp->mRight; + fexp->mRight = lexp; + } + else + fexp->mRight = texp; + + ResolveOverloadCall(cexp, fexp->mRight); + + Expression* dexp = nullptr; + if (ndec->mBase->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = ndec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + ndec->mValue = nexp; + } + else + { + ndec->mValue = pexp; + } } } @@ -2658,7 +2747,6 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - cdec->mFlags |= DTF_FUNC_DESTRUCTOR; cdec->mSection = mCodeSection; cdec->mBase->mFlags |= typeFlags; @@ -2666,11 +2754,6 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (mCompilerOptions & COPT_NATIVE) cdec->mFlags |= DTF_NATIVE; - if (pthis->mBase->mDestructor) - mErrors->Error(ctdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate destrcutor definition"); - else - pthis->mBase->mDestructor = cdec; - char dname[100]; strcpy_s(dname, "~"); strcat_s(dname, pthis->mBase->mIdent->mString); @@ -2706,16 +2789,11 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); - if (ctdec->mParams && !ctdec->mParams->mNext && ctdec->mParams->mBase->mType == DT_TYPE_REFERENCE && - pthis->mBase->IsConstSame(ctdec->mParams->mBase->mBase)) - pthis->mBase->mCopyConstructor = cdec; - PrependThisArgument(ctdec, pthis); cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - cdec->mFlags |= DTF_FUNC_CONSTRUCTOR; cdec->mSection = mCodeSection; cdec->mBase->mFlags |= typeFlags; @@ -2723,7 +2801,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (mCompilerOptions & COPT_NATIVE) cdec->mFlags |= DTF_NATIVE; - Declaration* pdec = pthis->mBase->mConstructor; + Declaration* pdec = pthis->mBase->mScope ? pthis->mBase->mScope->Lookup(pthis->mBase->mIdent) : nullptr; if (pdec) { while (pdec && !cdec->mBase->IsSameParams(pdec->mBase)) @@ -2756,11 +2834,6 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec = pdec; } - else - { - cdec->mNext = pthis->mBase->mConstructor; - pthis->mBase->mConstructor = cdec; - } cdec->mIdent = pthis->mBase->mIdent; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); @@ -2805,7 +2878,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex PrependThisArgument(ctdec, bthis); - Declaration* cdec = bdec->mConstructor; + Declaration* cdec = bdec->mScope->Lookup(bdec->mIdent); if (cdec) { while (cdec && !cdec->mBase->IsSameParams(ctdec)) @@ -2887,7 +2960,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex AppendMemberDestructor(bthis); } else - mErrors->Error(ctdec->mLocation, EERR_DUPLICATE_DEFINITION, "Desctructor not declared", bdec->mIdent); + mErrors->Error(ctdec->mLocation, EERR_DUPLICATE_DEFINITION, "Destructor not declared", bdec->mIdent); return bdec->mDestructor; } @@ -2935,13 +3008,6 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) { - if (ndec->mIdent == Ident::Unique("operator=")) - { - if (ndec->mBase->mParams && ndec->mBase->mParams->mBase->mType == DT_TYPE_REFERENCE && ndec->mBase->mParams->mBase->mBase->IsConstSame(pthis->mBase)) - { - pthis->mBase->mCopyAssignment = ndec; - } - } PrependThisArgument(ndec->mBase, pthis); @@ -3108,7 +3174,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex else rdec = ndec; ldec = ndec; - ndec->mNext = nullptr; +// ndec->mNext = nullptr; if (mScanner->mToken == TK_ASSIGN) { @@ -3146,108 +3212,101 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex while (bdec && bdec->mType == DT_TYPE_ARRAY) bdec = bdec->mBase; - if (bdec && bdec->mConstructor) + if (bdec && bdec->mDefaultConstructor) { - Declaration* cdec = bdec->mConstructor; - while (cdec && cdec->mBase->mParams->mNext) - cdec = cdec->mNext; + Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE); + vexp->mDecType = ndec->mBase; + vexp->mDecValue = ndec; - if (cdec) + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_DEFINED; + texp->mDecType->mBase = bdec; + texp->mDecType->mSize = 2; + + if (bdec->mSize == ndec->mBase->mSize) { - Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE); - vexp->mDecType = ndec->mBase; - vexp->mDecValue = ndec; + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mDefaultConstructor; + cexp->mDecType = cexp->mDecValue->mBase; - Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); - texp->mToken = TK_BINARY_AND; - texp->mLeft = vexp; - texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); - texp->mDecType->mFlags |= DTF_DEFINED; - texp->mDecType->mBase = bdec; - texp->mDecType->mSize = 2; + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = texp; - if (bdec->mSize == ndec->mBase->mSize) + Expression* dexp = nullptr; + if (ndec->mBase->mDestructor) { Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = cdec; + cexp->mDecValue = ndec->mBase->mDestructor; cexp->mDecType = cexp->mDecValue->mBase; - Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); - fexp->mLeft = cexp; - fexp->mRight = texp; - - Expression* dexp = nullptr; - if (ndec->mBase->mDestructor) - { - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = ndec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; - - dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = texp; - } - - Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); - - nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); - nexp->mLeft->mLeft = fexp; - nexp->mLeft->mRight = dexp; - - nexp->mRight = vexp; - nexp->mDecType = vexp->mDecType; - - ndec->mValue = nexp; + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; } - else - { - Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); - ncdec->mBase = TheUnsignedIntTypeDeclaration; - ncdec->mInteger = ndec->mSize / bdec->mSize; - Expression * ncexp = new Expression(mScanner->mLocation, EX_CONSTANT); - ncexp->mDecType = ncdec->mBase; - ncexp->mDecValue = ncdec; + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = bdec->mVectorConstructor; - cexp->mDecType = cexp->mDecValue->mBase; + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; - Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); - fexp->mLeft = cexp; - fexp->mRight = new Expression(mScanner->mLocation, EX_LIST); - fexp->mRight->mLeft = vexp; - fexp->mRight->mRight = ncexp; + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; - Expression* dexp = nullptr; - if (bdec->mDestructor) - { - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = bdec->mVectorDestructor; - cexp->mDecType = cexp->mDecValue->mBase; - - dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); - dexp->mRight->mLeft = vexp; - dexp->mRight->mRight = ncexp; - } - - Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); - - nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); - nexp->mLeft->mLeft = fexp; - nexp->mLeft->mRight = dexp; - - nexp->mRight = vexp; - nexp->mDecType = vexp->mDecType; - - ndec->mValue = nexp; - } + ndec->mValue = nexp; } else - mErrors->Error(ndec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor for class", ndec->mBase->mIdent); + { + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + ncdec->mBase = TheUnsignedIntTypeDeclaration; + ncdec->mInteger = ndec->mSize / bdec->mSize; + + Expression * ncexp = new Expression(mScanner->mLocation, EX_CONSTANT); + ncexp->mDecType = ncdec->mBase; + ncexp->mDecValue = ncdec; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorConstructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + fexp->mRight->mLeft = vexp; + fexp->mRight->mRight = ncexp; + + Expression* dexp = nullptr; + if (bdec->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = bdec->mVectorDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + dexp->mRight->mLeft = vexp; + dexp->mRight->mRight = ncexp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + ndec->mValue = nexp; + } } + else if (bdec && bdec->mDestructor) + mErrors->Error(ndec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor for class", ndec->mBase->mIdent); } if (storageFlags & DTF_EXPORT) @@ -3938,7 +3997,9 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) else return NOOVERLOAD; } - else if (ptype->IsSubType(ex->mDecType)) + else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_ARRAY && ptype->mBase->IsSame(etype->mBase)) + dist += 1; + else if (ptype->IsSubType(etype)) dist += 256; else return NOOVERLOAD; @@ -4040,78 +4101,82 @@ Expression* Parser::ParsePostfixExpression(bool lhs) // Simple copy exp = pexp; } - else if (exp->mDecType->mConstructor) - { - Declaration* tdec = new Declaration(mScanner->mLocation, DT_VARIABLE); - - tdec->mBase = exp->mDecType; - tdec->mVarIndex = mLocalIndex++; - tdec->mSize = exp->mDecType->mSize; - tdec->mFlags |= DTF_DEFINED; - - Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); - vexp->mDecType = exp->mDecType; - vexp->mDecValue = tdec; - - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = exp->mDecType->mConstructor; - cexp->mDecType = cexp->mDecValue->mBase; - - Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); - fexp->mLeft = cexp; - - fexp->mRight = pexp; - - Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); - texp->mToken = TK_BINARY_AND; - texp->mLeft = vexp; - texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); - texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = exp->mDecType; - texp->mDecType->mSize = 2; - - if (fexp->mRight) - { - Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); - lexp->mLeft = texp; - lexp->mRight = fexp->mRight; - fexp->mRight = lexp; - } - else - fexp->mRight = texp; - - ResolveOverloadCall(cexp, fexp->mRight); - - Expression* dexp = nullptr; - if (exp->mDecType->mBase->mDestructor) - { - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = exp->mDecType->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; - - dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = texp; - } - - Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); - - nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); - nexp->mLeft->mLeft = fexp; - nexp->mLeft->mRight = dexp; - - nexp->mRight = vexp; - nexp->mDecType = vexp->mDecType; - - exp = nexp; - } else { - Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); - nexp->mDecType = exp->mDecType; - nexp->mLeft = exp; - nexp->mRight = pexp; - exp = nexp->ConstantFold(mErrors); + Declaration* fcons = exp->mDecType->mScope ? exp->mDecType->mScope->Lookup(exp->mDecType->mIdent) : nullptr; + if (fcons) + { + Declaration* tdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + + tdec->mBase = exp->mDecType; + tdec->mVarIndex = mLocalIndex++; + tdec->mSize = exp->mDecType->mSize; + tdec->mFlags |= DTF_DEFINED; + + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = exp->mDecType; + vexp->mDecValue = tdec; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = fcons; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + + fexp->mRight = pexp; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = exp->mDecType; + texp->mDecType->mSize = 2; + + if (fexp->mRight) + { + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = fexp->mRight; + fexp->mRight = lexp; + } + else + fexp->mRight = texp; + + ResolveOverloadCall(cexp, fexp->mRight); + + Expression* dexp = nullptr; + if (exp->mDecType->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = exp->mDecType->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + exp = nexp; + } + else + { + Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); + nexp->mDecType = exp->mDecType; + nexp->mLeft = exp; + nexp->mRight = pexp; + exp = nexp->ConstantFold(mErrors); + } } } else @@ -4348,7 +4413,9 @@ Expression* Parser::ParseAddExpression(bool lhs) else nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(mErrors); + exp = CheckOperatorOverload(nexp); + + exp = exp->ConstantFold(mErrors); } return exp; @@ -4567,6 +4634,66 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) ResolveOverloadCall(nexp->mLeft, nexp->mRight); nexp->mDecType = nexp->mLeft->mDecType->mBase; + exp = nexp; + } + } + } + } + else if (exp->mType == EX_BINARY) + { + const Ident* opident = nullptr; + switch (exp->mToken) + { + case TK_ADD: + opident = Ident::Unique("operator+"); + break; + case TK_SUB: + opident = Ident::Unique("operator+"); + break; + case TK_MUL: + opident = Ident::Unique("operator+"); + break; + case TK_DIV: + opident = Ident::Unique("operator+"); + break; + case TK_MOD: + opident = Ident::Unique("operator%"); + break; + } + + if (opident) + { + Declaration* tdec = exp->mLeft->mDecType; + if (tdec->mType == DT_TYPE_STRUCT) + { + Declaration* mdec = tdec->mScope->Lookup(opident); + if (mdec) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_CALL); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + nexp->mRight = exp->mRight; + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp->mLeft; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = exp->mDecType; + texp->mDecType->mSize = 2; + + Expression* lexp = new Expression(nexp->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = nexp->mRight; + nexp->mRight = lexp; + + ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + exp = nexp; } } diff --git a/oscar64/Parser.h b/oscar64/Parser.h index e889bce..6e749f7 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -49,6 +49,7 @@ protected: void AddDefaultConstructors(Declaration* pthis); void ParseVariableInit(Declaration* ndec); + void AddMemberFunction(Declaration* dec, Declaration* mdec); Expression * AddFunctionCallRefReturned(Expression * exp); Expression* CleanupExpression(Expression* exp); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 28905ef..91cba05 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1397,13 +1397,33 @@ void Scanner::NextRawToken(void) else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); - if (mToken == TK_ASSIGN) + switch (mToken) { - mToken = TK_IDENT; + case TK_ASSIGN: mTokenIdent = Ident::Unique("operator="); - } - else + break; + + case TK_ADD: + mTokenIdent = Ident::Unique("operator+"); + break; + case TK_SUB: + mTokenIdent = Ident::Unique("operator-"); + break; + case TK_MUL: + mTokenIdent = Ident::Unique("operator*"); + break; + case TK_DIV: + mTokenIdent = Ident::Unique("operator/"); + break; + case TK_MOD: + mTokenIdent = Ident::Unique("operator%"); + break; + + default: mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "Invalid operator token"); + } + + mToken = TK_IDENT; } else { From 63ebf6aa7c84f545624b03fda5c160fda9c08ef7 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 27 Jun 2023 15:34:13 +0200 Subject: [PATCH 010/169] strlen optimization --- oscar64/InterCode.cpp | 21 ++++++++ oscar64/NativeCodeGenerator.cpp | 91 +++++++++++++++++++++++++++------ oscar64/NativeCodeGenerator.h | 2 +- 3 files changed, 96 insertions(+), 18 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 802dc43..6e4723b 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -14196,6 +14196,27 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 0]->mNumOperands = 0; changed = true; } + else if ( + mInstructions[i + 0]->mCode == IC_LEA && + mInstructions[i + 0]->mSrc[0].mTemp >= 0 && mInstructions[i + 0]->mSrc[1].mTemp >= 0 && + + mInstructions[i + 1]->mCode == IC_LOAD && + mInstructions[i + 1]->mSrc[0].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mFinal && + + mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 2]->mOperator == IA_ADD && + mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 2]->mDst.mTemp && + mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 0]->mSrc[0].mTemp && + mInstructions[i + 2]->mSrc[0].mTemp < 0 && + mInstructions[i + 2]->mSrc[0].mIntConst == mInstructions[i + 1]->mSrc[0].mIntConst && + mInstructions[i + 2]->mSrc[1].mTemp != mInstructions[i + 1]->mDst.mTemp) + { + InterInstruction* iadd = mInstructions[i + 2]; + mInstructions[i + 2] = mInstructions[i + 1]; + mInstructions[i + 1] = mInstructions[i + 0]; + mInstructions[i + 0] = iadd; + mInstructions[i + 2]->mSrc[0].mIntConst = 0; + changed = true; + } #if 1 if (i + 2 < mInstructions.Size() && diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 7d1d0fd..308af63 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -16842,6 +16842,28 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) } } +#if 1 + if (mIns.Size() >= 4 && mTrueJump && mFalseJump && mTrueJump->mEntryRequiredRegs.Size() > 0 && mFalseJump->mEntryRequiredRegs.Size() > 0) + { + int sz = mIns.Size(); + + if (mIns[sz - 4].mType == ASMIT_TYA && + mIns[sz - 3].mType == ASMIT_CLC && + mIns[sz - 2].mType == ASMIT_ADC && mIns[sz - 2].mMode == ASMIM_IMMEDIATE && mIns[sz - 2].mAddress == 1 && + mIns[sz - 1].mType == ASMIT_TAY && !(mIns[sz - 1].mLive & LIVE_CPU_REG_A) && + (mBranch == ASMIT_BCC || mBranch == ASMIT_BCS) && + !mTrueJump->mEntryRequiredRegs[CPU_REG_C] && !mFalseJump->mEntryRequiredRegs[CPU_REG_C]) + { + mIns[sz - 4].mType = ASMIT_INY; mIns[sz - 4].mLive |= LIVE_CPU_REG_Y | LIVE_CPU_REG_Z; + if (mBranch == ASMIT_BCC) + mBranch = ASMIT_BNE; + else + mBranch = ASMIT_BEQ; + mIns.SetSize(sz - 3); + changed = true; + } + } +#endif if (mIns.Size() >= 2) { int sz = mIns.Size(); @@ -21304,7 +21326,7 @@ bool NativeCodeBasicBlock::PatchForwardLowYPointer(const NativeCodeBasicBlock* b return changed; } -bool NativeCodeBasicBlock::CheckForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, const NativeCodeInstruction& iins, int at, int yval) +bool NativeCodeBasicBlock::CheckForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, const NativeCodeInstruction& iins, int at, int yval, int ymax) { if (!mPatched) { @@ -21346,10 +21368,11 @@ bool NativeCodeBasicBlock::CheckForwardSumYPointer(const NativeCodeBasicBlock* b { if (iins.mMode == ASMIM_IMMEDIATE && yval + iins.mAddress > 255) return false; - if (yval < 0 || yval > 3) + if (yval < 0 || yval > ymax) return false; else if (!(ins.mLive & LIVE_MEM)) return true; + if (yval == 0) ymax = 3; } if (ins.mType == ASMIT_LDY && ins.mMode == ASMIM_IMMEDIATE) @@ -21377,9 +21400,9 @@ bool NativeCodeBasicBlock::CheckForwardSumYPointer(const NativeCodeBasicBlock* b at++; } - if (mTrueJump && !mTrueJump->CheckForwardSumYPointer(block, reg, base, iins, 0, yval)) + if (mTrueJump && !mTrueJump->CheckForwardSumYPointer(block, reg, base, iins, 0, yval, ymax)) return false; - if (mFalseJump && !mFalseJump->CheckForwardSumYPointer(block, reg, base, iins, 0, yval)) + if (mFalseJump && !mFalseJump->CheckForwardSumYPointer(block, reg, base, iins, 0, yval, ymax)) return false; } @@ -38380,7 +38403,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { int yval = RetrieveYValue(i); proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 1], i + 7, yval)) + if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 1], i + 7, yval, 0)) { proc->ResetPatched(); if (PatchForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 1], i + 7, yval)) @@ -38411,7 +38434,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { int yval = RetrieveYValue(i); proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval)) + if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval, 0)) { proc->ResetPatched(); if (PatchForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval)) @@ -38432,15 +38455,30 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass if (mIns[i + 0].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && - mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress != mIns[i + 1].mAddress && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 4].mType == ASMIT_LDA && mIns[i + 4].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 6].mType == ASMIT_STA && mIns[i + 6].mMode == ASMIM_ZERO_PAGE && mIns[i + 6].mAddress == mIns[i + 3].mAddress + 1 && !(mIns[i + 6].mLive & LIVE_CPU_REG_A)) { int yval = RetrieveYValue(i); + + bool subs1 = mIns[i + 3].mAddress != mIns[i + 1].mAddress; + bool subs2 = mIns[i + 3].mAddress != mIns[i + 2].mAddress; + + if (subs1 && subs2) + { + if (mLoopHead) + { + if (ChangesZeroPage(mIns[i + 1].mAddress)) + subs2 = false; + else if (ChangesZeroPage(mIns[i + 2].mAddress)) + subs1 = false; + } + } + proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 1], i + 7, yval)) + if (subs1 && CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 1], i + 7, yval, 0)) { proc->ResetPatched(); if (PatchForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 1], i + 7, yval)) @@ -38456,6 +38494,25 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass if (mFalseJump) mFalseJump->CheckLive(); } + else if (subs2) + { + proc->ResetPatched(); + if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval, 0)) + { + proc->ResetPatched(); + if (PatchForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval)) + { + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + + progress = true; + } + + if (mTrueJump) + mTrueJump->CheckLive(); + if (mFalseJump) + mFalseJump->CheckLive(); + } + } } #endif #if 1 @@ -38470,7 +38527,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { int yval = RetrieveYValue(i); proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 1].mAddress, mIns[i + 2], i + 7, yval)) + if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 1].mAddress, mIns[i + 2], i + 7, yval, 3)) { proc->ResetPatched(); if (PatchForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 1].mAddress, mIns[i + 2], i + 7, yval)) @@ -38504,7 +38561,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { int yval = RetrieveYValue(i); proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 2].mAddress, mIns[i + 0], i + 7, yval)) + if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 2].mAddress, mIns[i + 0], i + 7, yval, 3)) { proc->ResetPatched(); if (PatchForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 2].mAddress, mIns[i + 0], i + 7, yval)) @@ -38537,7 +38594,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { int yval = RetrieveYValue(i); proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval)) + if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval, 3)) { proc->ResetPatched(); if (PatchForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval)) @@ -38566,7 +38623,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass int yval = RetrieveYValue(i); proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval)) + if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval, 3)) { proc->ResetPatched(); if (PatchForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 3].mAddress, mIns[i + 2], i + 7, yval)) @@ -38595,7 +38652,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass int yval = RetrieveYValue(i); proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 2].mAddress, mIns[i + 1], i + 7, yval)) + if (CheckForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 2].mAddress, mIns[i + 1], i + 7, yval, 3)) { proc->ResetPatched(); if (PatchForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 2].mAddress, mIns[i + 1], i + 7, yval)) @@ -38622,7 +38679,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { int yval = RetrieveYValue(i); proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 1].mAddress, mIns[i + 2], i + 6, yval)) + if (CheckForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 1].mAddress, mIns[i + 2], i + 6, yval, 0)) { proc->ResetPatched(); if (PatchForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 1].mAddress, mIns[i + 2], i + 6, yval)) @@ -38650,7 +38707,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { int yval = RetrieveYValue(i); proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 1].mAddress, mIns[i + 2], i + 6, yval)) + if (CheckForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 1].mAddress, mIns[i + 2], i + 6, yval, 3)) { proc->ResetPatched(); if (PatchForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 1].mAddress, mIns[i + 2], i + 6, yval)) @@ -38681,7 +38738,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass NativeCodeInstruction iins(mIns[i + 0].mIns, ASMIT_STA, ASMIM_ZERO_PAGE, reg); proc->ResetPatched(); - if (CheckForwardSumYPointer(this, mIns[i + 1].mAddress, mIns[i + 1].mAddress, iins, i + 6, yval)) + if (CheckForwardSumYPointer(this, mIns[i + 1].mAddress, mIns[i + 1].mAddress, iins, i + 6, yval, 3)) { mIns[i + 0] = iins; for (int j = 1; j < 6; j++) @@ -40035,7 +40092,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "Y::Y"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "strlen"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 1479b4d..b5c8c5e 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -603,7 +603,7 @@ public: // iins : indexing instruction // at : start position in block // yval: known y immediate value of -1 if not known - bool CheckForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, const NativeCodeInstruction & iins, int at, int yval); + bool CheckForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, const NativeCodeInstruction & iins, int at, int yval, int ymax); bool PatchForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, const NativeCodeInstruction & iins, int at, int yval); // reg : base register pair to replace LSB with zero From a41c3d445b8207be8aa619b9f98f883f38f5ac27 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 27 Jun 2023 17:18:12 +0200 Subject: [PATCH 011/169] Add class, public, private and protected keywords --- oscar64/Declaration.h | 2 + oscar64/GlobalAnalyzer.cpp | 2 +- oscar64/Parser.cpp | 142 +++++++++++++++++++++++-------------- oscar64/Scanner.cpp | 14 +++- oscar64/Scanner.h | 4 ++ 5 files changed, 108 insertions(+), 56 deletions(-) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 5672068..5139bda 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -79,6 +79,8 @@ static const uint64 DTF_ZEROPAGE = (1ULL << 22); static const uint64 DTF_PREVENT_INLINE = (1ULL << 23); static const uint64 DTF_STRIPED = (1ULL << 24); static const uint64 DTF_DYNSTACK = (1ULL << 25); +static const uint64 DTF_PRIVATE = (1ULL << 26); +static const uint64 DTF_PROTECTED = (1ULL << 27); static const uint64 DTF_FUNC_VARIABLE = (1ULL << 32); static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33); diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index f299058..4fedd33 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -170,7 +170,7 @@ void GlobalAnalyzer::AutoInline(void) doinline = true; if (doinline) - { + { #if 0 printf("INLINING %s %d * (%d - 1)\n", f->mIdent->mString, cost, f->mCallers.Size()); #endif diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 1992d83..7f523b5 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -128,74 +128,95 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) Declaration* mlast = nullptr; for (;;) { - Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis); - - mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent); - - int offset = dec->mSize; - if (dt == DT_TYPE_UNION) - offset = 0; - - if (mdec->mBase->mType == DT_TYPE_FUNCTION) + if (ConsumeTokenIf(TK_PUBLIC)) { - mdec->mType = DT_CONST_FUNCTION; - mdec->mSection = mCodeSection; - mdec->mFlags |= DTF_GLOBAL; - mdec->mBase->mFlags |= DTF_FUNC_THIS; - - if (mCompilerOptions & COPT_NATIVE) - mdec->mFlags |= DTF_NATIVE; - - if (!(mdec->mFlags & DTF_DEFINED)) - ConsumeToken(TK_SEMICOLON); - - AddMemberFunction(dec, mdec); + flags &= ~(DTF_PRIVATE | DTF_PROTECTED); + ConsumeToken(TK_COLON); + } + else if (ConsumeTokenIf(TK_PROTECTED)) + { + flags &= ~DTF_PRIVATE; + flags |= DTF_PROTECTED; + ConsumeToken(TK_COLON); + } + else if (ConsumeTokenIf(TK_PRIVATE)) + { + flags |= DTF_PRIVATE | DTF_PROTECTED; + ConsumeToken(TK_COLON); } else { - while (mdec) + Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis); + + mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED); + + mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent); + + int offset = dec->mSize; + if (dt == DT_TYPE_UNION) + offset = 0; + + if (mdec->mBase->mType == DT_TYPE_FUNCTION) { - if (!(mdec->mBase->mFlags & DTF_DEFINED)) - mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); + mdec->mType = DT_CONST_FUNCTION; + mdec->mSection = mCodeSection; + mdec->mFlags |= DTF_GLOBAL; + mdec->mBase->mFlags |= DTF_FUNC_THIS; - if (mdec->mType != DT_VARIABLE) - { - mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected"); - break; - } + if (mCompilerOptions & COPT_NATIVE) + mdec->mFlags |= DTF_NATIVE; - mdec->mType = DT_ELEMENT; - mdec->mOffset = offset; + if (!(mdec->mFlags & DTF_DEFINED)) + ConsumeToken(TK_SEMICOLON); - offset += mdec->mBase->mSize; - if (offset > dec->mSize) - dec->mSize = offset; - - if (dec->mScope->Insert(mdec->mIdent, mdec)) - mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); - - if (mlast) - mlast->mNext = mdec; - else - dec->mParams = mdec; - mlast = mdec; - mdec = mdec->mNext; + AddMemberFunction(dec, mdec); } - - if (mScanner->mToken == TK_SEMICOLON) - mScanner->NextToken(); else { - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); + while (mdec) + { + if (!(mdec->mBase->mFlags & DTF_DEFINED)) + mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); + + if (mdec->mType != DT_VARIABLE) + { + mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected"); + break; + } + + mdec->mType = DT_ELEMENT; + mdec->mOffset = offset; + + offset += mdec->mBase->mSize; + if (offset > dec->mSize) + dec->mSize = offset; + + if (dec->mScope->Insert(mdec->mIdent, mdec)) + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + + if (mlast) + mlast->mNext = mdec; + else + dec->mParams = mdec; + mlast = mdec; + mdec = mdec->mNext; + } + + if (mScanner->mToken == TK_SEMICOLON) + mScanner->NextToken(); + else + { + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); + break; + } + } + + if (mScanner->mToken == TK_CLOSE_BRACE) + { + mScanner->NextToken(); break; } } - - if (mScanner->mToken == TK_CLOSE_BRACE) - { - mScanner->NextToken(); - break; - } } if (mlast) @@ -470,6 +491,9 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) case TK_STRUCT: dec = ParseStructDeclaration(flags, DT_TYPE_STRUCT); break; + case TK_CLASS: + dec = ParseStructDeclaration(flags | DTF_PRIVATE, DT_TYPE_STRUCT); + break; case TK_UNION: dec = ParseStructDeclaration(flags, DT_TYPE_UNION); break; @@ -3331,6 +3355,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex ndec->mValue = ParseFunction(ndec->mBase); + if (pthis) + ndec->mFlags |= DTF_REQUEST_INLINE; + ndec->mFlags |= DTF_DEFINED; ndec->mNumVars = mLocalIndex; @@ -3537,6 +3564,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) case TK_CONST: case TK_VOLATILE: case TK_STRUCT: + case TK_CLASS: case TK_UNION: case TK_TYPEDEF: case TK_STATIC: @@ -3872,6 +3900,12 @@ Expression* Parser::ParseQualify(Expression* exp) if (mdec) { + if (mdec->mFlags & DTF_PROTECTED) + { + if (!mThisPointer || mThisPointer->mBase->IsConstSame(dtype)) + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", mScanner->mTokenIdent); + } + mScanner->NextToken(); if (mdec->mType == DT_ELEMENT) { diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 91cba05..535e6f3 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -153,7 +153,11 @@ const char* TokenNames[] = "'namespace'", "'using'", "'this'", - "'::'" + "'::'", + "'class'", + "'public'", + "'protected'", + "'private'", }; @@ -1394,6 +1398,14 @@ void Scanner::NextRawToken(void) mToken = TK_USING; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "this")) mToken = TK_THIS; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "class")) + mToken = TK_CLASS; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "public")) + mToken = TK_PUBLIC; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "protected")) + mToken = TK_PROTECTED; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "private")) + mToken = TK_PRIVATE; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 08a4992..a7474a3 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -153,6 +153,10 @@ enum Token TK_USING, TK_THIS, TK_COLCOLON, + TK_CLASS, + TK_PUBLIC, + TK_PROTECTED, + TK_PRIVATE, NUM_TOKENS }; From 478f93922deada7fe06cf46ad5e84b5ce4c9145e Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 27 Jun 2023 18:16:13 +0200 Subject: [PATCH 012/169] Error on pointer/integer compare --- oscar64/InterCodeGenerator.cpp | 12 +++++++++-- oscar64/NativeCodeGenerator.cpp | 35 +++++++++++++++++--------------- oscar64/NativeCodeGenerator.h | 8 +++++++- oscar64/Parser.cpp | 2 +- samples/memmap/charsetload.d64 | Bin 174848 -> 174848 bytes 5 files changed, 37 insertions(+), 20 deletions(-) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 9fe9cf9..da41554 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -2452,8 +2452,16 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mType->mType == DT_TYPE_POINTER || vr.mType->mType == DT_TYPE_POINTER) { dtype = vl.mType; - if (vl.mType->IsIntegerType() || vr.mType->IsIntegerType()) - ; + if (vl.mType->IsIntegerType()) + { + if ((mCompilerOptions & COPT_CPLUSPLUS) || exp->mLeft->mType != EX_CONSTANT || exp->mLeft->mDecValue->mInteger != 0) + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot compare integer and pointer"); + } + else if (vr.mType->IsIntegerType()) + { + if ((mCompilerOptions & COPT_CPLUSPLUS) || exp->mRight->mType != EX_CONSTANT || exp->mRight->mDecValue->mInteger != 0) + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot compare integer and pointer"); + } else if ((vl.mType->mType == DT_TYPE_POINTER || vl.mType->mType == DT_TYPE_ARRAY) && (vr.mType->mType == DT_TYPE_POINTER || vr.mType->mType == DT_TYPE_ARRAY)) { if (vl.mType->mBase->mType == DT_TYPE_VOID || vr.mType->mBase->mType == DT_TYPE_VOID) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 308af63..166976a 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -12350,7 +12350,7 @@ void NativeCodeBasicBlock::BuildCollisionTable(NumberSet* collisionSets) } } -void NativeCodeBasicBlock::BuildDominatorTree(NativeCodeBasicBlock* from) +void NativeCodeBasicBlock::BuildDominatorTree(NativeCodeBasicBlock* from, DominatorStacks& stacks) { if (from == this) return; @@ -12360,25 +12360,26 @@ void NativeCodeBasicBlock::BuildDominatorTree(NativeCodeBasicBlock* from) return; else { - ExpandingArray< NativeCodeBasicBlock * > d1, d2; + stacks.d1.SetSize(0); + stacks.d2.SetSize(0); NativeCodeBasicBlock* b = mDominator; while (b) { - d1.Push(b); + stacks.d1.Push(b); b = b->mDominator; } b = from; while (b) { - d2.Push(b); + stacks.d2.Push(b); b = b->mDominator; } b = nullptr; - while (d1.Size() > 0 && d2.Size() > 0 && d1.Last() == d2.Last()) + while (stacks.d1.Size() > 0 && stacks.d2.Size() > 0 && stacks.d1.Last() == stacks.d2.Last()) { - b = d1.Pop(); d2.Pop(); + b = stacks.d1.Pop(); stacks.d2.Pop(); } if (mDominator == b) @@ -12388,9 +12389,9 @@ void NativeCodeBasicBlock::BuildDominatorTree(NativeCodeBasicBlock* from) } if (mTrueJump) - mTrueJump->BuildDominatorTree(this); + mTrueJump->BuildDominatorTree(this, stacks); if (mFalseJump) - mFalseJump->BuildDominatorTree(this); + mFalseJump->BuildDominatorTree(this, stacks); } @@ -40657,8 +40658,9 @@ void NativeCodeProcedure::RebuildEntry(void) ResetVisited(); mEntryBlock->CollectEntryBlocks(nullptr); + NativeCodeBasicBlock::DominatorStacks stacks; - mEntryBlock->BuildDominatorTree(nullptr); + mEntryBlock->BuildDominatorTree(nullptr, stacks); } void NativeCodeProcedure::Optimize(void) @@ -41523,13 +41525,14 @@ void NativeCodeProcedure::ResetPatched(void) { for (int i = 0; i < mBlocks.Size(); i++) { - mBlocks[i]->mPatched = false; - mBlocks[i]->mPatchFail = false; - mBlocks[i]->mPatchChecked = false; - mBlocks[i]->mPatchStart = false; - mBlocks[i]->mPatchLoop = false; - mBlocks[i]->mPatchLoopChanged = false; - mBlocks[i]->mPatchExit = false; + NativeCodeBasicBlock* b = mBlocks[i]; + b->mPatched = false; + b->mPatchFail = false; + b->mPatchChecked = false; + b->mPatchStart = false; + b->mPatchLoop = false; + b->mPatchLoopChanged = false; + b->mPatchExit = false; } } diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index b5c8c5e..97e44bb 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -370,7 +370,13 @@ public: NativeCodeBasicBlock * ForwardAccuBranch(bool eq, bool ne, bool pl, bool mi, int limit); bool MergeBasicBlocks(void); void MarkLoopHead(void); - void BuildDominatorTree(NativeCodeBasicBlock * from); + + struct DominatorStacks + { + ExpandingArray< NativeCodeBasicBlock* > d1, d2; + }; + + void BuildDominatorTree(NativeCodeBasicBlock * from, DominatorStacks & stacks); bool MoveLoadStoreUp(int at); bool MoveLoadStoreXUp(int at); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 7f523b5..79cbbaf 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1253,7 +1253,7 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) { Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); pthisexp->mDecType = pthis; - pthisexp->mDecValue = pthis->mBase->mDestructor->mBase->mParams; + pthisexp->mDecValue = cfunc->mBase->mParams; Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); thisexp->mToken = TK_MUL; diff --git a/samples/memmap/charsetload.d64 b/samples/memmap/charsetload.d64 index 10be50be15aa602a57eabdf0893cd37ca9108bc4..ea91a386155aba5183c7a05d6e7a7fb6eb237590 100644 GIT binary patch delta 660 zcmYL^L1+^}6ozMZ(>6QpCcCI5c3L{oQ(6kGpsn;^CA*0U#fvEjR#?FldK0fbB$rpA z5NR%M1uKnq0#8u%6c8$kQVaw;2hGV!Js9mRH!sDNMAXy&zsLLjpI26MB_ z<93*a`@@VpJTrN2iV*Vh?nj1AIEf5~W{@2+Kc1t<^zVmFe>z7;bx{oa#T*?gU>r;| zAR_t=)WC!&h9M#*49VNaQG*B)h~jIo#DamEIM0xP2@$Zc(cRnPB6~zuoh`DOieV$~ zKzgm5iY?P8(pe_p)OFQ5_@NHO{r_YLqG)wV+o)*^^cSsI)UpR~y3}GokpPEb&%eD$ zPxT?Gnww4LKUkzgg`9yDxL1wrG+BL4g^;udR-H8wWs<8t47wZ=a3KXr5oeM^T8uNv z+oAfLvSf1df*O(Ob}u9)Z-0@z>TEWdILo99T&Cu48PbJJOj`LAWMz6gTF$gwrL|JK zNy(L(m|rnsGMaZG^XFtnX1=8%EwhINF3Dt~0LfV11$SL*rM7CpRjO$fixxh=NS8D3 z-zC*gB%Nkeo?kJ*teRpsKmxWMb&=|3g{L6Vd=zDqkit2Yp MmuPKtN&D*j2J+|cn*aa+ delta 1585 zcmY*ZU5Fc16h8MRo6gQ;Cdt}eGP%)=P8w_*BvrIQP%D{DcV(2)ZlzMiY$1i(BJ@R3 zl&obhMj^66)~pYffP0rtKBC@TP3!Nu;ehJNqv$tL!7|zaPaZmQyT!_=qG~_L!hz| zp^3Z^S&B3sot_J z+<0XIt*b|0Uf7OsB_`y81H?Y(swbl-y^uTRhxPz*Oz+}q>m`>lE6uI+paAGQxw&{* zu01EQ#2%<^k`#a@m@1VmQ>BTjzKhE<^@eOwm8IQ~Hsxu2h^?us7R%JtxqP{z(lrK@ z(==0cxbLtT2$8l4($|_aekf!M-^7LF~ zeHUlSG-a7GRV=@ES1qvz>MBc7nJF}(?_4?8MwX6+0pQ8-`&>R;a3KI}4FinI!gMFhAZ){!zYEV)%V zX^Zrc1aMONO}Zrk9O>>r7!z_srfGeWyW6$fv_8oJs-sRN7WEYVzyNp#nTsfb$atc&mV5s4(+;;QQ-0|8z@& z*(gNa60$KvA|!)=gb4hD;W}VgX5xV4aLuk|iuQkv2X~<1eai+ch+ha1e=wN1Ak9aV zqg~}hcZOr4ayNl7L`v0 zMx5Z;O?H$Oa?jX=6`c@Wcnt+AvDF1eoGXmf#E5cGU>YTCRR4iz8Xb!pC(5IAoE4i; zA6wLHyf}KMz=-{$eu+0Af3--91}p*H+%I(Zl#8^;#><=OW>#2Rp@n!^quLB!9BqPG ztdCiz3iiJSP?zUp{ZfTrUJ#WtU3cIQW4|-yLf3bI(z0^oEQW+gb+=r>%=tyce{#E-Qa77SQ From 3d6b60c9f4396dcf0d89cfa035d49390d3cae3e8 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 28 Jun 2023 22:14:29 +0200 Subject: [PATCH 013/169] Implement base class constructors --- oscar64/Declaration.cpp | 100 ++++++++++++++++------- oscar64/Declaration.h | 5 +- oscar64/GlobalAnalyzer.cpp | 2 +- oscar64/InterCodeGenerator.cpp | 34 ++++---- oscar64/Parser.cpp | 141 ++++++++++++++++++++++++++++++--- oscar64/Parser.h | 2 + 6 files changed, 226 insertions(+), 58 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index bd4f610..38b65d7 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -447,46 +447,46 @@ Expression* Expression::ConstantFold(Errors * errors) return ex; } #endif - else if (mType == EX_TYPECAST && mRight->mType == EX_CONSTANT) + else if (mType == EX_TYPECAST && mLeft->mType == EX_CONSTANT) { - if (mLeft->mDecType->mType == DT_TYPE_POINTER) + if (mDecType->mType == DT_TYPE_POINTER) { - if (mRight->mDecValue->mType == DT_CONST_ADDRESS || mRight->mDecValue->mType == DT_CONST_INTEGER) + if (mLeft->mDecValue->mType == DT_CONST_ADDRESS || mLeft->mDecValue->mType == DT_CONST_INTEGER) { Expression* ex = new Expression(mLocation, EX_CONSTANT); Declaration* dec = new Declaration(mLocation, DT_CONST_ADDRESS); - dec->mBase = mLeft->mDecType; - dec->mInteger = mRight->mDecValue->mInteger; + dec->mBase = mDecType; + dec->mInteger = mLeft->mDecValue->mInteger; ex->mDecValue = dec; - ex->mDecType = mLeft->mDecType; + ex->mDecType = mDecType; return ex; } - else if (mRight->mDecValue->mType == DT_CONST_FUNCTION) + else if (mLeft->mDecValue->mType == DT_CONST_FUNCTION) { Expression* ex = new Expression(mLocation, EX_CONSTANT); - ex->mDecValue = mRight->mDecValue; - ex->mDecType = mLeft->mDecType; + ex->mDecValue = mLeft->mDecValue; + ex->mDecType = mDecType; return ex; } } - else if (mLeft->mDecType->mType == DT_TYPE_INTEGER) + else if (mDecType->mType == DT_TYPE_INTEGER) { - if (mRight->mDecValue->mType == DT_CONST_FLOAT) + if (mLeft->mDecValue->mType == DT_CONST_FLOAT) { Expression* ex = new Expression(mLocation, EX_CONSTANT); Declaration* dec = new Declaration(mLocation, DT_CONST_INTEGER); - dec->mBase = mLeft->mDecType; - dec->mInteger = int64(mRight->mDecValue->mNumber); + dec->mBase = mDecType; + dec->mInteger = int64(mLeft->mDecValue->mNumber); ex->mDecValue = dec; - ex->mDecType = mLeft->mDecType; + ex->mDecType = mDecType; return ex; } - else if (mRight->mDecValue->mType == DT_CONST_INTEGER) + else if (mLeft->mDecValue->mType == DT_CONST_INTEGER) { - int64 sval = 1ULL << (8 * mLeft->mDecType->mSize); - int64 v = mRight->mDecValue->mInteger & (sval - 1); + int64 sval = 1ULL << (8 * mDecType->mSize); + int64 v = mLeft->mDecValue->mInteger & (sval - 1); - if (mLeft->mDecType->mFlags & DTF_SIGNED) + if (mDecType->mFlags & DTF_SIGNED) { if (v & (sval >> 1)) v -= sval; @@ -494,23 +494,23 @@ Expression* Expression::ConstantFold(Errors * errors) Expression* ex = new Expression(mLocation, EX_CONSTANT); Declaration* dec = new Declaration(mLocation, DT_CONST_INTEGER); - dec->mBase = mLeft->mDecType; + dec->mBase = mDecType; dec->mInteger = v; ex->mDecValue = dec; - ex->mDecType = mLeft->mDecType; + ex->mDecType = mDecType; return ex; } } - else if (mLeft->mDecType->mType == DT_TYPE_FLOAT) + else if (mDecType->mType == DT_TYPE_FLOAT) { - if (mRight->mDecValue->mType == DT_CONST_INTEGER) + if (mLeft->mDecValue->mType == DT_CONST_INTEGER) { Expression* ex = new Expression(mLocation, EX_CONSTANT); Declaration* dec = new Declaration(mLocation, DT_CONST_FLOAT); - dec->mBase = mLeft->mDecType; - dec->mNumber = double(mRight->mDecValue->mInteger); + dec->mBase = mDecType; + dec->mNumber = double(mLeft->mDecValue->mInteger); ex->mDecValue = dec; - ex->mDecType = mLeft->mDecType; + ex->mDecType = mDecType; return ex; } } @@ -781,7 +781,8 @@ Expression* Expression::ConstantFold(Errors * errors) Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), - mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), + mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), + mConst(nullptr), mMutable(nullptr), mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), @@ -938,12 +939,49 @@ Declaration* Declaration::ToConstType(void) ndec->mParams = mParams; ndec->mIdent = mIdent; ndec->mQualIdent = mQualIdent; + + ndec->mDefaultConstructor = mDefaultConstructor; + ndec->mCopyConstructor = mCopyConstructor; + ndec->mVectorConstructor = mVectorConstructor; + ndec->mVectorCopyConstructor = mVectorCopyConstructor; + + ndec->mMutable = this; mConst = ndec; } return mConst; } +Declaration* Declaration::ToMutableType(void) +{ + if (!(mFlags & DTF_CONST)) + return this; + + if (!mMutable) + { + Declaration* ndec = new Declaration(mLocation, mType); + ndec->mSize = mSize; + ndec->mStride = mStride; + ndec->mBase = mBase; + ndec->mFlags = mFlags | DTF_CONST; + ndec->mScope = mScope; + ndec->mParams = mParams; + ndec->mIdent = mIdent; + ndec->mQualIdent = mQualIdent; + + ndec->mDefaultConstructor = mDefaultConstructor; + ndec->mCopyConstructor = mCopyConstructor; + ndec->mVectorConstructor = mVectorConstructor; + ndec->mVectorCopyConstructor = mVectorCopyConstructor; + + ndec->mConst = this; + mMutable = ndec; + } + + return mMutable; +} + + bool Declaration::IsSubType(const Declaration* dec) const { if (this == dec) @@ -978,7 +1016,15 @@ bool Declaration::IsSubType(const Declaration* dec) const return true; if (dec->mBase) - return IsSubType(dec->mBase); + { + Declaration* bcdec = dec->mBase; + while (bcdec) + { + if (IsSubType(bcdec->mBase)) + return true; + bcdec = bcdec->mNext; + } + } return false; } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 5139bda..3667799 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -49,6 +49,7 @@ enum DecType DT_FUNCTION_REF, DT_LABEL_REF, DT_NAMESPACE, + DT_BASECLASS }; // TypeFlags @@ -222,7 +223,7 @@ public: Location mLocation, mEndLocation; DecType mType; Token mToken; - Declaration * mBase, * mParams, * mNext, * mPrev, * mConst; + Declaration * mBase, * mParams, * mNext, * mPrev, * mConst, * mMutable; Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; @@ -254,6 +255,8 @@ public: void SetDefined(void); Declaration* ToConstType(void); + Declaration* ToMutableType(void); + Declaration* ToStriped(int stripe); Declaration* ToStriped(Errors* errors); Declaration* Clone(void); diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 4fedd33..20f2221 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -823,7 +823,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo case EX_TYPE: break; case EX_TYPECAST: - return Analyze(exp->mRight, procDec, false); + return Analyze(exp->mLeft, procDec, false); break; case EX_LOGICAL_AND: ldec = Analyze(exp->mLeft, procDec, false); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index da41554..855932f 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -3739,11 +3739,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_TYPECAST: { - vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); + vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); - if (exp->mLeft->mDecType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType()) + if (exp->mDecType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType()) { vr = Dereference(proc, exp, block, vr); @@ -3778,50 +3778,50 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mOperator = (vr.mType->mFlags & DTF_SIGNED) ? IA_INT2FLOAT : IA_UINT2FLOAT; ins->mSrc[0].mType = IT_INT16; ins->mSrc[0].mTemp = stemp; - ins->mDst.mType = InterTypeOf(exp->mLeft->mDecType); + ins->mDst.mType = InterTypeOf(exp->mDecType); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); block->Append(ins); } - else if (exp->mLeft->mDecType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT) + else if (exp->mDecType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT) { vr = Dereference(proc, exp, block, vr); - ins->mOperator = (exp->mLeft->mDecType->mFlags & DTF_SIGNED) ? IA_FLOAT2INT : IA_FLOAT2UINT; + ins->mOperator = (exp->mDecType->mFlags & DTF_SIGNED) ? IA_FLOAT2INT : IA_FLOAT2UINT; ins->mSrc[0].mType = InterTypeOf(vr.mType); ins->mSrc[0].mTemp = vr.mTemp; ins->mDst.mType = IT_INT16; ins->mDst.mTemp = proc->AddTemporary(IT_INT16); block->Append(ins); - if (exp->mLeft->mDecType->mSize == 1) + if (exp->mDecType->mSize == 1) { InterInstruction* xins = new InterInstruction(exp->mLocation, IC_TYPECAST); xins->mSrc[0].mType = IT_INT16; xins->mSrc[0].mTemp = ins->mDst.mTemp; - xins->mDst.mType = InterTypeOf(exp->mLeft->mDecType); + xins->mDst.mType = InterTypeOf(exp->mDecType); xins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); block->Append(xins); ins = xins; } } - else if (exp->mLeft->mDecType->mType == DT_TYPE_POINTER && vr.mType->mType == DT_TYPE_POINTER) + else if (exp->mDecType->mType == DT_TYPE_POINTER && vr.mType->mType == DT_TYPE_POINTER) { // no need for actual operation when casting pointer to pointer - return ExValue(exp->mLeft->mDecType, vr.mTemp, vr.mReference); + return ExValue(exp->mDecType, vr.mTemp, vr.mReference); } - else if (exp->mLeft->mDecType->mType == DT_TYPE_POINTER && vr.mType->mType == DT_TYPE_ARRAY) + else if (exp->mDecType->mType == DT_TYPE_POINTER && vr.mType->mType == DT_TYPE_ARRAY) { // no need for actual operation when casting pointer to pointer - return ExValue(exp->mLeft->mDecType, vr.mTemp, vr.mReference - 1); + return ExValue(exp->mDecType, vr.mTemp, vr.mReference - 1); } - else if (exp->mLeft->mDecType->mType != DT_TYPE_VOID && vr.mType->mType == DT_TYPE_VOID) + else if (exp->mDecType->mType != DT_TYPE_VOID && vr.mType->mType == DT_TYPE_VOID) { mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Cannot cast void object to non void object"); - return ExValue(exp->mLeft->mDecType, vr.mTemp, vr.mReference); + return ExValue(exp->mDecType, vr.mTemp, vr.mReference); } - else if (exp->mLeft->mDecType->IsIntegerType() && vr.mType->IsIntegerType()) + else if (exp->mDecType->IsIntegerType() && vr.mType->IsIntegerType()) { vr = Dereference(proc, exp, block, vr); - return CoerceType(proc, exp, block, vr, exp->mLeft->mDecType); + return CoerceType(proc, exp, block, vr, exp->mDecType); } else { @@ -3829,12 +3829,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mCode = IC_TYPECAST; ins->mSrc[0].mType = InterTypeOf(vr.mType); ins->mSrc[0].mTemp = vr.mTemp; - ins->mDst.mType = InterTypeOf(exp->mLeft->mDecType); + ins->mDst.mType = InterTypeOf(exp->mDecType); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); block->Append(ins); } - return ExValue(exp->mLeft->mDecType, ins->mDst.mTemp); + return ExValue(exp->mDecType, ins->mDst.mTemp); } break; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 79cbbaf..4718930 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -104,8 +104,12 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) { if (pdec->mType == DT_TYPE_STRUCT) { - dec->mBase = pdec; + Declaration* bcdec = new Declaration(mScanner->mLocation, DT_BASECLASS); + bcdec->mBase = pdec; + dec->mSize = pdec->mSize; + + dec->mBase = bcdec; } else mErrors->Error(mScanner->mLocation, ERRO_NOT_A_BASE_CLASS, "Not a base class", dec->mIdent); @@ -1260,9 +1264,44 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) thisexp->mDecType = pthis->mBase; thisexp->mLeft = pthisexp; + Declaration* bcdec = pthis->mBase->mBase; + while (bcdec) + { + Declaration* mfunc = cfunc->mScope ? cfunc->mScope->Lookup(bcdec->mBase->mIdent) : nullptr; + + if (mfunc) + { + Expression* sexp = new Expression(cfunc->mLocation, EX_SEQUENCE); + sexp->mLeft = mfunc->mValue; + sexp->mRight = cfunc->mValue; + cfunc->mValue = sexp; + } + else if (bcdec->mBase->mDefaultConstructor) + { + Declaration* mdec = bcdec->mBase->mDefaultConstructor; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression * dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pthisexp; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = cfunc->mValue; + cfunc->mValue = sexp; + } + + bcdec = bcdec->mNext; + } + Declaration* dec = pthis->mBase->mParams; if (dec) { + dec = dec->Last(); while (dec) { @@ -1387,7 +1426,28 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc) if (ExpectToken(TK_IDENT)) { Declaration* dec = pthis->mBase->mScope->Lookup(mScanner->mTokenIdent); - if (dec && dec->mType == DT_ELEMENT) + + Declaration* pcdec = pthis->mBase->mBase; + while (pcdec && pcdec->mBase->mIdent != mScanner->mTokenIdent) + pcdec = pcdec->mNext; + + if (pcdec) + { + Expression* qexp = new Expression(mScanner->mLocation, EX_PREFIX); + qexp->mToken = TK_MUL; + qexp->mDecType = pcdec->mBase; + qexp->mLeft = pthisexp; + + Declaration* dec = new Declaration(mScanner->mLocation, DT_CONST_CONSTRUCTOR); + dec->mIdent = mScanner->mTokenIdent; + + mScanner->NextToken(); + + dec->mValue = BuildMemberInitializer(qexp); + + cfunc->mScope->Insert(dec->mIdent, dec); + } + else if (dec && dec->mType == DT_ELEMENT) { Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); qexp->mLeft = thisexp; @@ -1415,7 +1475,7 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc) void Parser::AddDefaultConstructors(Declaration* pthis) { - bool simpleDestructor = true, simpleAssignment = true; + bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true; char dname[100]; strcpy_s(dname, "~"); @@ -1455,6 +1515,20 @@ void Parser::AddDefaultConstructors(Declaration* pthis) adec = adec->mNext; } + Declaration* bcdec = pthis->mBase->mBase; + while (bcdec) + { + if (bcdec->mBase->mDestructor) + simpleDestructor = false; + if (bcdec->mBase->mDefaultConstructor) + simpleConstructor = false; + if (bcdec->mBase->mCopyConstructor) + simpleCopy = false; + if (bcdec->mBase->mCopyAssignment) + simpleAssignment = false; + bcdec = bcdec->mNext; + } + Declaration* dec = pthis->mBase->mParams; while (dec) { @@ -1470,6 +1544,10 @@ void Parser::AddDefaultConstructors(Declaration* pthis) { if (bdec->mDestructor) simpleDestructor = false; + if (bdec->mDefaultConstructor) + simpleConstructor = false; + if (bdec->mCopyConstructor) + simpleCopy = false; if (bdec->mCopyAssignment) simpleAssignment = false; } @@ -1514,7 +1592,10 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); } + } + if (!simpleConstructor) + { if (!pthis->mBase->mDefaultConstructor) { Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); @@ -1552,7 +1633,10 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); } + } + if (!simpleCopy) + { if (!pthis->mBase->mCopyConstructor) { Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); @@ -2567,8 +2651,10 @@ void Parser::ParseVariableInit(Declaration* ndec) if (fcons) { + Declaration* mtype = ndec->mBase->ToMutableType(); + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); - vexp->mDecType = ndec->mBase; + vexp->mDecType = mtype; vexp->mDecValue = ndec; Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); @@ -2584,7 +2670,7 @@ void Parser::ParseVariableInit(Declaration* ndec) texp->mLeft = vexp; texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = ndec->mBase; + texp->mDecType->mBase = mtype; texp->mDecType->mSize = 2; if (fexp->mRight) @@ -2793,7 +2879,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec->mValue = ParseFunction(cdec->mBase); - cdec->mFlags |= DTF_DEFINED; + cdec->mFlags |= DTF_DEFINED | DTF_REQUEST_INLINE; cdec->mNumVars = mLocalIndex; } @@ -2880,7 +2966,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec->mValue = ParseFunction(cdec->mBase); - cdec->mFlags |= DTF_DEFINED; + cdec->mFlags |= DTF_DEFINED | DTF_REQUEST_INLINE; cdec->mNumVars = mLocalIndex; } @@ -3238,6 +3324,8 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (bdec && bdec->mDefaultConstructor) { + bdec = bdec->ToMutableType(); + Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE); vexp->mDecType = ndec->mBase; vexp->mDecValue = ndec; @@ -3844,8 +3932,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) { Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; - nexp->mLeft = exp; - nexp->mRight = ParsePrefixExpression(false); + nexp->mLeft = ParsePrefixExpression(false); exp = nexp->ConstantFold(mErrors); } } @@ -3882,6 +3969,36 @@ Expression* Parser::ParseSimpleExpression(bool lhs) return exp; } +Declaration* Parser::MemberLookup(Declaration* dtype, const Ident* ident, int & offset) +{ + Declaration* mdec = dtype->mScope->Lookup(ident); + offset = 0; + + if (!mdec) + { + Declaration* bcdec = dtype->mBase; + + while (bcdec) + { + int noffset; + Declaration* ndec = MemberLookup(bcdec->mBase, ident, noffset); + if (ndec) + { + if (mdec) + mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Multiple definitions for member", ident); + else + { + mdec = ndec; + offset = noffset + bcdec->mOffset; + } + } + bcdec = bcdec->mNext; + } + } + + return mdec; +} + Expression* Parser::ParseQualify(Expression* exp) { @@ -3896,7 +4013,8 @@ Expression* Parser::ParseQualify(Expression* exp) nexp->mLeft = exp; if (mScanner->mToken == TK_IDENT) { - Declaration* mdec = dtype->mScope->Lookup(mScanner->mTokenIdent); + int moffset; + Declaration* mdec = MemberLookup(dtype, mScanner->mTokenIdent, moffset); if (mdec) { @@ -4207,8 +4325,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) { Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; - nexp->mLeft = exp; - nexp->mRight = pexp; + nexp->mLeft = pexp; exp = nexp->ConstantFold(mErrors); } } diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 6e749f7..0ff0b9c 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -82,6 +82,8 @@ protected: Expression* ParseStatement(void); Expression* ParseSwitchStatement(void); + Declaration* MemberLookup(Declaration* dtype, const Ident * ident, int& offset); + Expression* ParseQualify(Expression * exp); int OverloadDistance(Declaration* pdec, Expression* pexp); From fa9aa9c2bb2ef1f165e1a9ad9dc49f36a659d1cd Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 29 Jun 2023 16:34:38 +0200 Subject: [PATCH 014/169] Visibility in base classes --- oscar64/Parser.cpp | 31 ++++++++++++++++++++++++------- oscar64/Parser.h | 2 +- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 4718930..4f39d9f 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -99,6 +99,15 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_COLON) { mScanner->NextToken(); + uint64 pflags = flags; + + if (ConsumeTokenIf(TK_PUBLIC)) + pflags &= ~(DTF_PRIVATE | DTF_PROTECTED); + else if (ConsumeTokenIf(TK_PROTECTED)) + pflags = (pflags & ~DTF_PRIVATE) | DTF_PROTECTED; + else if (ConsumeTokenIf(TK_PRIVATE)) + pflags |= DTF_PRIVATE | DTF_PROTECTED; + Declaration* pdec = ParseQualIdent(); if (pdec) { @@ -106,6 +115,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) { Declaration* bcdec = new Declaration(mScanner->mLocation, DT_BASECLASS); bcdec->mBase = pdec; + bcdec->mFlags = pflags; dec->mSize = pdec->mSize; @@ -496,7 +506,7 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) dec = ParseStructDeclaration(flags, DT_TYPE_STRUCT); break; case TK_CLASS: - dec = ParseStructDeclaration(flags | DTF_PRIVATE, DT_TYPE_STRUCT); + dec = ParseStructDeclaration(flags | DTF_PRIVATE | DTF_PROTECTED, DT_TYPE_STRUCT); break; case TK_UNION: dec = ParseStructDeclaration(flags, DT_TYPE_UNION); @@ -3969,19 +3979,22 @@ Expression* Parser::ParseSimpleExpression(bool lhs) return exp; } -Declaration* Parser::MemberLookup(Declaration* dtype, const Ident* ident, int & offset) +Declaration* Parser::MemberLookup(Declaration* dtype, const Ident* ident, int & offset, uint64& flags) { Declaration* mdec = dtype->mScope->Lookup(ident); offset = 0; + flags = 0; if (!mdec) { Declaration* bcdec = dtype->mBase; - + while (bcdec) { - int noffset; - Declaration* ndec = MemberLookup(bcdec->mBase, ident, noffset); + int noffset; + uint64 nflags; + + Declaration* ndec = MemberLookup(bcdec->mBase, ident, noffset, nflags); if (ndec) { if (mdec) @@ -3990,11 +4003,14 @@ Declaration* Parser::MemberLookup(Declaration* dtype, const Ident* ident, int & { mdec = ndec; offset = noffset + bcdec->mOffset; + flags = nflags | bcdec->mFlags; } } bcdec = bcdec->mNext; } } + else + flags = mdec->mFlags; return mdec; } @@ -4014,11 +4030,12 @@ Expression* Parser::ParseQualify(Expression* exp) if (mScanner->mToken == TK_IDENT) { int moffset; - Declaration* mdec = MemberLookup(dtype, mScanner->mTokenIdent, moffset); + uint64 mflags; + Declaration* mdec = MemberLookup(dtype, mScanner->mTokenIdent, moffset, mflags); if (mdec) { - if (mdec->mFlags & DTF_PROTECTED) + if (mflags & DTF_PROTECTED) { if (!mThisPointer || mThisPointer->mBase->IsConstSame(dtype)) mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", mScanner->mTokenIdent); diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 0ff0b9c..b0515fe 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -82,7 +82,7 @@ protected: Expression* ParseStatement(void); Expression* ParseSwitchStatement(void); - Declaration* MemberLookup(Declaration* dtype, const Ident * ident, int& offset); + Declaration* MemberLookup(Declaration* dtype, const Ident * ident, int& offset, uint64 & flags); Expression* ParseQualify(Expression * exp); From 1b73df7e254d0ca1e2132afdde5b6d381238fb41 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:11:11 +0200 Subject: [PATCH 015/169] const member functions --- include/opp/string.cpp | 147 ++++++++++++++++++++++++++++++++++++++++ include/opp/string.h | 45 ++++++++++++ oscar64/Declaration.cpp | 9 +++ oscar64/Declaration.h | 2 + oscar64/Parser.cpp | 116 +++++++++++++++++++++++++++---- oscar64/Scanner.cpp | 67 ++++++++++++++++++ 6 files changed, 374 insertions(+), 12 deletions(-) create mode 100644 include/opp/string.cpp create mode 100644 include/opp/string.h diff --git a/include/opp/string.cpp b/include/opp/string.cpp new file mode 100644 index 0000000..9d79206 --- /dev/null +++ b/include/opp/string.cpp @@ -0,0 +1,147 @@ +#include "string.h" +#include +#include + +string::string(void) : cstr(nullptr) +{} + +string::string(const string & s) +{ + cstr = malloc(strlen(s.cstr) + 1); + strcpy(cstr, s.cstr); +} + +string::string(const char * s) +{ + cstr = malloc(strlen(s) + 1); + strcpy(cstr, s); +} + +string::string(const char * s1, const char * s2) +{ + cstr = malloc(strlen(s1) + strlen(s2) + 1); + strcpy(cstr, s1); + strcat(cstr, s2); +} + +string::~string(void) +{ + free(cstr); +} + +string & string::operator=(const string & s) +{ + if (cstr != s.cstr) + { + free(cstr); + cstr = malloc(strlen(s.cstr) + 1); + strcpy(cstr, s.cstr); + } + + return *this; +} + +string & string::operator=(const char * s) +{ + free(cstr); + cstr = malloc(strlen(s) + 1); + strcpy(cstr, s); + + return *this; +} + +string & string::operator+=(const string & s) +{ + char * nstr = malloc(strlen(cstr) + strlen(s.cstr) + 1); + strcpy(nstr, cstr); + strcat(nstr, s.cstr); + free(cstr); + cstr = nstr; + return *this; +} + +string & string::operator+=(const char * s) +{ + char * nstr = malloc(strlen(cstr) + strlen(s) + 1); + strcpy(nstr, cstr); + strcat(nstr, s); + free(cstr); + cstr = nstr; + return *this; +} + +inline const char * string::tocstr(void) const +{ + return cstr; +} + +string string::operator+(const string & s) +{ + return string(cstr, s.cstr); +} + +string string::operator+(const char * s) +{ + return string(cstr, s); +} + + +inline bool string::operator==(const string & s) const +{ + return strcmp(cstr, s.cstr) == 0; +} + +inline bool string::operator==(const char * s) const +{ + return strcmp(cstr, s) == 0; +} + +inline bool string::operator!=(const string & s) const +{ + return strcmp(cstr, s.cstr) != 0; +} + +inline bool string::operator!=(const char * s) const +{ + return strcmp(cstr, s) == 0; +} + +inline bool string::operator<(const string & s) const +{ + return strcmp(cstr, s.cstr) < 0; +} + +inline bool string::operator<(const char * s) const +{ + return strcmp(cstr, s) < 0; +} + +inline bool string::operator<=(const string & s) const +{ + return strcmp(cstr, s.cstr) <= 0; +} + +inline bool string::operator<=(const char * s) const +{ + return strcmp(cstr, s) <= 0; +} + +inline bool string::operator>(const string & s) const +{ + return strcmp(cstr, s.cstr) > 0; +} + +inline bool string::operator>(const char * s) const +{ + return strcmp(cstr, s) > 0; +} + +inline bool string::operator>=(const string & s) const +{ + return strcmp(cstr, s.cstr) >= 0; +} + +inline bool string::operator>=(const char * s) const +{ + return strcmp(cstr, s) >= 0; +} diff --git a/include/opp/string.h b/include/opp/string.h new file mode 100644 index 0000000..a0b4926 --- /dev/null +++ b/include/opp/string.h @@ -0,0 +1,45 @@ +#ifndef OPP_STRING_H +#define OPP_STRING_H + +class string +{ +private: + char * cstr; + +public: + string(void); + string(const string & s); + string(const char * s); + string(const char * s1, const char * s2); + ~string(void); + + string & operator=(const string & s); + string & operator=(const char * s); + + string & operator+=(const string & s); + string & operator+=(const char * s); + + string operator+(const string & s); + string operator+(const char * s); + + bool operator==(const string & s) const; + bool operator==(const char * s) const; + bool operator!=(const string & s) const; + bool operator!=(const char * s) const; + + bool operator<(const string & s) const; + bool operator<(const char * s) const; + bool operator<=(const string & s) const; + bool operator<=(const char * s) const; + + bool operator>(const string & s) const; + bool operator>(const char * s) const; + bool operator>=(const string & s) const; + bool operator>=(const char * s) const; + + const char * tocstr(void) const; +}; + +#pragma compile("string.cpp") + +#endif diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 38b65d7..99b56f6 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -801,6 +801,15 @@ int Declaration::Stride(void) const return mStride > 0 ? mStride : mBase->mSize; } +Declaration* Declaration::BuildPointer(const Location& loc) +{ + Declaration* pdec = new Declaration(loc, DT_TYPE_POINTER); + pdec->mBase = this; + pdec->mFlags = DTF_DEFINED; + pdec->mSize = 2; + return pdec; +} + Declaration* Declaration::Last(void) { mPrev = nullptr; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 3667799..6c161db 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -262,6 +262,8 @@ public: Declaration* Clone(void); Declaration* Last(void); + Declaration* BuildPointer(const Location& loc); + int Stride(void) const; }; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 4f39d9f..5f08de3 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -48,6 +48,8 @@ void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec) pcdec->mNext = mdec; dec->mScope->Insert(mdec->mIdent, gdec); + if (dec->mConst) + dec->mConst->mScope->Insert(mdec->mIdent, gdec); } else mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); @@ -2993,7 +2995,10 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex Declaration * bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); bthis->mFlags |= DTF_CONST | DTF_DEFINED; - bthis->mBase = bdec; + if (ConsumeTokenIf(TK_CONST)) + bthis->mBase = bdec->ToConstType(); + else + bthis->mBase = bdec; bthis->mSize = 2; PrependThisArgument(ctdec, bthis); @@ -3127,10 +3132,11 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex else { if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) - { - - PrependThisArgument(ndec->mBase, pthis); - + { + if (ConsumeTokenIf(TK_CONST)) + PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildPointer(ndec->mLocation)); + else + PrependThisArgument(ndec->mBase, pthis); } if (variable) @@ -3180,6 +3186,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex Declaration* adec = pdec->mBase->mParams->Clone(); adec->mNext = ndec->mBase->mParams; + if (ConsumeTokenIf(TK_CONST)) + adec->mBase = adec->mBase->mBase->ToConstType()->BuildPointer(adec->mLocation); + Declaration* p = adec->mBase->mParams; while (p) { @@ -3230,6 +3239,8 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } } + pdec->mFlags |= ndec->mFlags & DTF_REQUEST_INLINE; + ndec = pdec; } } @@ -4603,6 +4614,8 @@ Expression* Parser::ParseShiftExpression(bool lhs) nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(mErrors); + + exp = CheckOperatorOverload(exp); } return exp; @@ -4622,6 +4635,8 @@ Expression* Parser::ParseRelationalExpression(bool lhs) nexp->mDecType = TheBoolTypeDeclaration; exp = nexp->ConstantFold(mErrors); + + exp = CheckOperatorOverload(exp); } return exp; @@ -4641,6 +4656,8 @@ Expression* Parser::ParseBinaryAndExpression(bool lhs) nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(mErrors); + + exp = CheckOperatorOverload(exp); } return exp; @@ -4659,6 +4676,8 @@ Expression* Parser::ParseBinaryXorExpression(bool lhs) nexp->mRight = ParseBinaryAndExpression(false); nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(mErrors); + + exp = CheckOperatorOverload(exp); } return exp; @@ -4677,6 +4696,8 @@ Expression* Parser::ParseBinaryOrExpression(bool lhs) nexp->mRight = ParseBinaryXorExpression(false); nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(mErrors); + + exp = CheckOperatorOverload(exp); } return exp; @@ -4772,9 +4793,47 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) Declaration* tdec = exp->mLeft->mDecType; if (tdec->mType == DT_TYPE_STRUCT) { - if (exp->mToken == TK_ASSIGN) + const Ident* opident = nullptr; + switch (exp->mToken) { - Declaration* mdec = tdec->mScope->Lookup(Ident::Unique("operator=")); + case TK_ASSIGN: + opident = Ident::Unique("operator="); + break; + case TK_ASSIGN_ADD: + opident = Ident::Unique("operator+="); + break; + case TK_ASSIGN_SUB: + opident = Ident::Unique("operator-="); + break; + case TK_ASSIGN_MUL: + opident = Ident::Unique("operator*="); + break; + case TK_ASSIGN_DIV: + opident = Ident::Unique("operator/="); + break; + case TK_ASSIGN_MOD: + opident = Ident::Unique("operator%="); + break; + case TK_ASSIGN_SHL: + opident = Ident::Unique("operator<<="); + break; + case TK_ASSIGN_SHR: + opident = Ident::Unique("operator>>="); + break; + case TK_ASSIGN_AND: + opident = Ident::Unique("operator&="); + break; + case TK_ASSIGN_XOR: + opident = Ident::Unique("operator^="); + break; + case TK_ASSIGN_OR: + opident = Ident::Unique("operator|="); + break; + } + + if (opident) + { + Declaration* mdec = tdec->mScope->Lookup(opident); if (mdec) { Expression * nexp = new Expression(mScanner->mLocation, EX_CALL); @@ -4807,7 +4866,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) } } } - else if (exp->mType == EX_BINARY) + else if (exp->mType == EX_BINARY || exp->mType == EX_RELATIONAL) { const Ident* opident = nullptr; switch (exp->mToken) @@ -4816,17 +4875,50 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) opident = Ident::Unique("operator+"); break; case TK_SUB: - opident = Ident::Unique("operator+"); + opident = Ident::Unique("operator-"); break; case TK_MUL: - opident = Ident::Unique("operator+"); + opident = Ident::Unique("operator*"); break; case TK_DIV: - opident = Ident::Unique("operator+"); + opident = Ident::Unique("operator/"); break; case TK_MOD: opident = Ident::Unique("operator%"); break; + case TK_BINARY_AND: + opident = Ident::Unique("operator&"); + break; + case TK_BINARY_OR: + opident = Ident::Unique("operator|"); + break; + case TK_BINARY_XOR: + opident = Ident::Unique("operator^"); + break; + case TK_LEFT_SHIFT: + opident = Ident::Unique("operator<<"); + break; + case TK_RIGHT_SHIFT: + opident = Ident::Unique("operator>>"); + break; + case TK_EQUAL: + opident = Ident::Unique("operator=="); + break; + case TK_NOT_EQUAL: + opident = Ident::Unique("operator!="); + break; + case TK_GREATER_THAN: + opident = Ident::Unique("operator>"); + break; + case TK_GREATER_EQUAL: + opident = Ident::Unique("operator>="); + break; + case TK_LESS_THAN: + opident = Ident::Unique("operator<"); + break; + case TK_LESS_EQUAL: + opident = Ident::Unique("operator<="); + break; } if (opident) @@ -4851,7 +4943,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mLeft = exp->mLeft; texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = exp->mDecType; + texp->mDecType->mBase = exp->mLeft->mDecType; texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 535e6f3..1a5e293 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1415,6 +1415,37 @@ void Scanner::NextRawToken(void) mTokenIdent = Ident::Unique("operator="); break; + case TK_ASSIGN_ADD: + mTokenIdent = Ident::Unique("operator+="); + break; + case TK_ASSIGN_SUB: + mTokenIdent = Ident::Unique("operator-="); + break; + case TK_ASSIGN_MUL: + mTokenIdent = Ident::Unique("operator*="); + break; + case TK_ASSIGN_DIV: + mTokenIdent = Ident::Unique("operator/="); + break; + case TK_ASSIGN_MOD: + mTokenIdent = Ident::Unique("operator%="); + break; + case TK_ASSIGN_SHL: + mTokenIdent = Ident::Unique("operator<<="); + break; + case TK_ASSIGN_SHR: + mTokenIdent = Ident::Unique("operator>>="); + break; + case TK_ASSIGN_AND: + mTokenIdent = Ident::Unique("operator&="); + break; + case TK_ASSIGN_XOR: + mTokenIdent = Ident::Unique("operator^="); + break; + case TK_ASSIGN_OR: + mTokenIdent = Ident::Unique("operator|="); + break; + case TK_ADD: mTokenIdent = Ident::Unique("operator+"); break; @@ -1431,6 +1462,42 @@ void Scanner::NextRawToken(void) mTokenIdent = Ident::Unique("operator%"); break; + case TK_BINARY_AND: + mTokenIdent = Ident::Unique("operator&"); + break; + case TK_BINARY_OR: + mTokenIdent = Ident::Unique("operator|"); + break; + case TK_BINARY_XOR: + mTokenIdent = Ident::Unique("operator^"); + break; + + case TK_LEFT_SHIFT: + mTokenIdent = Ident::Unique("operator<<"); + break; + case TK_RIGHT_SHIFT: + mTokenIdent = Ident::Unique("operator>>"); + break; + + case TK_EQUAL: + mTokenIdent = Ident::Unique("operator=="); + break; + case TK_NOT_EQUAL: + mTokenIdent = Ident::Unique("operator!="); + break; + case TK_GREATER_THAN: + mTokenIdent = Ident::Unique("operator>"); + break; + case TK_GREATER_EQUAL: + mTokenIdent = Ident::Unique("operator>="); + break; + case TK_LESS_THAN: + mTokenIdent = Ident::Unique("operator<"); + break; + case TK_LESS_EQUAL: + mTokenIdent = Ident::Unique("operator<="); + break; + default: mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "Invalid operator token"); } From c8fbc15c3717e4ad4d091add597befe319e4f05d Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 1 Jul 2023 09:27:03 +0200 Subject: [PATCH 016/169] Copy propagation on struct return of functionr result --- oscar64/InterCodeGenerator.cpp | 36 ++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 855932f..4de30c7 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1074,6 +1074,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper) { + if (vr.mTemp == vl.mTemp) + return; + if (vl.mType->mCopyConstructor) { Declaration* ccdec = vl.mType->mCopyConstructor; @@ -3179,10 +3182,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RETURN); if (exp->mLeft) { - vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - if (procType->mBase->mType == DT_TYPE_REFERENCE) { + vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vr = Dereference(proc, exp, block, vr, 1); vr = CoerceType(proc, exp, block, vr, procType->mBase); @@ -3229,14 +3232,6 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else if (procType->mBase->mType == DT_TYPE_STRUCT) { - vr = Dereference(proc, exp, block, vr, 1); - - if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID) - mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Function has void return type"); - else if (!procType->mBase->CanAssign(vr.mType)) - mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type"); - else if (vr.mReference != 1) - mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Non addressable object"); InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); @@ -3289,7 +3284,20 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mCode = IC_RETURN; } - CopyStruct(proc, exp, block, ExValue(procType->mBase, ains->mDst.mTemp), vr, inlineMapper); + ExValue rvr(procType->mBase, ains->mDst.mTemp, 1); + + vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper, &rvr); + + vr = Dereference(proc, exp, block, vr, 1); + + if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID) + mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Function has void return type"); + else if (!procType->mBase->CanAssign(vr.mType)) + mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type"); + else if (vr.mReference != 1) + mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Non addressable object"); + + CopyStruct(proc, exp, block, rvr, vr, inlineMapper); #if 0 if (procType->mBase->mCopyConstructor) { @@ -3388,6 +3396,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { + vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vr = Dereference(proc, exp, block, vr); if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID) @@ -4336,8 +4346,8 @@ 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)); -#if 0 - if (proc->mIdent && !strcmp(proc->mIdent->mString, "test_member")) +#if 1 + if (proc->mIdent && !strcmp(proc->mIdent->mString, "test")) exp->Dump(0); #endif #if 0 From 08adc7f1bd93d285ac670e1ac8333edfa903f83a Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 1 Jul 2023 10:06:08 +0200 Subject: [PATCH 017/169] Bump version number --- README.md | 4 +- oscar64/oscar64.cpp | 4 +- oscar64/oscar64.rc | 8 ++-- oscar64setup/oscar64setup.vdproj | 69 ++++++++++++++++++++++++++++++-- 4 files changed, 75 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b03eeb6..84f3064 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,9 @@ Supported Features: * reference types * member functions * constructors and destructors -* operator overloading (assignment) +* operator overloading (not complete yet) +* single inheritance of class and struct +* const member functions ## Installation and Usage diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 455f79a..18aa475 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.20.208"); + strcpy(strProductVersion, "1.21.209"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); @@ -491,7 +491,7 @@ int main2(int argc, const char** argv) } else { - printf("oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=target] [-tm=machine] [-e] [-n] [-g] [-O(0|1|2|3)] {-dSYMBOL[=value]} [-v] [-d64=diskname] {-f[z]=file.xxx} {source.c}\n"); + printf("oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=target] [-tm=machine] [-e] [-n] [-g] [-O(0|1|2|3)] [-pp] {-dSYMBOL[=value]} [-v] [-d64=diskname] {-f[z]=file.xxx} {source.c}\n"); return 0; } diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 80cd98b..abb5828 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,20,208,0 - PRODUCTVERSION 1,20,208,0 + FILEVERSION 1,21,209,0 + PRODUCTVERSION 1,21,209,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.20.208.0" + VALUE "FileVersion", "1.21.209.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.20.208.0" + VALUE "ProductVersion", "1.21.209.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index df8af4f..9350e86 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -94,6 +94,12 @@ } "Entry" { + "MsmKey" = "8:_12ACD00110E34BF9A3C06E00A16449D9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_12C998C755E643038CDF5D9F56983ECA" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -448,6 +454,12 @@ } "Entry" { + "MsmKey" = "8:_6EE9325B01F74FFF8146A6AD7FE71A31" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_7127D91089DA4162BB8DC8EAB0C107F0" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1471,6 +1483,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_12ACD00110E34BF9A3C06E00A16449D9" + { + "SourcePath" = "8:..\\include\\opp\\string.cpp" + "TargetName" = "8:string.cpp" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_12C998C755E643038CDF5D9F56983ECA" { "SourcePath" = "8:..\\include\\fixmath.h" @@ -2651,6 +2683,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6EE9325B01F74FFF8146A6AD7FE71A31" + { + "SourcePath" = "8:..\\include\\opp\\string.h" + "TargetName" = "8:string.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7127D91089DA4162BB8DC8EAB0C107F0" { "SourcePath" = "8:..\\include\\c64\\vic.c" @@ -5202,6 +5254,17 @@ { } } + "{9EF0B969-E518-4E46-987F-47570745A589}:_D76A1802AFD04C48A519C9F8700E53CC" + { + "Name" = "8:opp" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_36F6D5A5C23349D190D89E25E1F78C22" + "Folders" + { + } + } "{9EF0B969-E518-4E46-987F-47570745A589}:_E0C7A8689A4144D0842BCEDA85A07B5D" { "Name" = "8:gfx" @@ -5233,15 +5296,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{30CBD281-E43B-4539-A830-C8EA3D9ECEEC}" - "PackageCode" = "8:{B24DA444-F39A-4974-97A1-BF31AB02202C}" + "ProductCode" = "8:{30BEED33-B5ED-4443-B82C-B365168D7780}" + "PackageCode" = "8:{46BC17E9-3B6D-4E1E-A1E7-42B0AD7512D8}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.20.208" + "ProductVersion" = "8:1.21.209" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 7858c2135b1e772ff0e47c7680b6996832780cea Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 2 Jul 2023 12:00:53 +0200 Subject: [PATCH 018/169] Add malloc/free as intrinsic --- autotest/stdlibtest.c | 5 +- include/crt.c | 469 ++++++++++++++++++++++++++++++++ include/crt.h | 4 +- include/stdlib.c | 2 + include/stdlib.h | 4 + oscar64/ByteCodeGenerator.cpp | 66 ++++- oscar64/ByteCodeGenerator.h | 6 +- oscar64/Compiler.cpp | 3 + oscar64/Declaration.h | 2 +- oscar64/Disassembler.cpp | 7 + oscar64/InterCode.cpp | 84 +++++- oscar64/InterCode.h | 2 + oscar64/InterCodeGenerator.cpp | 60 ++++ oscar64/Linker.cpp | 4 +- oscar64/NativeCodeGenerator.cpp | 71 ++++- oscar64/NativeCodeGenerator.h | 3 + oscar64/Parser.cpp | 123 ++++++++- oscar64/Scanner.cpp | 6 + oscar64/Scanner.h | 2 + 19 files changed, 891 insertions(+), 32 deletions(-) diff --git a/autotest/stdlibtest.c b/autotest/stdlibtest.c index 2409c2b..84d3268 100644 --- a/autotest/stdlibtest.c +++ b/autotest/stdlibtest.c @@ -51,16 +51,15 @@ void heapcheck(void) for(i=0; iHeapStart + sta HeapNode + 1 + + // set size to size of heap + sec + lda #HeapEnd + sbc #>HeapStart + sta HeapStart + 3 + +hasHeap: + // remember address of pointer to this + // heap block, to correct if block is a + // perfect fit + + lda #HeapNode + sta accu + 3 + + // Now loop over free nodes, until we find a match +loop: + // next heap block + + ldy #0 + lda (accu + 2), y + sta accu + iny + lda (accu + 2), y + sta accu + 1 + + // exit if out of blocks + + beq done + // calculate remaining size of heap block + + ldy #2 + sec + lda (accu), y + sbc tmp + sta tmp + 2 + iny + lda (accu), y + sbc tmp + 1 + sta tmp + 3 + + // will fit + bcs avail + + // prev + lda accu + sta accu + 2 + lda accu + 1 + sta accu + 3 + jmp loop + +done: + // no more heap blocks + rts +avail: + // is it a perfect fit? + lda tmp + 2 + ora tmp + 3 + bne nofit + + // so adjust previous pointer to point to + // next heap block + ldy #0 + lda (accu), y + sta (accu + 2), y + iny + lda (accu), y + sta (accu + 2), y + jmp found + +nofit: + // adjust size of remaining heapblock + ldy #2 + lda tmp + 2 + sta (accu), y + iny + lda tmp + 3 + sta (accu), y + + // advance address to start of next heap block + + clc + lda accu + adc tmp + 2 + sta accu + lda accu + 1 + adc tmp + 3 + sta accu + 1 + +found: + // remember size of heap block for free without size + + ldy #0 + lda tmp + 4 + sta (accu), y + iny + lda tmp + 5 + sta (accu), y + + // advanve by two bytes to skip size + clc + lda accu + adc #2 + sta accu + bcc page + inc accu + 1 +page: + rts +} + +__asm inp_malloc +{ + sty tmpy + jsr malloc + ldy tmpy + jmp startup.exec +} + +#pragma bytecode(BC_MALLOC, inp_malloc) + +__asm free +{ + // check nullptr free + lda accu + ora accu + 1 + bne notnull + rts +notnull: + // two bytes back to fix size + sec + lda accu + sbc #2 + sta accu + bcs page + dec accu + 1 +page: + + // cache size and end of block + + clc + ldy #0 + lda (accu), y + adc #5 + and #$fc + sta tmp + iny + lda (accu), y + adc #0 + sta tmp + 1 + + clc + lda tmp + 0 + adc accu + sta accu + 2 + lda tmp + 1 + adc accu + 1 + sta accu + 3 + + // pointer to heap block, starting with + // dummy block + + lda #HeapNode + sta tmp + 3 + +loop: + // check if end of heap + + ldy #1 + lda (tmp + 2), y + beq noend + + // Check if behind this block + + cmp accu + 1 + bcc before + bne after + + dey + lda (tmp + 2), y + cmp accu + 0 + bcs after + +before: + ldy # 1 + lda (tmp + 2), y + tax + dey + lda (tmp + 2), y + sta tmp + 2 + stx tmp + 3 + jmp loop +after: + + // Merge with next block + + ldy #1 + lda accu + 3 + cmp (tmp + 2), y + bne noend + dey + lda accu + 2 + cmp (tmp + 2), y + bne noend + + // Pointer to next next block + ldy #0 + lda (accu + 2), y + sta (accu), y + iny + lda (accu + 2), y + sta (accu), y + + // Add size of next block to this + iny + clc + lda tmp + adc (accu + 2), y + sta tmp + iny + lda tmp + 1 + adc (accu + 2), y + sta tmp + 1 + + jmp start +noend: + // Link to next block + ldy #0 + lda (tmp + 2), y + sta (accu), y + iny + lda (tmp + 2), y + sta (accu), y + +start: + // Calculate end of free block + ldy #2 + clc + lda tmp + 2 + adc (tmp + 2), y + iny + tax + lda tmp + 3 + adc (tmp + 2), y + + // Matches start of new block + cmp accu + 1 + bne nostart + cpx accu + bne nostart + + // If so, increase the size and link + // to free block after + + ldy #0 + lda (accu), y + sta (tmp + 2), y + iny + lda (accu), y + sta (tmp + 2), y + + iny + clc + lda (tmp + 2), y + adc tmp + sta (tmp + 2), y + iny + lda (tmp + 2), y + adc tmp + 1 + sta (tmp + 2), y + + rts + +nostart: + // Link to new free block + + ldy #0 + lda accu + sta (tmp + 2), y + iny + lda accu + 1 + sta (tmp + 2), y + iny + + // Set size of free block + lda tmp + sta (accu), y + iny + lda tmp + 1 + sta (accu), y + rts +} + +__asm inp_free +{ + sty tmpy + jsr free + ldy tmpy + jmp startup.exec +} + +#pragma bytecode(BC_FREE, inp_free) + + +#pragma runtime(malloc, malloc) +#pragma runtime(free, free) + +#if 0 + +void * malloc(unsigned int size) +{ + size = (size + 7) & ~3; + if (!freeHeapInit) + { + freeHeap = (Heap *)&HeapStart; + freeHeap->next = nullptr; + freeHeap->size = (unsigned int)&HeapEnd - (unsigned int)&HeapStart; + freeHeapInit = true; + } + + Heap * pheap = nullptr, * heap = freeHeap; + while (heap) + { + if (size <= heap->size) + { + if (size == heap->size) + { + if (pheap) + pheap->next = heap->next; + else + freeHeap = heap->next; + } + else + { + Heap * nheap = (Heap *)((int)heap + size); + nheap->size = heap->size - size; + nheap->next = heap->next; + if (pheap) + pheap->next = nheap; + else + freeHeap = nheap; + heap->size = size; + } + + return (void *)((int)heap + 2); + } + pheap = heap; + heap = heap->next; + } + + return nullptr; +} + +void free(void * ptr) +{ + if (!ptr) + return; + + Heap * fheap = (Heap *)((int)ptr - 2); + Heap * eheap = (Heap *)((int)ptr - 2 + fheap->size); + + if (freeHeap) + { + if (eheap == freeHeap) + { + fheap->size += freeHeap->size; + fheap->next = freeHeap->next; + freeHeap = fheap; + } + else if (eheap < freeHeap) + { + fheap->next = freeHeap; + freeHeap = fheap; + } + else + { + Heap * pheap = freeHeap; + while (pheap->next && pheap->next < fheap) + pheap = pheap->next; + Heap * nheap = (Heap *)((int)pheap + pheap->size); + + if (nheap == fheap) + { + pheap->size += fheap->size; + if (pheap->next == eheap) + { + pheap->size += pheap->next->size; + pheap->next = pheap->next->next; + } + } + else if (pheap->next == eheap) + { + fheap->next = pheap->next->next; + fheap->size += pheap->next->size; + pheap->next = fheap; + } + else + { + fheap->next = pheap->next; + pheap->next = fheap; + } + } + } + else + { + freeHeap = fheap; + freeHeap->next = nullptr; + } +} +#endif diff --git a/include/crt.h b/include/crt.h index 5844f9c..2cc7fc0 100644 --- a/include/crt.h +++ b/include/crt.h @@ -142,8 +142,8 @@ enum ByteCode BC_BRANCHF_LE, BC_LOOP_U8, - BC_UNUSED_2, - BC_UNUSED_3, + BC_MALLOC, + BC_FREE, BC_UNUSED_4, BC_UNUSED_5, BC_UNUSED_6, diff --git a/include/stdlib.c b/include/stdlib.c index cfcbda6..a181c0a 100644 --- a/include/stdlib.c +++ b/include/stdlib.c @@ -524,6 +524,7 @@ void exit(int status) } } +#if 0 struct Heap { unsigned int size; Heap * next; @@ -636,6 +637,7 @@ void free(void * ptr) freeHeap->next = nullptr; } } +#endif void * calloc(int num, int size) { diff --git a/include/stdlib.h b/include/stdlib.h index 1761f40..7384454 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -47,6 +47,10 @@ unsigned int rand(void); void srand(unsigned int seed); +#pragma intrinsic(malloc) + +#pragma intrinsic(free) + #pragma compile("stdlib.c") #endif diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index 94181cc..cd17825 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -142,8 +142,8 @@ static const char* ByteCodeNames[] = { "BRANCHF_LE", "LOOP_U8", - nullptr, - nullptr, + "MALLOC", + "FREE", nullptr, nullptr, nullptr, @@ -565,6 +565,11 @@ bool ByteCodeInstruction::CheckAccuSize(uint32 & used) used = 0; break; + case BC_MALLOC: + case BC_FREE: + used = 0x0000ffff; + break; + case BC_BINOP_ADDA_16: used |= 0x0000ffff; break; @@ -779,6 +784,8 @@ bool ByteCodeInstruction::UsesRegister(uint32 reg) const return true; if (mCode == BC_BINOP_ADDA_16) return true; + if (mCode == BC_MALLOC || mCode == BC_FREE) + return true; } if (reg == BC_REG_ADDR) @@ -851,6 +858,8 @@ bool ByteCodeInstruction::ChangesRegister(uint32 reg) const return true; if (mCode == BC_LOOP_U8) return true; + if (mCode == BC_MALLOC || mCode == BC_FREE) + return true; } if (reg == BC_REG_ADDR) @@ -869,6 +878,8 @@ bool ByteCodeInstruction::ChangesRegister(uint32 reg) const { if (mCode == BC_JSR || mCode == BC_CALL_ADDR || mCode == BC_CALL_ABS) return true; + if (mCode == BC_MALLOC || mCode == BC_FREE) + return true; if (mCode == BC_BINOP_DIVR_I16 || mCode == BC_BINOP_DIVR_U16 || mCode == BC_BINOP_MODR_I16 || mCode == BC_BINOP_MODR_U16 || mCode == BC_BINOP_DIV_I32 || mCode == BC_BINOP_DIV_U32 || mCode == BC_BINOP_MOD_I32 || mCode == BC_BINOP_MOD_U32 || @@ -1149,6 +1160,8 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl assert(false); break; + case BC_MALLOC: + case BC_FREE: case BC_CALL_ADDR: block->PutCode(generator, mCode); break; @@ -1578,6 +1591,49 @@ void ByteCodeBasicBlock::StrcpyValue(InterCodeProcedure* proc, const InterInstru mIns.Push(cins); } +void ByteCodeBasicBlock::CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins) +{ + if (ins->mSrc[0].mTemp < 0) + { + ByteCodeInstruction dins(BC_CONST_16); + dins.mRegister = BC_REG_ACCU; + dins.mValue = int(ins->mSrc[0].mIntConst & 0xffff); + mIns.Push(dins); + } + else + { + ByteCodeInstruction dins(BC_LOAD_REG_16); + dins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; + dins.mRegisterFinal = ins->mSrc[0].mFinal; + mIns.Push(dins); + } + ByteCodeInstruction cins(BC_MALLOC); + mIns.Push(cins); + ByteCodeInstruction bins(BC_STORE_REG_16); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]; + mIns.Push(bins); +} + +void ByteCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins) +{ + if (ins->mSrc[0].mTemp < 0) + { + ByteCodeInstruction dins(BC_CONST_16); + dins.mRegister = BC_REG_ACCU; + dins.mValue = int(ins->mSrc[0].mIntConst & 0xffff); + mIns.Push(dins); + } + else + { + ByteCodeInstruction dins(BC_LOAD_REG_16); + dins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; + dins.mRegisterFinal = ins->mSrc[0].mFinal; + mIns.Push(dins); + } + ByteCodeInstruction cins(BC_FREE); + mIns.Push(cins); +} + void ByteCodeBasicBlock::StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins) { if (ins->mSrc[0].mType == IT_FLOAT) @@ -4259,6 +4315,12 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p case IC_STRCPY: StrcpyValue(iproc, ins); break; + case IC_MALLOC: + CallMalloc(iproc, ins); + break; + case IC_FREE: + CallFree(iproc, ins); + break; case IC_LOAD_TEMPORARY: { if (ins->mSrc[0].mTemp != ins->mDst.mTemp) diff --git a/oscar64/ByteCodeGenerator.h b/oscar64/ByteCodeGenerator.h index 19871bc..fac6acb 100644 --- a/oscar64/ByteCodeGenerator.h +++ b/oscar64/ByteCodeGenerator.h @@ -143,8 +143,8 @@ enum ByteCode BC_BRANCHF_LE, BC_LOOP_U8, - BC_UNUSED_2, - BC_UNUSED_3, + BC_MALLOC, + BC_FREE, BC_UNUSED_4, BC_UNUSED_5, BC_UNUSED_6, @@ -283,6 +283,8 @@ public: void FloatConstToWork(double val); void CopyValue(InterCodeProcedure* proc, const InterInstruction * ins); void StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins); + void CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins); + void CallFree(InterCodeProcedure* proc, const InterInstruction* ins); void LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins); void StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins); void LoadDirectValue(InterCodeProcedure* proc, const InterInstruction * ins); diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index c34aa31..7215372 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -669,6 +669,9 @@ bool Compiler::GenerateCode(void) RegisterRuntime(loc, Ident::Unique("mods32")); RegisterRuntime(loc, Ident::Unique("divu32")); RegisterRuntime(loc, Ident::Unique("modu32")); + + RegisterRuntime(loc, Ident::Unique("malloc")); + RegisterRuntime(loc, Ident::Unique("free")); } // Register extended byte code functions diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 6c161db..fab88ce 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -187,7 +187,7 @@ enum ExpressionType EX_ASSUME, EX_BANKOF, EX_CONSTRUCT, - EX_CLEANUP, + EX_CLEANUP }; class Expression diff --git a/oscar64/Disassembler.cpp b/oscar64/Disassembler.cpp index 042ce48..7f76623 100644 --- a/oscar64/Disassembler.cpp +++ b/oscar64/Disassembler.cpp @@ -476,6 +476,13 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank fprintf(file, "CNVFS\tACCU"); break; + case BC_MALLOC: + fprintf(file, "MALLOC\tACCU"); + break; + case BC_FREE: + fprintf(file, "FREE\tACCU"); + break; + case BC_JUMPS: fprintf(file, "JUMP\t$%04X", start + i + 1 + int8(memory[start + i + 0])); i++; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 6e4723b..2e22823 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -634,7 +634,7 @@ bool InterCodeBasicBlock::CanSwapInstructions(const InterInstruction* ins0, cons { if (ins0->mCode == IC_CALL || ins0->mCode == IC_CALL_NATIVE || ins0->mCode == IC_ASSEMBLER || ins0->mCode == IC_RETURN || ins0->mCode == IC_RETURN_STRUCT || ins0->mCode == IC_RETURN_VALUE || - ins0->mCode == IC_PUSH_FRAME || ins0->mCode == IC_POP_FRAME) + ins0->mCode == IC_PUSH_FRAME || ins0->mCode == IC_POP_FRAME || ins0->mCode == IC_MALLOC || ins0->mCode == IC_FREE) return false; if (ins0->mCode == IC_LOAD || ins0->mCode == IC_STORE || ins0->mCode == IC_COPY || ins0->mCode == IC_STRCPY) @@ -643,13 +643,30 @@ bool InterCodeBasicBlock::CanSwapInstructions(const InterInstruction* ins0, cons if (ins0->mCode == IC_CALL || ins0->mCode == IC_CALL_NATIVE || ins0->mCode == IC_ASSEMBLER) { if (ins1->mCode == IC_RETURN || ins1->mCode == IC_RETURN_STRUCT || ins1->mCode == IC_RETURN_VALUE || - ins1->mCode == IC_PUSH_FRAME || ins1->mCode == IC_POP_FRAME) + ins1->mCode == IC_PUSH_FRAME || ins1->mCode == IC_POP_FRAME || ins1->mCode == IC_MALLOC || ins1->mCode == IC_FREE) return false; if (ins1->mCode == IC_LOAD || ins1->mCode == IC_STORE || ins1->mCode == IC_COPY || ins1->mCode == IC_STRCPY) return false; } + if (ins0->mCode == IC_MALLOC || ins0->mCode == IC_FREE) + { + if (ins1->mCode == IC_MALLOC || ins1->mCode == IC_FREE) + return false; + } + + if (ins0->mCode == IC_FREE) + { + if (ins1->mCode == IC_LOAD || ins1->mCode == IC_STORE || ins1->mCode == IC_COPY || ins1->mCode == IC_STRCPY) + return false; + } + if (ins1->mCode == IC_FREE) + { + if (ins0->mCode == IC_LOAD || ins0->mCode == IC_STORE || ins0->mCode == IC_COPY || ins0->mCode == IC_STRCPY) + return false; + } + // Check frame pointer if (ins0->mCode == IC_PUSH_FRAME || ins0->mCode == IC_POP_FRAME) { @@ -1151,17 +1168,17 @@ void ValueSet::InsertValue(InterInstruction * ins) static bool HasSideEffect(InterCode code) { - return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER; + return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_MALLOC || code == IC_FREE; } static bool IsObservable(InterCode code) { - return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_STORE || code == IC_COPY || code == IC_STRCPY; + return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_STORE || code == IC_COPY || code == IC_STRCPY || code == IC_MALLOC || code == IC_FREE; } static bool IsMoveable(InterCode code) { - if (HasSideEffect(code) || code == IC_COPY || code == IC_STRCPY || code == IC_STORE || code == IC_BRANCH || code == IC_POP_FRAME || code == IC_PUSH_FRAME) + if (HasSideEffect(code) || code == IC_COPY || code == IC_STRCPY || code == IC_STORE || code == IC_BRANCH || code == IC_POP_FRAME || code == IC_PUSH_FRAME || code == IC_MALLOC || code == IC_FREE) return false; if (code == IC_RETURN || code == IC_RETURN_STRUCT || code == IC_RETURN_VALUE) return false; @@ -2762,12 +2779,43 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr case IC_BRANCH: if (ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT) { - if (tvalue[ins->mSrc[0].mTemp]->mConst.mIntConst) - ins->mCode = IC_JUMP; - else - ins->mCode = IC_JUMPF; - ins->mSrc[0].mTemp = -1; - ins->mNumOperands = 0; + InterInstruction* tins = tvalue[ins->mSrc[0].mTemp]; + if (IsIntegerType(tins->mConst.mType) || tins->mConst.mType == IT_BOOL) + { + if (tins->mConst.mIntConst) + ins->mCode = IC_JUMP; + else + ins->mCode = IC_JUMPF; + ins->mSrc[0].mTemp = -1; + ins->mNumOperands = 0; + } + else if (tins->mConst.mType == IT_POINTER) + { + if (tins->mConst.mMemory == IM_ABSOLUTE) + { + if (tins->mConst.mIntConst) + ins->mCode = IC_JUMP; + else + ins->mCode = IC_JUMPF; + ins->mSrc[0].mTemp = -1; + ins->mNumOperands = 0; + } + else if (tins->mConst.mMemory == IM_GLOBAL || tins->mConst.mMemory == IM_LOCAL || tins->mConst.mMemory == IM_PARAM || tins->mConst.mMemory == IM_FPARAM) + { + ins->mCode = IC_JUMP; + ins->mSrc[0].mTemp = -1; + ins->mNumOperands = 0; + } + } + else if (tins->mConst.mType == IT_FLOAT) + { + if (tins->mConst.mFloatConst) + ins->mCode = IC_JUMP; + else + ins->mCode = IC_JUMPF; + ins->mSrc[0].mTemp = -1; + ins->mNumOperands = 0; + } } break; case IC_PUSH_FRAME: @@ -4214,6 +4262,16 @@ void InterInstruction::Disassemble(FILE* file) else fprintf(file, "COPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]); break; + + case IC_MALLOC: + assert(mNumOperands == 1); + fprintf(file, "MALLOC"); + break; + case IC_FREE: + assert(mNumOperands == 1); + fprintf(file, "FREE"); + break; + case IC_STRCPY: fprintf(file, "STRCPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]); break; @@ -7696,7 +7754,7 @@ bool InterCodeBasicBlock::CalculateSingleAssignmentTemps(FastNumberSet& tassigne bool valid = j == ins->mNumOperands; if (valid) { - if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE || ins->mCode == IC_ASSEMBLER) + if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE || ins->mCode == IC_ASSEMBLER || ins->mCode == IC_MALLOC || ins->mCode == IC_FREE) valid = false; else if (ins->mCode == IC_LOAD) { @@ -16035,7 +16093,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "test"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 0c7f5fd..8d45c16 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -24,6 +24,8 @@ enum InterCode IC_LEA, IC_COPY, IC_STRCPY, + IC_MALLOC, + IC_FREE, IC_TYPECAST, IC_CONSTANT, IC_BRANCH, diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 4de30c7..6f34fd8 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -2429,6 +2429,30 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } mErrors->Error(exp->mLocation, ERRR_CANNOT_FIND_BANK_OF_EXPRESSION, "Cannot find bank of expressiohn"); } break; + + case TK_NEW: + { + ins->mCode = IC_MALLOC; + ins->mSrc[0].mType = InterTypeOf(vl.mType); + ins->mSrc[0].mTemp = vl.mTemp; + ins->mDst.mType = IT_POINTER; + ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + block->Append(ins); + return ExValue(exp->mDecType, ins->mDst.mTemp, 0); + + } break; + + case TK_DELETE: + { + vl = Dereference(proc, exp, block, vl, 0); + + ins->mCode = IC_FREE; + ins->mSrc[0].mType = IT_POINTER; + ins->mSrc[0].mTemp = vl.mTemp; + block->Append(ins); + return ExValue(TheConstVoidTypeDeclaration, -1); + + } break; } ins->mSrc[0].mType = InterTypeOf(vl.mType); @@ -2611,6 +2635,42 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* return ExValue(TheFloatTypeDeclaration, ins->mDst.mTemp); } + else if (!strcmp(iname->mString, "malloc")) + { + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); + vr = Dereference(proc, exp, block, vr); + + if (decf->mBase->mParams->CanAssign(vr.mType)) + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + vr = CoerceType(proc, exp, block, vr, decf->mBase->mParams); + + InterInstruction* ins = new InterInstruction(exp->mLocation, IC_MALLOC); + ins->mSrc[0].mType = IT_INT16; + ins->mSrc[0].mTemp = vr.mTemp; + ins->mNumOperands = 1; + ins->mDst.mType = IT_POINTER; + ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + block->Append(ins); + + return ExValue(TheVoidPointerTypeDeclaration, ins->mDst.mTemp); + } + else if (!strcmp(iname->mString, "free")) + { + vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); + vr = Dereference(proc, exp, block, vr); + + if (decf->mBase->mParams->CanAssign(vr.mType)) + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + vr = CoerceType(proc, exp, block, vr, decf->mBase->mParams); + + InterInstruction* ins = new InterInstruction(exp->mLocation, IC_FREE); + ins->mSrc[0].mType = IT_POINTER; + ins->mSrc[0].mTemp = vr.mTemp; + ins->mNumOperands = 1; + block->Append(ins); + + return ExValue(TheVoidTypeDeclaration, 0); + } else if (!strcmp(iname->mString, "strcpy")) { if (exp->mRight->mType == EX_LIST) diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index fdf3317..c2a23cf 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -489,8 +489,8 @@ void Linker::Link(void) if (lsec->mType == LST_HEAP) { - lsec->mStart = lrgn->mStart + lrgn->mUsed; - lsec->mEnd = lrgn->mEnd; + lsec->mStart = (lrgn->mStart + lrgn->mUsed + 3) & ~3; + lsec->mEnd = lrgn->mEnd & ~3; if (lsec->mStart + lsec->mSize > lsec->mEnd) { diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 166976a..1550a92 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -7346,6 +7346,54 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, } } +void NativeCodeBasicBlock::CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc) +{ + if (ins->mSrc[0].mTemp < 0) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + } + + NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("malloc"))); + mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER)); + + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); +} + +void NativeCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc) +{ + if (ins->mSrc[0].mTemp < 0) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, ins->mSrc[0].mIntConst & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + } + + NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("free"))); + mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER)); +} + + NativeCodeBasicBlock* NativeCodeBasicBlock::StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc) { int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp], dreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; @@ -17338,10 +17386,13 @@ bool NativeCodeBasicBlock::CombineZPPair(int at, int r0, int r1, bool use0, bool } } } - else if (ins.ChangesZeroPage(r0)) - valid0 = false; - else if (ins.ChangesZeroPage(r1)) - valid1 = false; + else + { + if (ins.ChangesZeroPage(r0)) + valid0 = false; + if (ins.ChangesZeroPage(r1)) + valid1 = false; + } i++; } @@ -40093,7 +40144,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "strlen"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "heapcheck"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -40881,7 +40932,7 @@ void NativeCodeProcedure::Optimize(void) } #endif - if (step == 5) + if (step == 5 && cnt < 10) { ResetVisited(); if (mEntryBlock->RemoveDoubleZPStore()) @@ -41703,6 +41754,14 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode case IC_STRCPY: block = block->StrcpyValue(iproc, ins, this); break; + + case IC_MALLOC: + block->CallMalloc(iproc, ins, this); + break; + case IC_FREE: + block->CallFree(iproc, ins, this); + break; + case IC_LOAD_TEMPORARY: { if (ins->mSrc[0].mTemp != ins->mDst.mTemp) diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 97e44bb..3cf5e56 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -336,6 +336,9 @@ public: NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc); void AddAsrSignedByte(InterCodeProcedure* proc, const InterInstruction* ains, const InterInstruction* sins); + void CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc); + void CallFree(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc); + void LoadByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins); void StoreByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 5f08de3..9fcdab6 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -4470,7 +4470,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) { if (mScanner->mToken == TK_SUB || mScanner->mToken == TK_BINARY_NOT || mScanner->mToken == TK_LOGICAL_NOT || mScanner->mToken == TK_MUL || mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC || mScanner->mToken == TK_BINARY_AND || - mScanner->mToken == TK_BANKOF) + mScanner->mToken == TK_BANKOF || mScanner->mToken == TK_NEW || mScanner->mToken == TK_DELETE) { Expression* nexp; if (mScanner->mToken == TK_LOGICAL_NOT) @@ -4487,6 +4487,127 @@ Expression* Parser::ParsePrefixExpression(bool lhs) nexp->mLeft = ParsePrefixExpression(false);; nexp->mDecType = nexp->mLeft->mDecType; } + else if (mScanner->mToken == TK_NEW) + { + nexp = new Expression(mScanner->mLocation, EX_PREFIX); + nexp->mToken = TK_NEW; + mScanner->NextToken(); + Declaration * dec = ParseBaseTypeDeclaration(0); + + Declaration* sconst = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + sconst->mBase = TheUnsignedIntTypeDeclaration; + sconst->mInteger = dec->mSize; + + Expression* sexp = new Expression(mScanner->mLocation, EX_CONSTANT); + sexp->mDecValue = sconst; + sexp->mDecType = TheUnsignedIntTypeDeclaration; + + nexp->mLeft = sexp; + nexp->mDecType = dec->BuildPointer(mScanner->mLocation); + + if (mScanner->mToken == TK_OPEN_PARENTHESIS || dec->mDefaultConstructor) + { + Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + vdec->mVarIndex = mLocalIndex++; + vdec->mBase = nexp->mDecType; + vdec->mSize = 2; + + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = vdec->mBase; + vexp->mDecValue = vdec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + iexp->mToken = TK_ASSIGN; + iexp->mLeft = vexp; + iexp->mRight = nexp; + iexp->mDecType = nexp->mDecType; + + Declaration* mdec = dec->mDefaultConstructor; + Expression* pexp = iexp; + + if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) + { + if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) + { + pexp = ParseListExpression(); + + mdec = dec->mScope->Lookup(dec->mIdent); + + ConsumeToken(TK_CLOSE_PARENTHESIS); + + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = iexp; + lexp->mRight = pexp; + pexp = lexp; + } + } + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + + ResolveOverloadCall(cexp, pexp); + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = vexp; + + nexp = sexp; + } + } + else if (mScanner->mToken == TK_DELETE) + { + nexp = new Expression(mScanner->mLocation, EX_PREFIX); + nexp->mToken = TK_DELETE; + mScanner->NextToken(); + nexp->mLeft = ParsePrefixExpression(false); + nexp->mDecType = TheVoidTypeDeclaration; + if (nexp->mLeft->mDecType->mType == DT_TYPE_POINTER) + { + Declaration* dec = nexp->mLeft->mDecType->mBase; + if (dec->mDestructor) + { + Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + vdec->mVarIndex = mLocalIndex++; + vdec->mBase = nexp->mLeft->mDecType; + vdec->mSize = 2; + + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = vdec->mBase; + vexp->mDecValue = vdec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + iexp->mToken = TK_ASSIGN; + iexp->mLeft = vexp; + iexp->mRight = nexp->mLeft; + iexp->mDecType = nexp->mLeft->mDecType; + + Declaration* mdec = dec->mDestructor; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = iexp; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = nexp; + + nexp->mLeft = iexp; + + nexp = sexp; + } + } + } else { nexp = new Expression(mScanner->mLocation, EX_PREFIX); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 1a5e293..c68fcba 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -158,6 +158,8 @@ const char* TokenNames[] = "'public'", "'protected'", "'private'", + "'new'", + "'delete'", }; @@ -1406,6 +1408,10 @@ void Scanner::NextRawToken(void) mToken = TK_PROTECTED; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "private")) mToken = TK_PRIVATE; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "new")) + mToken = TK_NEW; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "delete")) + mToken = TK_DELETE; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index a7474a3..580c5ee 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -157,6 +157,8 @@ enum Token TK_PUBLIC, TK_PROTECTED, TK_PRIVATE, + TK_NEW, + TK_DELETE, NUM_TOKENS }; From 291ff890e614da35e7037cb4c12dbad61eff8a23 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 2 Jul 2023 13:36:02 +0200 Subject: [PATCH 019/169] Change heap layout for vector delete --- include/crt.c | 282 +++++++++++++++----------------- oscar64/ByteCodeGenerator.cpp | 10 +- oscar64/NativeCodeGenerator.cpp | 11 +- 3 files changed, 146 insertions(+), 157 deletions(-) diff --git a/include/crt.c b/include/crt.c index 12f060d..6a4b56a 100644 --- a/include/crt.c +++ b/include/crt.c @@ -4118,26 +4118,21 @@ void HeapStart, HeapEnd; bool HeapInit; struct Heap { - Heap * next; - unsigned size; + Heap * next, * end; } HeapNode; #pragma section(heap, 0x0000, HeapStart, HeapEnd) __asm malloc { - // round size to be a multiple of four - // and make room for two additional bytes - // to store size of memory node + // make room for two additional bytes + // to store pointer to end of used memory clc lda accu + 0 - sta tmp + 4 - adc #$05 - and #$fc + adc #2 sta tmp lda accu + 1 - sta tmp + 5 adc #$00 sta tmp + 1 @@ -4166,13 +4161,10 @@ __asm malloc lda #>HeapStart sta HeapNode + 1 - // set size to size of heap - sec + // set end of memory block to end of heap lda #HeapEnd - sbc #>HeapStart sta HeapStart + 3 hasHeap: @@ -4181,57 +4173,79 @@ hasHeap: // perfect fit lda #HeapNode - sta accu + 3 + ldx #>HeapNode // Now loop over free nodes, until we find a match loop: + sta accu + 2 + stx accu + 3 + // next heap block + // calculate potential end of block + + clc ldy #0 lda (accu + 2), y - sta accu + sta accu + 0 + adc tmp + sta tmp + 2 iny lda (accu + 2), y sta accu + 1 // exit if out of blocks - - beq done - // calculate remaining size of heap block - - ldy #2 - sec - lda (accu), y - sbc tmp - sta tmp + 2 - iny - lda (accu), y - sbc tmp + 1 + beq done + adc tmp + 1 sta tmp + 3 - // will fit + + // Check if in range of current free block + + ldy #2 + lda (accu), y + cmp tmp + 2 + iny + lda (accu), y + sbc tmp + 3 bcs avail - // prev + // move current block pointer to prev pointer + lda accu - sta accu + 2 - lda accu + 1 - sta accu + 3 + ldx accu + 1 jmp loop -done: +done: // no more heap blocks rts + avail: - // is it a perfect fit? + // calculate new end of block + + clc lda tmp + 2 - ora tmp + 3 + adc #3 + and #$fc + sta tmp + 4 + lda tmp + 3 + adc #0 + sta tmp + 5 + + // compare with end of free block + + ldy #2 + lda tmp + 4 + cmp (accu), y + bne nofit + iny + lda tmp + 5 + cmp (accu), y bne nofit - // so adjust previous pointer to point to - // next heap block + // perfect fit, so have previous block point to + // next free block + ldy #0 lda (accu), y sta (accu + 2), y @@ -4241,42 +4255,42 @@ avail: jmp found nofit: - // adjust size of remaining heapblock - ldy #2 + // set next link in new link block + + ldy #0 + lda (accu), y + sta (tmp + 4), y + lda tmp + 4 + sta (accu + 2), y + iny + lda (accu), y + sta (tmp + 4), y + lda tmp + 5 + sta (accu + 2), y + + // set new end of remaining block + iny + lda (accu), y + sta (tmp + 4), y + iny + lda (accu), y + sta (tmp + 4), y + +found: + // remember end of allocated block + + ldy #0 lda tmp + 2 sta (accu), y iny lda tmp + 3 sta (accu), y - // advance address to start of next heap block - - clc - lda accu - adc tmp + 2 - sta accu - lda accu + 1 - adc tmp + 3 - sta accu + 1 - -found: - // remember size of heap block for free without size - - ldy #0 - lda tmp + 4 - sta (accu), y - iny - lda tmp + 5 - sta (accu), y - // advanve by two bytes to skip size - clc lda accu - adc #2 + ora #2 sta accu - bcc page - inc accu + 1 -page: + rts } @@ -4292,91 +4306,68 @@ __asm inp_malloc __asm free { - // check nullptr free + + // two bytes back to fix remembered end of block + lda accu + and #$fc + sta accu + + // check nullptr free + ora accu + 1 bne notnull rts notnull: - // two bytes back to fix size - sec - lda accu - sbc #2 - sta accu - bcs page - dec accu + 1 -page: - // cache size and end of block + // cache end of block, rounding to next four byte + // address clc ldy #0 lda (accu), y - adc #5 + adc #3 and #$fc - sta tmp + sta accu + 2 iny lda (accu), y adc #0 - sta tmp + 1 - - clc - lda tmp + 0 - adc accu - sta accu + 2 - lda tmp + 1 - adc accu + 1 sta accu + 3 // pointer to heap block, starting with // dummy block lda #HeapNode - sta tmp + 3 + ldx #>HeapNode loop: + sta tmp + 2 + stx tmp + 3 + // check if end of heap ldy #1 lda (tmp + 2), y beq noend - - // Check if behind this block - - cmp accu + 1 - bcc before - bne after - - dey - lda (tmp + 2), y - cmp accu + 0 - bcs after - -before: - ldy # 1 - lda (tmp + 2), y tax dey lda (tmp + 2), y - sta tmp + 2 - stx tmp + 3 - jmp loop -after: - // Merge with next block + // Check if next block is behind the block to free - ldy #1 - lda accu + 3 - cmp (tmp + 2), y + cpx accu + 3 + bcc loop bne noend - dey - lda accu + 2 - cmp (tmp + 2), y + + cmp accu + 2 + bcc loop bne noend + // The end of the block to free matches the + // start of the next free block + // Pointer to next next block + ldy #0 lda (accu + 2), y sta (accu), y @@ -4384,18 +4375,16 @@ after: lda (accu + 2), y sta (accu), y - // Add size of next block to this - iny - clc - lda tmp - adc (accu + 2), y - sta tmp - iny - lda tmp + 1 - adc (accu + 2), y - sta tmp + 1 + // Append free space to new block + iny + lda (accu + 2), y + sta (accu), y + iny + lda (accu + 2), y + sta (accu), y jmp start + noend: // Link to next block ldy #0 @@ -4405,24 +4394,27 @@ noend: lda (tmp + 2), y sta (accu), y -start: - // Calculate end of free block - ldy #2 - clc - lda tmp + 2 - adc (tmp + 2), y + // End of new free block iny - tax - lda tmp + 3 - adc (tmp + 2), y + lda accu + 2 + sta (accu), y + iny + lda accu + 3 + sta (accu), y - // Matches start of new block +start: + // Check if new block matches end of previous block + + ldy #2 + lda (tmp + 2), y + cmp accu + bne nostart + iny + lda (tmp + 2), y cmp accu + 1 bne nostart - cpx accu - bne nostart - // If so, increase the size and link + // If so, increase the size of previous block and link // to free block after ldy #0 @@ -4433,13 +4425,10 @@ start: sta (tmp + 2), y iny - clc - lda (tmp + 2), y - adc tmp + lda (accu), y sta (tmp + 2), y iny - lda (tmp + 2), y - adc tmp + 1 + lda (accu), y sta (tmp + 2), y rts @@ -4453,14 +4442,7 @@ nostart: iny lda accu + 1 sta (tmp + 2), y - iny - // Set size of free block - lda tmp - sta (accu), y - iny - lda tmp + 1 - sta (accu), y rts } diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index cd17825..a966e7b 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -1609,9 +1609,13 @@ void ByteCodeBasicBlock::CallMalloc(InterCodeProcedure* proc, const InterInstruc } ByteCodeInstruction cins(BC_MALLOC); mIns.Push(cins); - ByteCodeInstruction bins(BC_STORE_REG_16); - bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]; - mIns.Push(bins); + + if (ins->mDst.mTemp >= 0) + { + ByteCodeInstruction bins(BC_STORE_REG_16); + bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]; + mIns.Push(bins); + } } void ByteCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 1550a92..de13f29 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -7366,10 +7366,13 @@ void NativeCodeBasicBlock::CallMalloc(InterCodeProcedure* proc, const InterInstr NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("malloc"))); mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); + if (ins->mDst.mTemp >= 0) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); + } } void NativeCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc) From 7f6cf654f647f2f58e18a1035322b609f9ba742a Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 2 Jul 2023 16:34:17 +0200 Subject: [PATCH 020/169] Implemented new and delete operators --- autotest/arrayconstruct.cpp | 5 +- autotest/testint32.c | 2 - include/crt.c | 9 +- oscar64/InterCode.cpp | 11 +- oscar64/InterCodeGenerator.cpp | 4 +- oscar64/Parser.cpp | 318 ++++++++++++++++++++++++--------- 6 files changed, 251 insertions(+), 98 deletions(-) diff --git a/autotest/arrayconstruct.cpp b/autotest/arrayconstruct.cpp index 845a9bb..171f109 100644 --- a/autotest/arrayconstruct.cpp +++ b/autotest/arrayconstruct.cpp @@ -136,16 +136,19 @@ void test_member_assign(void) int main(void) { +#if 0 test_local_init(); test_member_init(); +#endif test_member_array_init(); +#if 0 test_local_copy(); test_member_copy(); test_local_assign(); test_member_assign(); - +#endif return 0; } diff --git a/autotest/testint32.c b/autotest/testint32.c index fd188d8..b82fa8c 100644 --- a/autotest/testint32.c +++ b/autotest/testint32.c @@ -54,7 +54,6 @@ long sieve(long size) int main(void) { - testmuli(0, 0, 0); testmuli(1, 0, 0); testmuli(0, 1, 0); @@ -111,7 +110,6 @@ int main(void) assert(sieve(200) == 47); assert(sieve(1000) == 169); - long a = 0, b = 0; for(long i=0; i<10000; i++) { diff --git a/include/crt.c b/include/crt.c index 6a4b56a..26cf053 100644 --- a/include/crt.c +++ b/include/crt.c @@ -4115,7 +4115,6 @@ cmpne: void HeapStart, HeapEnd; -bool HeapInit; struct Heap { Heap * next, * end; @@ -4138,22 +4137,18 @@ __asm malloc // check if heap is initialized - lda HeapInit + lda HeapNode + 2 bne hasHeap // initialize heap - lda #$ff - sta HeapInit - // set next pointer to null lda #0 sta HeapStart + 0 sta HeapStart + 1 // set size of dummy node to null - sta HeapNode + 2 - sta HeapNode + 3 + inc HeapNode + 2 // set next pointer of dummy node to first free heap block lda #mConst; - mSrc[i].mType = t; - changed = true; + + if (t != IT_POINTER || ains->mConst.mMemory == IM_ABSOLUTE) + { + mSrc[i] = ains->mConst; + mSrc[i].mType = t; + changed = true; + } } } @@ -14167,6 +14171,7 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray { mInstructions[i + 1]->mSrc[0].mTemp = mInstructions[i + 0]->mSrc[1].mTemp; mInstructions[i + 1]->mSrc[0].mIntConst += mInstructions[i + 0]->mSrc[0].mIntConst; + mInstructions[i + 1]->mSrc[0].mFinal = mInstructions[i + 0]->mSrc[1].mFinal; mInstructions[i + 0]->mCode = IC_NONE; mInstructions[i + 0]->mNumOperands = 0; changed = true; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 6f34fd8..314b047 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -4406,8 +4406,8 @@ 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)); -#if 1 - if (proc->mIdent && !strcmp(proc->mIdent->mString, "test")) +#if 0 + 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 9fcdab6..1ab296b 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1388,9 +1388,13 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) dexp->mLeft = cexp; dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); dexp->mRight->mLeft = qexp; - dexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); - dexp->mRight->mRight->mDecType = ncdec->mBase; - dexp->mRight->mRight->mDecValue = ncdec; + dexp->mRight->mRight = new Expression(mScanner->mLocation, EX_BINARY); + dexp->mRight->mRight->mToken = TK_ADD; + dexp->mRight->mRight->mLeft = qexp; + dexp->mRight->mRight->mDecType = qexp->mDecType; + dexp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + dexp->mRight->mRight->mRight->mDecType = ncdec->mBase; + dexp->mRight->mRight->mRight->mDecValue = ncdec; } Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); @@ -1993,17 +1997,18 @@ void Parser::AddDefaultConstructors(Declaration* pthis) ctdec->mBase = TheVoidTypeDeclaration; ctdec->mFlags |= DTF_DEFINED; + Declaration* vthis = pthis->Clone(); + vthis->mFlags &= ~DTF_CONST; + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); adec->mVarIndex = 0; adec->mOffset = 0; - adec->mBase = TheUnsignedIntTypeDeclaration; + adec->mBase = pthis; adec->mSize = adec->mBase->mSize; - adec->mIdent = adec->mQualIdent = Ident::Unique("n"); + adec->mIdent = adec->mQualIdent = Ident::Unique("end"); ctdec->mParams = adec; - Declaration* vthis = pthis->Clone(); - vthis->mFlags &= ~DTF_CONST; PrependThisArgument(ctdec, vthis); Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); @@ -2034,17 +2039,13 @@ void Parser::AddDefaultConstructors(Declaration* pthis) pexp->mDecValue = ctdec->mParams; Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE); - aexp->mDecType = TheUnsignedIntTypeDeclaration; + aexp->mDecType = pthis; aexp->mDecValue = adec; Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); iexp->mToken = TK_INC; iexp->mLeft = pexp; - Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); - dexp->mToken = TK_DEC; - dexp->mLeft = aexp; - Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); fexp->mDecValue = pthis->mBase->mDefaultConstructor; fexp->mDecType = fexp->mDecValue->mBase; @@ -2054,10 +2055,12 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cexp->mRight = iexp; Expression * wexp = new Expression(mScanner->mLocation, EX_WHILE); - wexp->mLeft = aexp; - wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); - wexp->mRight->mLeft = cexp; - wexp->mRight->mRight = dexp; + wexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); + wexp->mLeft->mToken = TK_NOT_EQUAL; + wexp->mLeft->mLeft = pexp; + wexp->mLeft->mRight = aexp; + wexp->mLeft->mDecType = TheBoolTypeDeclaration; + wexp->mRight = cexp; cdec->mValue = wexp; } @@ -2070,17 +2073,18 @@ void Parser::AddDefaultConstructors(Declaration* pthis) ctdec->mBase = TheVoidTypeDeclaration; ctdec->mFlags |= DTF_DEFINED; + Declaration* vthis = pthis->Clone(); + vthis->mFlags &= ~DTF_CONST; + Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT); adec->mVarIndex = 0; adec->mOffset = 0; - adec->mBase = TheUnsignedIntTypeDeclaration; + adec->mBase = pthis; adec->mSize = adec->mBase->mSize; - adec->mIdent = adec->mQualIdent = Ident::Unique("n"); + adec->mIdent = adec->mQualIdent = Ident::Unique("end"); ctdec->mParams = adec; - Declaration* vthis = pthis->Clone(); - vthis->mFlags &= ~DTF_CONST; PrependThisArgument(ctdec, vthis); Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); @@ -2114,17 +2118,13 @@ void Parser::AddDefaultConstructors(Declaration* pthis) pexp->mDecValue = ctdec->mParams; Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE); - aexp->mDecType = TheUnsignedIntTypeDeclaration; + aexp->mDecType = pthis; aexp->mDecValue = adec; Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); iexp->mToken = TK_INC; iexp->mLeft = pexp; - Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); - dexp->mToken = TK_DEC; - dexp->mLeft = aexp; - Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); fexp->mDecValue = pthis->mBase->mDestructor; fexp->mDecType = fexp->mDecValue->mBase; @@ -2134,10 +2134,13 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cexp->mRight = iexp; Expression* wexp = new Expression(mScanner->mLocation, EX_WHILE); - wexp->mLeft = aexp; - wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); - wexp->mRight->mLeft = cexp; - wexp->mRight->mRight = dexp; + wexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); + wexp->mLeft->mToken = TK_NOT_EQUAL; + wexp->mLeft->mLeft = pexp; + wexp->mLeft->mRight = aexp; + wexp->mLeft->mDecType = TheBoolTypeDeclaration; + + wexp->mRight = cexp; cdec->mValue = wexp; } @@ -2419,9 +2422,13 @@ void Parser::AppendMemberDestructor(Declaration* pthis) dexp->mLeft = cexp; dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); dexp->mRight->mLeft = qexp; - dexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); - dexp->mRight->mRight->mDecType = ncdec->mBase; - dexp->mRight->mRight->mDecValue = ncdec; + dexp->mRight->mRight = new Expression(mScanner->mLocation, EX_BINARY); + dexp->mRight->mRight->mToken = TK_ADD; + dexp->mRight->mRight->mLeft = qexp; + dexp->mRight->mRight->mDecType = qexp->mDecType; + dexp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + dexp->mRight->mRight->mRight->mDecType = ncdec->mBase; + dexp->mRight->mRight->mRight->mDecValue = ncdec; } Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); @@ -3408,9 +3415,16 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); fexp->mLeft = cexp; + fexp->mRight = new Expression(mScanner->mLocation, EX_LIST); fexp->mRight->mLeft = vexp; - fexp->mRight->mRight = ncexp; + fexp->mRight->mRight = new Expression(mScanner->mLocation, EX_BINARY); + fexp->mRight->mRight->mToken = TK_ADD; + fexp->mRight->mRight->mLeft = vexp; + fexp->mRight->mRight->mDecType = vexp->mDecType; + fexp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + fexp->mRight->mRight->mRight->mDecType = ncdec->mBase; + fexp->mRight->mRight->mRight->mDecValue = ncdec; Expression* dexp = nullptr; if (bdec->mDestructor) @@ -3421,9 +3435,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex dexp = new Expression(mScanner->mLocation, EX_CALL); dexp->mLeft = cexp; - dexp->mRight = new Expression(mScanner->mLocation, EX_LIST); - dexp->mRight->mLeft = vexp; - dexp->mRight->mRight = ncexp; + dexp->mRight = fexp->mRight; } Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); @@ -4502,69 +4514,182 @@ Expression* Parser::ParsePrefixExpression(bool lhs) sexp->mDecValue = sconst; sexp->mDecType = TheUnsignedIntTypeDeclaration; - nexp->mLeft = sexp; - nexp->mDecType = dec->BuildPointer(mScanner->mLocation); + Declaration* nudec = new Declaration(mScanner->mLocation, DT_CONST_ADDRESS); + nudec->mBase = TheVoidPointerTypeDeclaration; + nudec->mInteger = 0; + Expression* nuexp = new Expression(mScanner->mLocation, EX_CONSTANT); + nuexp->mDecValue = nudec; + nuexp->mDecType = nudec->mBase; - if (mScanner->mToken == TK_OPEN_PARENTHESIS || dec->mDefaultConstructor) + if (ConsumeTokenIf(TK_OPEN_BRACKET)) { - Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); - vdec->mVarIndex = mLocalIndex++; - vdec->mBase = nexp->mDecType; - vdec->mSize = 2; + Expression* mexp = new Expression(mScanner->mLocation, EX_BINARY); + mexp->mToken = TK_MUL; + mexp->mLeft = sexp; + mexp->mRight = ParseExpression(false); + mexp->mDecType = TheUnsignedIntTypeDeclaration; + ConsumeToken(TK_CLOSE_BRACKET); - Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); - vexp->mDecType = vdec->mBase; - vexp->mDecValue = vdec; + nexp->mLeft = mexp; + nexp->mDecType = dec->BuildPointer(mScanner->mLocation); - Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); - iexp->mToken = TK_ASSIGN; - iexp->mLeft = vexp; - iexp->mRight = nexp; - iexp->mDecType = nexp->mDecType; - - Declaration* mdec = dec->mDefaultConstructor; - Expression* pexp = iexp; - - if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) + if (dec->mVectorConstructor) { - if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) - { - pexp = ParseListExpression(); + Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + vdec->mVarIndex = mLocalIndex++; + vdec->mBase = nexp->mDecType; + vdec->mSize = 2; - mdec = dec->mScope->Lookup(dec->mIdent); + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = vdec->mBase; + vexp->mDecValue = vdec; - ConsumeToken(TK_CLOSE_PARENTHESIS); + Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + iexp->mToken = TK_ASSIGN; + iexp->mLeft = vexp; + iexp->mRight = nexp; + iexp->mDecType = nexp->mDecType; - Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); - lexp->mLeft = iexp; - lexp->mRight = pexp; - pexp = lexp; - } + Expression* csexp = new Expression(mScanner->mLocation, EX_TYPECAST); + csexp->mLeft = vexp; + csexp->mDecType = nexp->mDecType->BuildPointer(mScanner->mLocation); + + Declaration* mdec = dec->mVectorConstructor; + + Expression* pexp = new Expression(mScanner->mLocation, EX_LIST); + pexp->mLeft = vexp; + pexp->mRight = new Expression(mScanner->mLocation, EX_INDEX); + pexp->mRight->mLeft = csexp; + pexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + pexp->mRight->mRight->mDecType = TheSignedIntTypeDeclaration; + pexp->mRight->mRight->mDecValue = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + pexp->mRight->mRight->mDecValue->mBase = TheSignedIntTypeDeclaration; + pexp->mRight->mRight->mDecValue->mInteger = -1; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + + Expression* coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); + coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); + coexp->mLeft->mDecType = TheBoolTypeDeclaration; + coexp->mLeft->mToken = TK_EQUAL; + coexp->mLeft->mLeft = vexp; + coexp->mLeft->mRight = nuexp; + coexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + coexp->mRight->mLeft = vexp; + coexp->mRight->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + coexp->mRight->mRight->mLeft = dexp; + coexp->mRight->mRight->mRight = vexp; + coexp->mDecType = vexp->mDecType; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + sexp->mLeft = iexp; + sexp->mRight = coexp; + + nexp = sexp; } + } + else + { + nexp->mLeft = sexp; + nexp->mDecType = dec->BuildPointer(mScanner->mLocation); - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; + if (mScanner->mToken == TK_OPEN_PARENTHESIS || dec->mDefaultConstructor) + { + Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + vdec->mVarIndex = mLocalIndex++; + vdec->mBase = nexp->mDecType; + vdec->mSize = 2; - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = vdec->mBase; + vexp->mDecValue = vdec; - ResolveOverloadCall(cexp, pexp); + Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + iexp->mToken = TK_ASSIGN; + iexp->mLeft = vexp; + iexp->mRight = nexp; + iexp->mDecType = nexp->mDecType; - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + Declaration* mdec = dec->mDefaultConstructor; + Expression* pexp = vexp; - sexp->mLeft = dexp; - sexp->mRight = vexp; + if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) + { + if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) + { + pexp = ParseListExpression(); - nexp = sexp; + mdec = dec->mScope->Lookup(dec->mIdent); + + ConsumeToken(TK_CLOSE_PARENTHESIS); + + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = vexp; + lexp->mRight = pexp; + pexp = lexp; + } + } + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + + ResolveOverloadCall(cexp, pexp); + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = vexp; + + Expression * coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); + coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); + coexp->mLeft->mDecType = TheBoolTypeDeclaration; + coexp->mLeft->mToken = TK_EQUAL; + coexp->mLeft->mLeft = vexp; + coexp->mLeft->mRight = nuexp; + coexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + coexp->mRight->mLeft = vexp; + coexp->mRight->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + coexp->mRight->mRight->mLeft = dexp; + coexp->mRight->mRight->mRight = vexp; + coexp->mDecType = vexp->mDecType; + + nexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + nexp->mLeft = iexp; + nexp->mRight = coexp; + } } } else if (mScanner->mToken == TK_DELETE) { + bool vdelete = false; + + mScanner->NextToken(); + if (ConsumeTokenIf(TK_OPEN_BRACKET)) + { + ConsumeToken(TK_CLOSE_BRACKET); + vdelete = true; + } + + Declaration* nudec = new Declaration(mScanner->mLocation, DT_CONST_ADDRESS); + nudec->mBase = TheVoidPointerTypeDeclaration; + nudec->mInteger = 0; + Expression* nuexp = new Expression(mScanner->mLocation, EX_CONSTANT); + nuexp->mDecValue = nudec; + nuexp->mDecType = nudec->mBase; + nexp = new Expression(mScanner->mLocation, EX_PREFIX); nexp->mToken = TK_DELETE; - mScanner->NextToken(); nexp->mLeft = ParsePrefixExpression(false); nexp->mDecType = TheVoidTypeDeclaration; if (nexp->mLeft->mDecType->mType == DT_TYPE_POINTER) @@ -4588,6 +4713,26 @@ Expression* Parser::ParsePrefixExpression(bool lhs) iexp->mDecType = nexp->mLeft->mDecType; Declaration* mdec = dec->mDestructor; + Expression* pexp = vexp; + + if (vdelete) + { + mdec = dec->mVectorDestructor; + + Expression* csexp = new Expression(mScanner->mLocation, EX_TYPECAST); + csexp->mLeft = vexp; + csexp->mDecType = nexp->mLeft->mDecType->BuildPointer(mScanner->mLocation); + + pexp = new Expression(mScanner->mLocation, EX_LIST); + pexp->mLeft = vexp; + pexp->mRight = new Expression(mScanner->mLocation, EX_INDEX); + pexp->mRight->mLeft = csexp; + pexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + pexp->mRight->mRight->mDecType = TheSignedIntTypeDeclaration; + pexp->mRight->mRight->mDecValue = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + pexp->mRight->mRight->mDecValue->mBase = TheSignedIntTypeDeclaration; + pexp->mRight->mRight->mDecValue->mInteger = -1; + } Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); cexp->mDecValue = mdec; @@ -4595,13 +4740,20 @@ Expression* Parser::ParsePrefixExpression(bool lhs) Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); dexp->mLeft = cexp; - dexp->mRight = iexp; + dexp->mRight = pexp; Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - - sexp->mLeft = dexp; - sexp->mRight = nexp; - + sexp->mLeft = iexp; + sexp->mRight = new Expression(mScanner->mLocation, EX_IF); + sexp->mRight->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); + sexp->mRight->mLeft->mDecType = TheBoolTypeDeclaration; + sexp->mRight->mLeft->mToken = TK_NOT_EQUAL; + sexp->mRight->mLeft->mLeft = vexp; + sexp->mRight->mLeft->mRight = nuexp; + sexp->mRight->mRight = new Expression(mScanner->mLocation, EX_LIST); + sexp->mRight->mRight->mLeft = new Expression(mScanner->mLocation, EX_SEQUENCE); + sexp->mRight->mRight->mLeft->mLeft = dexp; + sexp->mRight->mRight->mLeft->mRight = nexp; nexp->mLeft = iexp; nexp = sexp; From ef0a79b8f0f991099bf9212841ad36b887b49bc7 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 2 Jul 2023 18:21:40 +0200 Subject: [PATCH 021/169] Index operator overload --- README.md | 1 + oscar64/InterCodeGenerator.cpp | 38 ++++++++++++++++++++++ oscar64/InterCodeGenerator.h | 1 + oscar64/Parser.cpp | 58 +++++++++++++++++++++++++++++----- oscar64/Scanner.cpp | 7 ++++ 5 files changed, 97 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 84f3064..a68139f 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ Supported Features: * operator overloading (not complete yet) * single inheritance of class and struct * const member functions +* new, delete, new[] and delete[] ## Installation and Usage diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 314b047..2e094bb 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -38,6 +38,17 @@ static inline InterType InterTypeOf(const Declaration* dec) } } +InterCodeGenerator::ExValue InterCodeGenerator::ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v) +{ + if (v.mType->mType == DT_TYPE_REFERENCE) + { + v.mType = v.mType->mBase; + v.mReference++; + } + + return v; +} + InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level) { while (v.mReference > level) @@ -1617,6 +1628,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); } + if (exp->mType == EX_ASSIGNMENT) + { + vl = ToValue(proc, exp, block, vl); + vr = ToValue(proc, exp, block, vr); + } + 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)) @@ -1631,6 +1648,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* exp->mRight->mDecValue->mLinkerObject->mFlags |= LOBJF_CONST; } + if (vl.mType->mType == DT_TYPE_REFERENCE) { vr = Dereference(proc, exp, block, vr, 1); @@ -1661,6 +1679,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else if (vl.mType->mType == DT_TYPE_STRUCT || vl.mType->mType == DT_TYPE_ARRAY || vl.mType->mType == DT_TYPE_UNION) { + vr = ToValue(proc, exp, block, vr); + vr = Dereference(proc, exp, block, vr, 1); vl = Dereference(proc, exp, block, vl, 1); @@ -1689,6 +1709,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { + vr = ToValue(proc, exp, block, vr); + if (vl.mType->mType == DT_TYPE_POINTER && (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION)) { vr = Dereference(proc, exp, block, vr, 1); @@ -1864,6 +1886,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); + vl = ToValue(proc, exp, block, vl); + vr = ToValue(proc, exp, block, vr); + int stride = vl.mType->Stride(); if (vl.mType->mType == DT_TYPE_ARRAY && exp->mRight->mType == EX_CONSTANT && exp->mRight->mDecValue->mType == DT_CONST_INTEGER) @@ -1919,6 +1944,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_QUALIFY: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + + vl = ToValue(proc, exp, block, vl); + vl = Dereference(proc, exp, block, vl, 1); if (vl.mReference != 1) @@ -1947,6 +1975,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); + + vl = ToValue(proc, exp, block, vl); + vr = ToValue(proc, exp, block, vr); + vr = Dereference(proc, exp, block, vr); InterInstruction * ins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); @@ -2243,6 +2275,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_PREINCDEC: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vl = ToValue(proc, exp, block, vl); vl = Dereference(proc, exp, block, vl, 1); if (vl.mReference != 1) @@ -2304,6 +2337,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_POSTINCDEC: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vl = ToValue(proc, exp, block, vl); vl = Dereference(proc, exp, block, vl, 1); if (vl.mReference != 1) @@ -2363,6 +2397,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_PREFIX: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vl = ToValue(proc, exp, block, vl); InterInstruction * ins = new InterInstruction(exp->mLocation, IC_UNARY_OPERATOR); @@ -2468,10 +2503,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_RELATIONAL: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vl = ToValue(proc, exp, block, vl); vl = Dereference(proc, exp, block, vl, vl.mType->mType == DT_TYPE_ARRAY ? 1 : 0); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); + vr = ToValue(proc, exp, block, vr); vr = Dereference(proc, exp, block, vr, vr.mType->mType == DT_TYPE_ARRAY ? 1 : 0); + InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); Declaration* dtype = TheSignedIntTypeDeclaration; diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 4088beb..cb4f5e2 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -76,6 +76,7 @@ protected: void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, InterCodeBasicBlock* dblock); + ExValue ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v); ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level = 0); ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type, bool checkTrunc = true); ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 1ab296b..a988f19 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -4256,19 +4256,24 @@ Expression* Parser::ParsePostfixExpression(bool lhs) for (;;) { - if (mScanner->mToken == TK_OPEN_BRACKET) + if (ConsumeTokenIf(TK_OPEN_BRACKET)) { - if (exp->mDecType->mType != DT_TYPE_ARRAY && exp->mDecType->mType != DT_TYPE_POINTER) - mErrors->Error(mScanner->mLocation, EERR_INVALID_INDEX, "Array expected for indexing"); - mScanner->NextToken(); Expression* nexp = new Expression(mScanner->mLocation, EX_INDEX); nexp->mLeft = exp; nexp->mRight = ParseExpression(false); - if (mScanner->mToken == TK_CLOSE_BRACKET) - mScanner->NextToken(); + ConsumeToken(TK_CLOSE_BRACKET); + + if (exp->mDecType->mType == DT_TYPE_STRUCT) + { + nexp = CheckOperatorOverload(nexp); + } + else if (exp->mDecType->mType == DT_TYPE_ARRAY || exp->mDecType->mType == DT_TYPE_POINTER) + { + nexp->mDecType = exp->mDecType->mBase; + } else - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "']' expected"); - nexp->mDecType = exp->mDecType->mBase; + mErrors->Error(mScanner->mLocation, EERR_INVALID_INDEX, "Array expected for indexing"); + if (!nexp->mDecType) nexp->mDecType = TheVoidTypeDeclaration; exp = nexp; @@ -5139,6 +5144,43 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) } } } + else if (exp->mType == EX_INDEX) + { + Declaration* tdec = exp->mLeft->mDecType; + if (tdec->mType == DT_TYPE_STRUCT) + { + Declaration* mdec = tdec->mScope->Lookup(Ident::Unique("operator[]")); + if (mdec) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_CALL); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + nexp->mRight = exp->mRight; + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp->mLeft; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = exp->mLeft->mDecType; + texp->mDecType->mSize = 2; + + Expression* lexp = new Expression(nexp->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = nexp->mRight; + nexp->mRight = lexp; + + ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + + exp = nexp; + } + } + } else if (exp->mType == EX_BINARY || exp->mType == EX_RELATIONAL) { const Ident* opident = nullptr; diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index c68fcba..a072620 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1504,6 +1504,13 @@ void Scanner::NextRawToken(void) mTokenIdent = Ident::Unique("operator<="); break; + case TK_OPEN_BRACKET: + NextRawToken(); + if (mToken != TK_CLOSE_BRACKET) + mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "']' expected"); + mTokenIdent = Ident::Unique("operator[]"); + break; + default: mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "Invalid operator token"); } From 6c7347310be138c17afef803ca5a22d1d00aebe3 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 2 Jul 2023 20:48:46 +0200 Subject: [PATCH 022/169] Init const copy construction --- include/opp/string.cpp | 15 ++++ include/opp/string.h | 5 ++ oscar64/InterCodeGenerator.cpp | 16 +++- oscar64/Parser.cpp | 131 ++++++++++++++++----------------- 4 files changed, 95 insertions(+), 72 deletions(-) diff --git a/include/opp/string.cpp b/include/opp/string.cpp index 9d79206..b64136f 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -75,6 +75,11 @@ inline const char * string::tocstr(void) const return cstr; } +inline unsigned string::size(void) const +{ + return strlen(cstr); +} + string string::operator+(const string & s) { return string(cstr, s.cstr); @@ -145,3 +150,13 @@ inline bool string::operator>=(const char * s) const { return strcmp(cstr, s) >= 0; } + +inline char & string::operator[](unsigned t) +{ + return cstr[t]; +} + +inline char string::operator[](unsigned t) const +{ + return cstr[t]; +} diff --git a/include/opp/string.h b/include/opp/string.h index a0b4926..bde2f0a 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -13,6 +13,8 @@ public: string(const char * s1, const char * s2); ~string(void); + unsigned size(void) const; + string & operator=(const string & s); string & operator=(const char * s); @@ -37,6 +39,9 @@ public: bool operator>=(const string & s) const; bool operator>=(const char * s) const; + char & operator[](unsigned t); + char operator[](unsigned t) const; + const char * tocstr(void) const; }; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 2e094bb..27a5519 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1073,7 +1073,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro block->Append(ins); - return ExValue(rdec->mBase, ins->mDst.mTemp, 1); + ExValue rv(rdec->mBase, ins->mDst.mTemp, 1); + if (ins->mDst.mType != DT_TYPE_REFERENCE) + rv = Dereference(proc, exp, block, rv); + return rv; } else if (lrexp) { @@ -2991,7 +2994,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* pex = nullptr; } - ExValue vp(pdec ? pdec->mBase : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); + Declaration* ptype = pdec ? pdec->mBase : texp->mDecType; + + ExValue vp(ptype ? ptype : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE && texp->mType == EX_CALL) { @@ -3018,8 +3023,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* #endif } - vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, &vp); - + if (ptype && (ptype->mType == DT_TYPE_STRUCT || ptype->mType == DT_TYPE_UNION)) + vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, &vp); + else + vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, nullptr); + if (!(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) { if (pdec && !pdec->mBase->CanAssign(vr.mType)) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index a988f19..9488b7e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2660,78 +2660,73 @@ void Parser::ParseVariableInit(Declaration* ndec) else mScanner->NextToken(); - if (pexp && pexp->mType != EX_LIST && ndec->mBase->CanAssign(pexp->mDecType)) + Declaration* fcons = ndec->mBase->mScope ? ndec->mBase->mScope->Lookup(ndec->mBase->mIdent) : nullptr; + + if (fcons) + { + Declaration* mtype = ndec->mBase->ToMutableType(); + + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = mtype; + vexp->mDecValue = ndec; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = fcons; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = pexp; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = mtype; + texp->mDecType->mSize = 2; + + if (fexp->mRight) + { + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = fexp->mRight; + fexp->mRight = lexp; + } + else + fexp->mRight = texp; + + ResolveOverloadCall(cexp, fexp->mRight); + + Expression* dexp = nullptr; + if (ndec->mBase->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = ndec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + ndec->mValue = nexp; + } + else if (pexp && pexp->mType != EX_LIST && ndec->mBase->CanAssign(pexp->mDecType)) { ndec->mValue = pexp; } else - { - Declaration* fcons = ndec->mBase->mScope ? ndec->mBase->mScope->Lookup(ndec->mBase->mIdent) : nullptr; - - if (fcons) - { - Declaration* mtype = ndec->mBase->ToMutableType(); - - Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); - vexp->mDecType = mtype; - vexp->mDecValue = ndec; - - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = fcons; - cexp->mDecType = cexp->mDecValue->mBase; - - Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); - fexp->mLeft = cexp; - fexp->mRight = pexp; - - Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); - texp->mToken = TK_BINARY_AND; - texp->mLeft = vexp; - texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); - texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = mtype; - texp->mDecType->mSize = 2; - - if (fexp->mRight) - { - Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); - lexp->mLeft = texp; - lexp->mRight = fexp->mRight; - fexp->mRight = lexp; - } - else - fexp->mRight = texp; - - ResolveOverloadCall(cexp, fexp->mRight); - - Expression* dexp = nullptr; - if (ndec->mBase->mDestructor) - { - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = ndec->mBase->mDestructor; - cexp->mDecType = cexp->mDecValue->mBase; - - dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = texp; - } - - Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); - - nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); - nexp->mLeft->mLeft = fexp; - nexp->mLeft->mRight = dexp; - - nexp->mRight = vexp; - nexp->mDecType = vexp->mDecType; - - ndec->mValue = nexp; - } - else - { - ndec->mValue = pexp; - } - } + mErrors->Error(pexp->mLocation, EERR_INCOMPATIBLE_TYPES, "Can not initialize variable with expression", ndec->mIdent); } Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis) From b91e76f21601947c7fc4b63a56c1ecd6c5daa177 Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 3 Jul 2023 15:56:16 +0200 Subject: [PATCH 023/169] Update makefile missing prg --- samples/hires/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/hires/makefile b/samples/hires/makefile index c7d47ea..1159dda 100644 --- a/samples/hires/makefile +++ b/samples/hires/makefile @@ -4,7 +4,7 @@ CFLAGS=-n %.prg: %.c $(CC) $(CFLAGS) $< -all: splitscreen.prg func3d.prg lines.prg polygon.prg bitblit.prg fractaltree.prg qsort.prg +all: splitscreen.prg func3d.prg lines.prg polygon.prg bitblit.prg cube3d.prg fractaltree.prg qsort.prg splitscreen.prg: splitscreen.c $(CC) $< From 69480c87426bd621a621bc296db05acca6a50640 Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 3 Jul 2023 15:59:51 +0200 Subject: [PATCH 024/169] Update build.sh missing prg --- samples/hires/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/hires/build.sh b/samples/hires/build.sh index e1886b3..ca60279 100755 --- a/samples/hires/build.sh +++ b/samples/hires/build.sh @@ -4,5 +4,6 @@ ../../bin/oscar64 lines.c -n ../../bin/oscar64 polygon.c -n ../../bin/oscar64 bitblit.c -n +../../bin/oscar64 cube3d.c -n ../../bin/oscar64 fractaltree.c -n ../../bin/oscar64 qsort.c -n From 1e9e426758c76218e00cfef91b028ae9e66a57c5 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 3 Jul 2023 16:44:47 +0200 Subject: [PATCH 025/169] Fix wrong enum type check --- oscar64/InterCodeGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 27a5519..81e9299 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1074,7 +1074,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro block->Append(ins); ExValue rv(rdec->mBase, ins->mDst.mTemp, 1); - if (ins->mDst.mType != DT_TYPE_REFERENCE) + if (rdec->mBase->mType != DT_TYPE_REFERENCE) rv = Dereference(proc, exp, block, rv); return rv; } From e8587105c40e5fa60db9c02f2c2ff79771414ed2 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 3 Jul 2023 17:48:55 +0200 Subject: [PATCH 026/169] Fix duplicate label in crt.c --- include/crt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/crt.c b/include/crt.c index 26cf053..2f30649 100644 --- a/include/crt.c +++ b/include/crt.c @@ -4190,7 +4190,7 @@ loop: sta accu + 1 // exit if out of blocks - beq done + beq hempty adc tmp + 1 sta tmp + 3 @@ -4211,7 +4211,7 @@ loop: ldx accu + 1 jmp loop -done: +hempty: // no more heap blocks rts From 0b79d443455dee9ad4c29f66d7a477164033a9a0 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 3 Jul 2023 22:39:24 +0200 Subject: [PATCH 027/169] Fix location of error message of duplicate function definition --- oscar64/Parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 9488b7e..0e1caf2 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3462,7 +3462,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ndec->mBase->mType == DT_TYPE_FUNCTION) { if (ndec->mFlags & DTF_DEFINED) - mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition"); + mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition"); ndec->mCompilerOptions = mCompilerOptions; ndec->mBase->mCompilerOptions = mCompilerOptions; From 0b6a9c35843c257ed360dbe2e16178a888bb8722 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 5 Jul 2023 17:10:23 +0200 Subject: [PATCH 028/169] Copy elision on return statements --- oscar64/Declaration.cpp | 63 +++++++++++++++++++++++++++++++++ oscar64/Declaration.h | 5 ++- oscar64/GlobalAnalyzer.cpp | 2 +- oscar64/InterCode.cpp | 10 +++++- oscar64/InterCodeGenerator.cpp | 58 ++++++++++++++++++++++++++++-- oscar64/NativeCodeGenerator.cpp | 18 +++++++--- oscar64/Parser.cpp | 26 +++++++++++--- oscar64/Parser.h | 2 +- 8 files changed, 168 insertions(+), 16 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 99b56f6..520abe9 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -270,6 +270,9 @@ void Expression::Dump(int ident) const case EX_CLEANUP: printf("CLEANUP"); break; + case EX_RESULT: + printf("RESULT"); + break; } printf("\n"); @@ -810,6 +813,15 @@ Declaration* Declaration::BuildPointer(const Location& loc) return pdec; } +Declaration* Declaration::BuildReference(const Location& loc) +{ + Declaration* pdec = new Declaration(loc, DT_TYPE_REFERENCE); + pdec->mBase = this; + pdec->mFlags = DTF_DEFINED; + pdec->mSize = 2; + return pdec; +} + Declaration* Declaration::Last(void) { mPrev = nullptr; @@ -1069,6 +1081,57 @@ bool Declaration::IsSubType(const Declaration* dec) const return false; } +bool Declaration::IsSameMutable(const Declaration* dec) const +{ + if (this == dec) + return true; + if (mType != dec->mType) + return false; + if (mSize != dec->mSize) + return false; + if (mStripe != dec->mStripe) + return false; + + if ((mFlags & DTF_SIGNED) != (dec->mFlags & DTF_SIGNED)) + return false; + if ((dec->mFlags & DTF_CONST) && !(mFlags & DTF_CONST)) + return false; + + if (mType == DT_TYPE_INTEGER) + return true; + else if (mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_VOID) + return true; + else if (mType == DT_TYPE_ENUM) + return mIdent == dec->mIdent; + else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) + return this->Stride() == dec->Stride() && mBase->IsSame(dec->mBase); + else if (mType == DT_TYPE_STRUCT) + return mScope == dec->mScope || (mIdent == dec->mIdent && mSize == dec->mSize); + else if (mType == DT_TYPE_FUNCTION) + { + if (!mBase->IsSame(dec->mBase)) + return false; + Declaration* dl = mParams, * dr = dec->mParams; + while (dl && dr) + { + if (!dl->mBase->IsSame(dr->mBase)) + return false; + dl = dl->mNext; + dr = dr->mNext; + } + + if (dl || dr) + return false; + + if ((mFlags & DTF_VARIADIC) != (dec->mFlags & DTF_VARIADIC)) + return false; + + return true; + } + + return false; +} + bool Declaration::IsConstSame(const Declaration* dec) const { if (this == dec) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index fab88ce..8f44b7d 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -187,7 +187,8 @@ enum ExpressionType EX_ASSUME, EX_BANKOF, EX_CONSTRUCT, - EX_CLEANUP + EX_CLEANUP, + EX_RESULT }; class Expression @@ -247,6 +248,7 @@ public: bool IsConstSame(const Declaration* dec) const; bool IsSameValue(const Declaration* dec) const; bool IsSameParams(const Declaration* dec) const; + bool IsSameMutable(const Declaration* dec) const; bool IsIntegerType(void) const; bool IsNumericType(void) const; @@ -263,6 +265,7 @@ public: Declaration* Last(void); Declaration* BuildPointer(const Location& loc); + Declaration* BuildReference(const Location& loc); int Stride(void) const; }; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 20f2221..8d0bf1a 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -687,7 +687,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo if (pdec && !(ldec->mBase->mFlags & DTF_VARIADIC) && !(ldec->mFlags & (DTF_INTRINSIC | DTF_FUNC_ASSEMBLER))) { -#if 0 +#if 1 if (mCompilerOptions & COPT_OPTIMIZE_BASIC) { if (!(pdec->mFlags & DTF_FPARAM_NOCONST)) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 6bb85ca..e28d5c0 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -6879,6 +6879,10 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray vr.LimitMax(ins->mSrc[0].mIntConst - 1); else if (ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND) vr.LimitMax(ins->mSrc[0].mRange.mMaxValue - 1); + else if (ins->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND) + vr.LimitMax(ins->mSrc[1].mRange.mMaxValue); + else + vr.mMaxState = IntegerValueRange::S_UNBOUND; break; #endif default: @@ -11883,6 +11887,10 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) { ins->mInvariant = false; } + else if (ins->mSrc[0].mMemory == IM_PARAM && hasCall && aliasedParams[ins->mSrc[0].mVarIndex]) + { + ins->mInvariant = false; + } else { for (int bj = 0; bj < body.Size(); bj++) @@ -16098,7 +16106,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "print"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 81e9299..b909701 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1313,7 +1313,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_CONSTRUCT: { if (exp->mLeft->mLeft) - TranslateExpression(procType, proc, block, exp->mLeft->mLeft, destack, breakBlock, continueBlock, inlineMapper); + TranslateExpression(procType, proc, block, exp->mLeft->mLeft, destack, breakBlock, continueBlock, inlineMapper, lrexp); if (exp->mLeft->mRight) { @@ -1327,6 +1327,60 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } break; + case EX_RESULT: + { + if (lrexp) + return *lrexp; + + InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + + if (inlineMapper) + { + if (inlineMapper->mResultExp) + { + ains->mDst.mTemp = inlineMapper->mResultExp->mTemp; + } + else + { + ains->mCode = IC_CONSTANT; + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(IT_POINTER); + ains->mConst.mOperandSize = procType->mBase->mSize; + ains->mConst.mIntConst = 0; + ains->mConst.mVarIndex = inlineMapper->mResult; + ains->mConst.mMemory = IM_LOCAL; + block->Append(ains); + } + } + else + { + InterInstruction* pins = new InterInstruction(exp->mLocation, IC_CONSTANT); + pins->mDst.mType = IT_POINTER; + pins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + pins->mConst.mVarIndex = 0; + pins->mConst.mIntConst = 0; + pins->mConst.mOperandSize = 2; + if (procType->mFlags & DTF_FASTCALL) + { + pins->mConst.mMemory = IM_FPARAM; + pins->mConst.mVarIndex += procType->mFastCallBase; + } + else + pins->mConst.mMemory = IM_PARAM; + block->Append(pins); + + ains->mCode = IC_LOAD; + ains->mSrc[0].mMemory = IM_INDIRECT; + ains->mSrc[0].mType = IT_POINTER; + ains->mSrc[0].mTemp = pins->mDst.mTemp; + ains->mDst.mType = IT_POINTER; + ains->mDst.mTemp = proc->AddTemporary(IT_POINTER); + ains->mNumOperands = 1; + block->Append(ains); + } + + return ExValue(exp->mDecType, ains->mDst.mTemp, 1); + } case EX_CLEANUP: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); @@ -4453,7 +4507,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)); #if 0 - if (proc->mIdent && !strcmp(proc->mIdent->mString, "main")) + if (proc->mIdent && !strcmp(proc->mIdent->mString, "A::func")) exp->Dump(0); #endif #if 0 diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index de13f29..de92f06 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -18971,6 +18971,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool i++; if (i == mEntryBlocks.Size()) { + mEntryRequiredRegs += CPU_REG_A; + mIns.Insert(0, eb->mIns[index]); mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y; for (int i = 0; i < mEntryBlocks.Size(); i++) @@ -18992,6 +18994,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool i++; if (i == mEntryBlocks.Size()) { + mEntryRequiredRegs += CPU_REG_X; + mIns.Insert(0, eb->mIns[index]); mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y; for (int i = 0; i < mEntryBlocks.Size(); i++) @@ -19013,6 +19017,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool i++; if (i == mEntryBlocks.Size()) { + mEntryRequiredRegs += CPU_REG_Y; + mIns.Insert(0, eb->mIns[index]); mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y; for (int i = 0; i < mEntryBlocks.Size(); i++) @@ -24803,6 +24809,8 @@ bool NativeCodeBasicBlock::MoveAbsoluteLoadStoreUp(int at) return false; if (mIns[at + 1].mMode == ASMIM_ABSOLUTE_Y && mIns[j].ChangesYReg()) return false; + if (mIns[at + 1].mMode == ASMIM_INDIRECT_Y && (mIns[j].ChangesYReg() || mIns[j].ChangesZeroPage(mIns[at + 1].mAddress) || mIns[j].ChangesZeroPage(mIns[at + 1].mAddress + 1))) + return false; if (mIns[j].mType == ASMIT_JSR) return false; @@ -33307,7 +33315,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass for (int i = 2; i + 1 < mIns.Size(); i++) { if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STA && - (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_X || mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y)) + (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ABSOLUTE_X || mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y || mIns[i + 1].mMode == ASMIM_INDIRECT_Y)) { if (MoveAbsoluteLoadStoreUp(i)) changed = true; @@ -36469,7 +36477,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass else if ( mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mType == ASMIT_ROL && mIns[i + 1].mMode == ASMIM_IMPLIED && - mIns[i + 2].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_CLC && mIns[i + 3].mType == ASMIT_ADC) { mIns[i + 1].mType = ASMIT_NOP; @@ -36536,7 +36544,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } else if ( - mIns[i + 0].mType == ASMIT_LDA && + mIns[i + 0].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !mIns[i + 0].MayBeChangedOnAddress(mIns[i + 1]) && mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mType == ASMIT_ORA && mIns[i + 3].SameEffectiveAddress(mIns[i + 0]) && mIns[i + 3].mMode != ASMIM_IMMEDIATE) @@ -36548,9 +36556,9 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } else if ( - mIns[i + 0].mType == ASMIT_LDA && + mIns[i + 0].mType == ASMIT_LDA && mIns[i + 1].mType == ASMIT_EOR && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0xff && - mIns[i + 2].mType == ASMIT_SEC && + (mIns[i + 2].mType == ASMIT_SEC || mIns[i + 2].mType == ASMIT_CLC) && mIns[i + 3].mType == ASMIT_ADC) { mIns.Insert(i + 4, mIns[i + 0]); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 0e1caf2..c99c46e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3172,9 +3172,12 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { pdec = mCompilationUnits->mScope->Insert(ndec->mQualIdent, ndec); - Declaration * ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec); - if (ldec && ldec != pdec) - mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); + if (ndec->mIdent == ndec->mQualIdent) + { + Declaration* ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec); + if (ldec && ldec != pdec) + mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); + } } else pdec = mScope->Insert(ndec->mIdent, ndec); @@ -4184,7 +4187,7 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) else return NOOVERLOAD; } - else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_ARRAY && ptype->mBase->IsSame(etype->mBase)) + else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_ARRAY && ptype->mBase->IsSameMutable(etype->mBase)) dist += 1; else if (ptype->IsSubType(etype)) dist += 256; @@ -4819,7 +4822,9 @@ Expression* Parser::ParseMulExpression(bool lhs) else nexp->mDecType = exp->mDecType; - exp = nexp->ConstantFold(mErrors); + exp = CheckOperatorOverload(nexp); + + exp = exp->ConstantFold(mErrors); } return exp; @@ -5322,6 +5327,7 @@ Expression* Parser::ParseFunction(Declaration * dec) if (dec->mFlags & DTF_FUNC_THIS) mThisPointer = dec->mParams; + mReturnType = dec->mBase; DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_FUNCTION); mScope = scope; @@ -5713,7 +5719,17 @@ Expression* Parser::ParseStatement(void) mScanner->NextToken(); exp = new Expression(mScanner->mLocation, EX_RETURN); if (mScanner->mToken != TK_SEMICOLON) + { exp->mLeft = CleanupExpression(ParseRExpression()); + if (exp->mLeft->mType == EX_CONSTRUCT && mReturnType && mReturnType->mType == DT_TYPE_STRUCT) + { + Expression* cexp = exp->mLeft->mLeft->mLeft; + + exp->mLeft->mLeft->mRight = nullptr; + + exp->mLeft->mRight->mType = EX_RESULT; + } + } ConsumeToken(TK_SEMICOLON); break; case TK_BREAK: diff --git a/oscar64/Parser.h b/oscar64/Parser.h index b0515fe..8691e9e 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -13,7 +13,7 @@ public: DeclarationScope * mGlobals, * mScope; int mLocalIndex; CompilationUnits * mCompilationUnits; - Declaration * mThisPointer; + Declaration * mThisPointer, * mReturnType; LinkerSection * mCodeSection, * mDataSection, * mBSSection; From ed9aa3503b67ee782f84a7529dd25fd54aac53c3 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 8 Jul 2023 18:53:06 +0200 Subject: [PATCH 029/169] Added virtual functions --- README.md | 4 + autotest/autotest.bat | 6 + autotest/vcalltest.cpp | 93 +++++++++ autotest/vcalltree.cpp | 79 ++++++++ oscar64/ByteCodeGenerator.cpp | 1 + oscar64/CompilationUnits.cpp | 1 + oscar64/CompilationUnits.h | 2 +- oscar64/Compiler.cpp | 154 +++++++++++++++ oscar64/Compiler.h | 1 + oscar64/CompilerTypes.h | 7 +- oscar64/Declaration.cpp | 16 +- oscar64/Declaration.h | 19 +- oscar64/GlobalAnalyzer.cpp | 16 +- oscar64/InterCode.cpp | 38 ++-- oscar64/InterCode.h | 2 + oscar64/InterCodeGenerator.cpp | 46 ++++- oscar64/NativeCodeGenerator.cpp | 23 +-- oscar64/NativeCodeGenerator.h | 8 +- oscar64/Parser.cpp | 329 +++++++++++++++++++++++-------- oscar64/Scanner.cpp | 3 + oscar64/Scanner.h | 1 + oscar64/oscar64.cpp | 4 +- oscar64/oscar64.rc | 8 +- oscar64setup/oscar64setup.vdproj | 6 +- samples/sprites/sprmux64.c | 2 +- 25 files changed, 740 insertions(+), 129 deletions(-) create mode 100644 autotest/vcalltest.cpp create mode 100644 autotest/vcalltree.cpp diff --git a/README.md b/README.md index a68139f..4e118ca 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ Supported Features: * single inheritance of class and struct * const member functions * new, delete, new[] and delete[] +* virtual member functions ## Installation and Usage @@ -97,6 +98,7 @@ The compiler is command line driven, and creates an executable .prg file. * -Oi : enable auto inline of small functions (part of O2/O3) * -Oa : optimize inline assembler (part of O2/O3) * -Oz : enable auto placement of global variables in zero page (part of O3) +* -Op : optimize constant parameters * -g : create source level debug info and add source line numbers to asm listing * -tf : target format, may be prg, crt or bin * -tm : target machine @@ -328,6 +330,8 @@ Set optimizer options that are active for the functions after it * inline : inline if requesed with inline storage attribute * autoinline : auto inline of small or only once used functions * maxinline : inline any function suitable +* constparams : enable constant parameter folding into called functions +* noconstparams : disable constant parameter folding into called functions * 0 : no optimization * 1 : default optimizations * 2 : aggressive optimizations diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 4ec42d3..f6aca82 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -1,5 +1,11 @@ rem @echo off +@call :test vcalltest.cpp +@if %errorlevel% neq 0 goto :error + +@call :test vcalltree.cpp +@if %errorlevel% neq 0 goto :error + @call :test constructortest.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/vcalltest.cpp b/autotest/vcalltest.cpp new file mode 100644 index 0000000..2b1fd56 --- /dev/null +++ b/autotest/vcalltest.cpp @@ -0,0 +1,93 @@ +#include + +struct A +{ + virtual int f(int x); +}; + +struct B : A +{ + virtual int f(int x); +}; + +struct C : A +{ + virtual int f(int x); + virtual int g(int y, int z); +}; + +struct D : B +{ + virtual int f(int x); +}; + +struct E : C +{ + virtual int f(int x); + virtual int g(int y, int z); +}; + +struct F : C +{ + virtual int g(int y, int z); +}; + +int A::f(int x) +{ + return x * 1; +} + +int B::f(int x) +{ + return x * 2; +} + +int C::f(int x) +{ + return x * 3; +} + +int C::g(int y, int z) +{ + return (y + z) * 3; +} + +int D::f(int x) +{ + return x * 4; +} + +int E::f(int x) +{ + return x * 5; +} + +int E::g(int y, int z) +{ + return (y + z) * 5; +} + +int F::g(int y, int z) +{ + return (y + z) * 6; +} + +int main(void) +{ + A a; + B b; + C c; + D d; + E e; + F f; + + assert(a.f(3) == c.f(1)); + assert(b.f(4) == d.f(2)); + assert(e.f(2) == b.f(5)); + assert(f.f(5) == e.f(3)); + + assert(c.g(3, 2) == e.g(1, 2)); + assert(c.g(1, 5) == f.g(0, 3)); + + return 0; +} diff --git a/autotest/vcalltree.cpp b/autotest/vcalltree.cpp new file mode 100644 index 0000000..ef3ef13 --- /dev/null +++ b/autotest/vcalltree.cpp @@ -0,0 +1,79 @@ +#include + +struct Node +{ + virtual float eval(void) + { + return 1.0e6; + } +}; + +struct ConstNode : Node +{ + float c; + + ConstNode(float c_) + : c(c_) {} + + virtual float eval(void) + { + return c; + } +}; + +struct BinopNode : Node +{ + Node * left, * right; + + BinopNode(Node * left_, Node * right_) + : left(left_), right(right_) + {} +}; + +struct AddNode : BinopNode +{ + AddNode(Node * left_, Node * right_) + : BinopNode(left_, right_) + {} + + virtual float eval(void) + { + return left->eval() + right->eval(); + } +}; + +struct SubNode : BinopNode +{ + SubNode(Node * left_, Node * right_) + : BinopNode(left_, right_) + {} + + virtual float eval(void) + { + return left->eval() - right->eval(); + } +}; + +struct MulNode : BinopNode +{ + MulNode(Node * left_, Node * right_) + : BinopNode(left_, right_) + {} + + virtual float eval(void) + { + return left->eval() * right->eval(); + } +}; + +int main(void) +{ + Node * n = + new SubNode( + new MulNode(new ConstNode(4), new ConstNode(5)), + new AddNode(new ConstNode(12), new ConstNode(7))); + + assert(n->eval() == 1.0); + + return 0; +} diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index a966e7b..cc72866 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -4384,6 +4384,7 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p LoadConstant(iproc, ins); break; case IC_CALL: + case IC_DISPATCH: CallFunction(iproc, ins); break; case IC_CALL_NATIVE: diff --git a/oscar64/CompilationUnits.cpp b/oscar64/CompilationUnits.cpp index 11e381f..948964b 100644 --- a/oscar64/CompilationUnits.cpp +++ b/oscar64/CompilationUnits.cpp @@ -14,6 +14,7 @@ CompilationUnits::CompilationUnits(Errors * errors) mPendingUnits = nullptr; mScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); mRuntimeScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); + mVTableScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); mStartup = nullptr; for (int i = 0; i < 256; i++) diff --git a/oscar64/CompilationUnits.h b/oscar64/CompilationUnits.h index 16c334c..a68acbb 100644 --- a/oscar64/CompilationUnits.h +++ b/oscar64/CompilationUnits.h @@ -19,7 +19,7 @@ public: CompilationUnits(Errors * errors); ~CompilationUnits(void); - DeclarationScope* mScope; + DeclarationScope* mScope, * mVTableScope; CompilationUnit* mCompilationUnits, * mPendingUnits; Declaration* mStartup; diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 7215372..ad59d05 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -200,6 +200,152 @@ void Compiler::RegisterRuntime(const Location & loc, const Ident* ident) } } +static void IndexVTableTree(Declaration* vdec, int & index) +{ + vdec->mVarIndex = index; + vdec->mDefaultConstructor->mInteger = index; + index++; + Declaration* cvdec = vdec->mParams; + while (cvdec) + { + IndexVTableTree(cvdec, index); + cvdec = cvdec->mNext; + } + vdec->mSize = index - vdec->mVarIndex; +} + +static void FillVTableTree(Declaration* vdec) +{ + Declaration* cdec = vdec->mClass; + cdec->mScope->Iterate([=](const Ident* mident, Declaration* mdec) + { + if (mdec->mType == DT_CONST_FUNCTION) + { + while (mdec) + { + if (mdec->mBase->mFlags & DTF_VIRTUAL) + { + for (int i = 0; i < vdec->mSize; i++) + mdec->mVTable->mCalled[vdec->mVarIndex + i - mdec->mVTable->mDefaultConstructor->mVarIndex] = mdec; + } + mdec = mdec->mNext; + } + } + }); + + Declaration* cvdec = vdec->mParams; + while (cvdec) + { + FillVTableTree(cvdec); + cvdec = cvdec->mNext; + } +} +void Compiler::BuildVTables(void) +{ + // Connect vdecs with parents + mCompilationUnits->mVTableScope->Iterate([=](const Ident* ident, Declaration* vdec) + { + if (vdec->mBase) + { + vdec->mNext = vdec->mBase->mParams; + vdec->mBase->mParams = vdec; + } + }); + + // Number the child vtables + mCompilationUnits->mVTableScope->Iterate([=](const Ident* ident, Declaration* vdec) + { + if (!vdec->mBase) + { + int index = 0; + IndexVTableTree(vdec, index); + } + }); + + mCompilationUnits->mVTableScope->Iterate([=](const Ident* ident, Declaration* vdec) + { + if (!vdec->mBase) + { + FillVTableTree(vdec); + } + }); + + // Build vtables for functions + mCompilationUnits->mVTableScope->Iterate([=](const Ident* ident, Declaration* vdec) + { + vdec->mScope->Iterate([=](const Ident* mident, Declaration* mdec) + { + Declaration* vtabt = new Declaration(mdec->mLocation, DT_TYPE_ARRAY); + vtabt->mBase = mdec->mBase->ToStriped(vdec->mSize); + vtabt->mSize = vdec->mSize * 2; + vtabt->mStride = 1; + vtabt->mStripe = 1; + vtabt->mFlags |= DTF_CONST | DTF_DEFINED; + + Declaration* vtaba = new Declaration(mdec->mLocation, DT_VARIABLE); + vtaba->mFlags = DTF_CONST | DTF_GLOBAL | DTF_DEFINED; + vtaba->mBase = vtabt; + vtaba->mSize = vtabt->mSize; + vtaba->mValue = new Expression(mdec->mLocation, EX_CONSTANT); + vtaba->mValue->mDecType = vtabt; + vtaba->mValue->mDecValue = new Declaration(mdec->mLocation, DT_CONST_STRUCT); + vtaba->mIdent = mdec->mIdent; + vtaba->mQualIdent = mdec->mQualIdent->Mangle("$vtable"); + vtaba->mSection = mdec->mSection; + vtaba->mOffset = - vdec->mVarIndex; + + Declaration* last = nullptr; + + for (int i = 0; i < vdec->mSize; i++) + { + Declaration* vmdec = mdec->mCalled[i]; + + Expression* texp = new Expression(vmdec->mLocation, EX_CONSTANT); + texp->mDecType = vtabt->mBase; + texp->mDecValue = vmdec; + + Declaration* cdec = new Declaration(vmdec->mLocation, DT_CONST_POINTER); + cdec->mValue = texp; + cdec->mBase = vtabt->mBase; + cdec->mOffset = i; + + if (last) + last->mNext = cdec; + else + vtaba->mValue->mDecValue->mParams = cdec; + last = cdec; + } + +// mCompilationUnits->AddReferenced(vtaba); + + Expression* vexp = new Expression(mdec->mLocation, EX_QUALIFY); + vexp->mLeft = new Expression(mdec->mLocation, EX_PREFIX); + vexp->mLeft->mDecType = mdec->mBase->mParams->mBase->mBase; + vexp->mLeft->mToken = TK_MUL; + vexp->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE); + vexp->mLeft->mLeft->mDecType = mdec->mBase->mParams->mBase; + vexp->mLeft->mLeft->mDecValue = mdec->mBase->mParams; + + vexp->mDecValue = new Declaration(mdec->mLocation, DT_ELEMENT); + vexp->mDecValue->mBase = TheCharTypeDeclaration; + vexp->mDecValue->mOffset = vdec->mOffset; + vexp->mDecValue->mSize = 1; + vexp->mDecType = TheCharTypeDeclaration; + + Expression* ecall = new Expression(mdec->mLocation, EX_DISPATCH); + ecall->mLeft = new Expression(mdec->mLocation, EX_INDEX); + ecall->mDecType = vtabt->mBase; + ecall->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE); + ecall->mLeft->mLeft->mDecType = vtabt; + ecall->mLeft->mLeft->mDecValue = vtaba; + ecall->mLeft->mRight = vexp; + + mdec->mFlags |= DTF_DEFINED; + mdec->mValue = ecall; + }); + }); +} + void Compiler::CompileProcedure(InterCodeProcedure* proc) { if (!proc->mCompiled) @@ -591,6 +737,14 @@ bool Compiler::GenerateCode(void) mGlobalAnalyzer->mCompilerOptions = mCompilerOptions; + if (mCompilerOptions & COPT_CPLUSPLUS) + { + if (mCompilerOptions & COPT_VERBOSE) + printf("Build VTables\n"); + + BuildVTables(); + } + if (mCompilerOptions & COPT_VERBOSE) printf("Global analyzer\n"); diff --git a/oscar64/Compiler.h b/oscar64/Compiler.h index 0928278..b14571f 100644 --- a/oscar64/Compiler.h +++ b/oscar64/Compiler.h @@ -51,6 +51,7 @@ public: void RegisterRuntime(const Location& loc, const Ident* ident); void CompileProcedure(InterCodeProcedure* proc); + void BuildVTables(void); bool WriteDbjFile(const char* filename); }; diff --git a/oscar64/CompilerTypes.h b/oscar64/CompilerTypes.h index 9d8436e..5d0d66f 100644 --- a/oscar64/CompilerTypes.h +++ b/oscar64/CompilerTypes.h @@ -11,6 +11,7 @@ static const uint64 COPT_OPTIMIZE_AUTO_INLINE_ALL = 1ULL << 5; static const uint64 COPT_OPTIMIZE_AUTO_UNROLL = 1ULL << 6; static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 1ULL << 7; static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 1ULL << 8; +static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9; static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16; static const uint64 COPT_NATIVE = 1ULL << 17; @@ -42,11 +43,11 @@ static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS; -static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE; +static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS; -static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER; +static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS; -static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_AUTO_ZEROPAGE; +static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_AUTO_ZEROPAGE | COPT_OPTIMIZE_CONST_PARAMS; enum TargetMachine { diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 520abe9..925ad2f 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -192,6 +192,12 @@ void Expression::Dump(int ident) const case EX_INLINE: printf("INLINE"); break; + case EX_VCALL: + printf("VCALL"); + break; + case EX_DISPATCH: + printf("DISPATCH"); + break; case EX_LIST: printf("LIST"); break; @@ -788,6 +794,7 @@ Declaration::Declaration(const Location& loc, DecType type) mConst(nullptr), mMutable(nullptr), mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), + mVTable(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), mCompilerOptions(0), mUseCount(0) @@ -852,6 +859,7 @@ Declaration* Declaration::Clone(void) ndec->mLinkerObject = mLinkerObject; ndec->mAlignment = mAlignment; ndec->mSection = mSection; + ndec->mVTable = mVTable; return ndec; } @@ -930,6 +938,10 @@ Declaration* Declaration::ToStriped(int stripe) p = p->mNext; } } + else if (mType == DT_TYPE_FUNCTION) + { + ndec->mParams = mParams; + } else if (mType == DT_TYPE_ARRAY) { ndec->mStride = stripe; @@ -965,6 +977,7 @@ Declaration* Declaration::ToConstType(void) ndec->mCopyConstructor = mCopyConstructor; ndec->mVectorConstructor = mVectorConstructor; ndec->mVectorCopyConstructor = mVectorCopyConstructor; + ndec->mVTable = mVTable; ndec->mMutable = this; mConst = ndec; @@ -994,6 +1007,7 @@ Declaration* Declaration::ToMutableType(void) ndec->mCopyConstructor = mCopyConstructor; ndec->mVectorConstructor = mVectorConstructor; ndec->mVectorCopyConstructor = mVectorCopyConstructor; + ndec->mVTable = mVTable; ndec->mConst = this; mMutable = ndec; @@ -1011,7 +1025,7 @@ bool Declaration::IsSubType(const Declaration* dec) const if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) { if (dec->mType == DT_TYPE_POINTER) - return this->Stride() == dec->Stride() && mBase->IsSubType(dec->mBase); + return /*this->Stride() == dec->Stride() &&*/ mBase->IsSubType(dec->mBase); } if (mType != dec->mType) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 8f44b7d..360a62a 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -49,7 +49,9 @@ enum DecType DT_FUNCTION_REF, DT_LABEL_REF, DT_NAMESPACE, - DT_BASECLASS + DT_BASECLASS, + + DT_VTABLE }; // TypeFlags @@ -82,6 +84,7 @@ static const uint64 DTF_STRIPED = (1ULL << 24); static const uint64 DTF_DYNSTACK = (1ULL << 25); static const uint64 DTF_PRIVATE = (1ULL << 26); static const uint64 DTF_PROTECTED = (1ULL << 27); +static const uint64 DTF_VIRTUAL = (1ULL << 28); static const uint64 DTF_FUNC_VARIABLE = (1ULL << 32); static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33); @@ -129,6 +132,8 @@ public: void UseScope(DeclarationScope* scope); + template void Iterate(F && f); + ScopeLevel mLevel; const Ident * mName; @@ -144,6 +149,15 @@ protected: ExpandingArray mUsed; }; +template void DeclarationScope::Iterate(F&& f) +{ + for (int i = 0; i < mHashSize; i++) + { + if (mHash[i].mIdent) + f(mHash[i].mIdent, mHash[i].mDec); + } +} + enum ExpressionType { EX_ERROR, @@ -162,6 +176,8 @@ enum ExpressionType EX_QUALIFY, EX_CALL, EX_INLINE, + EX_VCALL, + EX_DISPATCH, EX_LIST, EX_RETURN, EX_SEQUENCE, @@ -227,6 +243,7 @@ public: Declaration * mBase, * mParams, * mNext, * mPrev, * mConst, * mMutable; Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; + Declaration * mVTable, * mClass; Expression* mValue; DeclarationScope* mScope; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 8d0bf1a..20fd213 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -656,6 +656,13 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo case EX_QUALIFY: Analyze(exp->mLeft, procDec, lhs); return exp->mDecValue->mBase; + case EX_DISPATCH: + Analyze(exp->mLeft, procDec, lhs); + break; + case EX_VCALL: + exp->mType = EX_CALL; + exp->mLeft->mDecValue = exp->mLeft->mDecValue->mVTable; + // intentional fall through case EX_CALL: case EX_INLINE: ldec = Analyze(exp->mLeft, procDec, false); @@ -688,7 +695,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo if (pdec && !(ldec->mBase->mFlags & DTF_VARIADIC) && !(ldec->mFlags & (DTF_INTRINSIC | DTF_FUNC_ASSEMBLER))) { #if 1 - if (mCompilerOptions & COPT_OPTIMIZE_BASIC) + if (mCompilerOptions & COPT_OPTIMIZE_CONST_PARAMS) { if (!(pdec->mFlags & DTF_FPARAM_NOCONST)) { @@ -922,6 +929,13 @@ void GlobalAnalyzer::RegisterProc(Declaration* to) { if (to->mType == DT_CONST_FUNCTION) { +#if 0 + if (to->mBase->mFlags & DTF_VIRTUAL) + { + + } + else +#endif if (!(to->mFlags & DTF_FUNC_VARIABLE)) { to->mFlags |= DTF_FUNC_VARIABLE; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index e28d5c0..874252d 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -626,7 +626,7 @@ static bool SameInstruction(const InterInstruction* ins1, const InterInstruction bool InterCodeBasicBlock::CanSwapInstructions(const InterInstruction* ins0, const InterInstruction* ins1) const { // Cannot swap branches - if (ins1->mCode == IC_JUMP || ins1->mCode == IC_BRANCH) + if (ins1->mCode == IC_JUMP || ins1->mCode == IC_BRANCH || ins1->mCode == IC_DISPATCH) return false; // Check function call @@ -1180,7 +1180,7 @@ static bool IsMoveable(InterCode code) { if (HasSideEffect(code) || code == IC_COPY || code == IC_STRCPY || code == IC_STORE || code == IC_BRANCH || code == IC_POP_FRAME || code == IC_PUSH_FRAME || code == IC_MALLOC || code == IC_FREE) return false; - if (code == IC_RETURN || code == IC_RETURN_STRUCT || code == IC_RETURN_VALUE) + if (code == IC_RETURN || code == IC_RETURN_STRUCT || code == IC_RETURN_VALUE || code == IC_DISPATCH) return false; return true; @@ -2945,6 +2945,7 @@ InterInstruction::InterInstruction(const Location& loc, InterCode code) case IC_RETURN_VALUE: case IC_RETURN_STRUCT: case IC_CONVERSION_OPERATOR: + case IC_DISPATCH: mNumOperands = 1; break; @@ -3141,7 +3142,7 @@ void InterInstruction::FilterStaticVarsUsage(const GrowingVariableArray& staticV requiredVars += mSrc[1].mVarIndex; } } - else if (mCode == IC_COPY || mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE || mCode == IC_STRCPY) + else if (mCode == IC_COPY || mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE || mCode == IC_STRCPY || mCode == IC_DISPATCH) { requiredVars.OrNot(providedVars); } @@ -3509,7 +3510,7 @@ void InterInstruction::BuildCallerSaveTempSet(NumberSet& requiredTemps, NumberSe if (mDst.mTemp >= 0) requiredTemps -= mDst.mTemp; - if (mCode == IC_CALL || mCode == IC_CALL_NATIVE) + if (mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_DISPATCH) callerSaveTemps |= requiredTemps; for (int i = 0; i < mNumOperands; i++) @@ -3700,7 +3701,7 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(InterCodeBasicBlock* requiredVars.Fill(); storeIns.SetSize(0); } - else if (mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE) + else if (mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE || mCode == IC_DISPATCH) { requiredVars.Fill(); storeIns.SetSize(0); @@ -4322,6 +4323,9 @@ void InterInstruction::Disassemble(FILE* file) case IC_ASSEMBLER: fprintf(file, "JSR"); break; + case IC_DISPATCH: + fprintf(file, "DISPATCH"); + break; case IC_RETURN_VALUE: assert(mNumOperands == 1); fprintf(file, "RETV"); @@ -9640,6 +9644,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& { ins->mCode = IC_LOAD_TEMPORARY; ins->mSrc[0] = lins->mSrc[0]; + ins->mDst.mRange.Limit(ins->mSrc[0].mRange); ins->mNumOperands = 1; assert(ins->mSrc[0].mTemp >= 0); changed = true; @@ -9702,6 +9707,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& assert(lins->mDst.mTemp >= 0); ins->mCode = IC_LOAD_TEMPORARY; ins->mSrc[0] = lins->mDst; + ins->mDst.mRange.Limit(ins->mSrc[0].mRange); ins->mNumOperands = 1; changed = true; } @@ -10091,7 +10097,7 @@ bool InterCodeBasicBlock::CanMoveInstructionDown(int si, int ti) const #if 1 if (ins->mCode == IC_COPY || ins->mCode == IC_PUSH_FRAME || ins->mCode == IC_POP_FRAME || - ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE) + ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE || ins->mCode == IC_DISPATCH) return false; for (int i = si + 1; i < ti; i++) @@ -10153,7 +10159,7 @@ bool InterCodeBasicBlock::CanMoveInstructionBeforeBlock(int ii, const InterInstr #if 1 if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE || ins->mCode == IC_COPY || ins->mCode == IC_PUSH_FRAME || ins->mCode == IC_POP_FRAME || - ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE) + ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE || ins->mCode == IC_DISPATCH) return false; for (int i = 0; i < ii; i++) @@ -10919,7 +10925,7 @@ bool InterCodeBasicBlock::IsLeafProcedure(void) mVisited = true; for (i = 0; i < mInstructions.Size(); i++) - if (mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE) + if (mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE || mInstructions[i]->mCode == IC_DISPATCH) return false; if (mTrueJump && !mTrueJump->IsLeafProcedure()) @@ -11080,6 +11086,8 @@ bool InterCodeBasicBlock::CheckStaticStack(void) else if (!(mInstructions[i]->mSrc[0].mLinkerObject->mFlags & LOBJF_STATIC_STACK)) return false; } + else if (mInstructions[i]->mCode == IC_DISPATCH) + return false; } if (mTrueJump && !mTrueJump->CheckStaticStack()) @@ -14899,7 +14907,7 @@ void InterCodeBasicBlock::CheckValueReturn(void) for (int i = 0; i < mInstructions.Size(); i++) { InterInstruction* ins = mInstructions[i]; - if (ins->mCode == IC_ASSEMBLER) + if (ins->mCode == IC_ASSEMBLER || ins->mCode == IC_DISPATCH) return; else if (ins->mCode == IC_RETURN) mProc->mModule->mErrors->Error(ins->mLocation, EWARN_MISSING_RETURN_STATEMENT, "Missing return statement"); @@ -15242,7 +15250,7 @@ void InterCodeBasicBlock::Disassemble(FILE* file, bool dumpSets) void InterCodeBasicBlock::WarnUnreachable(void) { - if (mNumEntries == 0) + if (mNumEntries == 0 && mProc->mCheckUnreachable) { int i = 0; while (i < mInstructions.Size() && !IsObservable(mInstructions[i]->mCode)) @@ -15262,6 +15270,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false), mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), + mCheckUnreachable(true), mDeclaration(nullptr) { mID = mModule->mProcedures.Size(); @@ -16106,7 +16115,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "print"); + CheckFunc = !strcmp(mIdent->mString, "setspr"); mEntryBlock = mBlocks[0]; @@ -16373,6 +16382,9 @@ void InterCodeProcedure::Close(void) BuildDataFlowSets(); + TempForwarding(); + RemoveUnusedInstructions(); + #if 1 ResetVisited(); mEntryBlock->BuildLocalIntegerRangeSets(mTemporaries.Size(), mLocalVars, mParamVars); @@ -16383,6 +16395,9 @@ void InterCodeProcedure::Close(void) ResetVisited(); } while (mEntryBlock->BuildGlobalIntegerRangeSets(true, mLocalVars, mParamVars)); + TempForwarding(); + RemoveUnusedInstructions(); + do { DisassembleDebug("tq"); @@ -16392,6 +16407,7 @@ void InterCodeProcedure::Close(void) DisassembleDebug("Estimated value range"); + GrowingInstructionPtrArray pipa(nullptr); ResetVisited(); mEntryBlock->LinkerObjectForwarding(pipa); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 8d45c16..b54cee6 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -40,6 +40,7 @@ enum InterCode IC_ASSEMBLER, IC_JUMPF, IC_SELECT, + IC_DISPATCH, IC_UNREACHABLE }; @@ -588,6 +589,7 @@ public: int mTempSize, mCommonFrameSize, mCallerSavedTemps, mFreeCallerSavedTemps, mFastCallBase; bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure; bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack; + bool mCheckUnreachable; GrowingInterCodeProcedurePtrArray mCalledFunctions; InterCodeModule * mModule; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index b909701..bd1a538 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -894,6 +894,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro Expression* fexp = fdec->mValue; Declaration* ftype = fdec->mBase; + proc->mCheckUnreachable = false; + InlineMapper nmapper; nmapper.mReturn = new InterCodeBasicBlock(proc); nmapper.mVarIndex = proc->mNumLocals; @@ -1610,6 +1612,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (inlineMapper) ins->mConst.mVarIndex += inlineMapper->mVarIndex; InitLocalVariable(proc, dec, ins->mConst.mVarIndex); + proc->mCheckUnreachable = false; } else if (inlineMapper) { @@ -2665,6 +2668,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* return ExValue(TheBoolTypeDeclaration, ins->mDst.mTemp); } + case EX_VCALL: case EX_CALL: case EX_INLINE: { @@ -2854,7 +2858,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* bool canInline = exp->mLeft->mType == EX_CONSTANT && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION && (mCompilerOptions & COPT_OPTIMIZE_INLINE) && - !(inlineMapper && inlineMapper->mDepth > 10); + !(inlineMapper && inlineMapper->mDepth > 10) && + exp->mType != EX_VCALL; bool doInline = false, inlineConstexpr = false; if (canInline) @@ -2902,7 +2907,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + Expression * funcexp = exp->mLeft; + + vl = TranslateExpression(procType, proc, block, funcexp, destack, breakBlock, continueBlock, inlineMapper); + vl = Dereference(proc, exp, block, vl); int atotal = 0; @@ -2992,8 +3000,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* atotal = 2; } - if (exp->mLeft->mDecValue && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION) - proc->AddCalledFunction(proc->mModule->mProcedures[exp->mLeft->mDecValue->mVarIndex]); + if (funcexp->mDecValue && funcexp->mDecValue->mType == DT_CONST_FUNCTION) + proc->AddCalledFunction(proc->mModule->mProcedures[funcexp->mDecValue->mVarIndex]); else proc->CallsFunctionPointer(); @@ -3187,15 +3195,15 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block->Append(defins[i]); InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CALL); - if (exp->mLeft->mDecValue && (exp->mLeft->mDecValue->mFlags & DTF_NATIVE)) + if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_NATIVE)) cins->mCode = IC_CALL_NATIVE; else cins->mCode = IC_CALL; - if (exp->mLeft->mDecValue && (exp->mLeft->mDecValue->mFlags & DTF_FUNC_PURE)) + if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_FUNC_PURE)) cins->mNoSideEffects = true; - if (exp->mLeft->mType == EX_CONSTANT && (exp->mLeft->mDecValue->mFlags & DTF_FUNC_CONSTEXPR)) + if (funcexp->mType == EX_CONSTANT && (funcexp->mDecValue->mFlags & DTF_FUNC_CONSTEXPR)) cins->mConstExpr = true; cins->mSrc[0].mType = IT_POINTER; @@ -4059,6 +4067,30 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } break; + case EX_DISPATCH: + { + vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + vl = Dereference(proc, exp, block, vl); + + InterInstruction* ins = new InterInstruction(exp->mLocation, IC_DISPATCH); + ins->mSrc[0].mType = IT_POINTER; + ins->mSrc[0].mTemp = vl.mTemp; + + block->Append(ins); + + Declaration* dinit = exp->mLeft->mLeft->mDecValue->mValue->mDecValue->mParams; + while (dinit) + { + proc->AddCalledFunction(proc->mModule->mProcedures[dinit->mValue->mDecValue->mVarIndex]); + dinit = dinit->mNext; + } + + +// proc->CallsFunctionPointer(); + + return ExValue(TheVoidTypeDeclaration); + } + case EX_WHILE: { DestructStack* odestack = destack; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index de92f06..b0a1fe5 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -27069,11 +27069,6 @@ bool NativeCodeBasicBlock::ReverseBitfieldForwarding(void) return changed; } -struct NativeCodeLoadStorePair -{ - NativeCodeInstruction mLoad, mStore; -}; - bool NativeCodeBasicBlock::RemoveLocalUnusedLinkerObjects(void) { bool changed = false; @@ -27124,7 +27119,7 @@ void NativeCodeBasicBlock::MarkLocalUsedLinkerObjects(void) } } -bool NativeCodeBasicBlock::AbsoluteValueForwarding(void) +bool NativeCodeBasicBlock::AbsoluteValueForwarding(const ExpandingArray & npairs) { bool changed = false; @@ -27133,6 +27128,8 @@ bool NativeCodeBasicBlock::AbsoluteValueForwarding(void) mVisited = true; ExpandingArray pairs; + if (mNumEntries == 1) + pairs = npairs; int ains = -1; @@ -27205,9 +27202,9 @@ bool NativeCodeBasicBlock::AbsoluteValueForwarding(void) } } - if (mTrueJump && mTrueJump->AbsoluteValueForwarding()) + if (mTrueJump && mTrueJump->AbsoluteValueForwarding(pairs)) changed = true; - if (mFalseJump && mFalseJump->AbsoluteValueForwarding()) + if (mFalseJump && mFalseJump->AbsoluteValueForwarding(pairs)) changed = true; } @@ -28674,6 +28671,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc mIns[1].mType = ASMIT_LDA; mIns[1].mLive |= LIVE_CPU_REG_A; mIns[0].mType = ASMIT_CMP; mIns[0].mLive |= LIVE_CPU_REG_Z; prevBlock->mIns.Push(mIns[1]); + prevBlock->mExitRequiredRegs += CPU_REG_A; + mEntryRequiredRegs += CPU_REG_A; mIns.Remove(1); CheckLive(); @@ -37703,7 +37702,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_STX; mIns[i + 1].CopyMode(mIns[i + 3]); - mIns[i + 3].mType = mIns[i + 2].mType; + mIns[i + 3].mType = mIns[i + 2].mType; mIns[i + 3].mLive |= LIVE_CPU_REG_A; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED; progress = true; @@ -37717,7 +37716,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_STY; mIns[i + 1].CopyMode(mIns[i + 3]); - mIns[i + 3].mType = mIns[i + 2].mType; + mIns[i + 3].mType = mIns[i + 2].mType; mIns[i + 3].mLive |= LIVE_CPU_REG_A; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED; progress = true; @@ -40878,7 +40877,8 @@ void NativeCodeProcedure::Optimize(void) if (step == 9) { ResetVisited(); - if (mEntryBlock->AbsoluteValueForwarding()) + ExpandingArray pairs; + if (mEntryBlock->AbsoluteValueForwarding(pairs)) { changed = true; @@ -41889,6 +41889,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode case IC_CONSTANT: block->LoadConstant(iproc, ins); break; + case IC_DISPATCH: case IC_CALL: block->CallFunction(iproc, this, ins); break; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 3cf5e56..6db7ec7 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -207,6 +207,12 @@ public: uint32 NeedsLive(void) const; }; +struct NativeCodeLoadStorePair +{ + NativeCodeInstruction mLoad, mStore; +}; + + class NativeCodeBasicBlock { public: @@ -474,7 +480,7 @@ public: bool BitFieldForwarding(const NativeRegisterDataSet& data); bool ReverseBitfieldForwarding(void); bool OffsetValueForwarding(const ValueNumberingDataSet & data); - bool AbsoluteValueForwarding(void); + bool AbsoluteValueForwarding(const ExpandingArray& npairs); void MarkLocalUsedLinkerObjects(void); bool RemoveLocalUnusedLinkerObjects(void); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index c99c46e..dcedd38 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -64,6 +64,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) Declaration * dec = new Declaration(mScanner->mLocation, dt); + bool needVTable = false; + mScanner->NextToken(); if (mScanner->mToken == TK_IDENT) { @@ -119,6 +121,9 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) bcdec->mBase = pdec; bcdec->mFlags = pflags; + if (pdec->mVTable) + needVTable = true; + dec->mSize = pdec->mSize; dec->mBase = bcdec; @@ -141,109 +146,205 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) } mScanner->NextToken(); - Declaration* mlast = nullptr; - for (;;) + if (ConsumeTokenIf(TK_CLOSE_BRACE)) { - if (ConsumeTokenIf(TK_PUBLIC)) + dec->mParams = nullptr; + } + else + { + Declaration* mlast = nullptr; + for (;;) { - flags &= ~(DTF_PRIVATE | DTF_PROTECTED); - ConsumeToken(TK_COLON); - } - else if (ConsumeTokenIf(TK_PROTECTED)) - { - flags &= ~DTF_PRIVATE; - flags |= DTF_PROTECTED; - ConsumeToken(TK_COLON); - } - else if (ConsumeTokenIf(TK_PRIVATE)) - { - flags |= DTF_PRIVATE | DTF_PROTECTED; - ConsumeToken(TK_COLON); - } - else - { - Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis); - - mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED); - - mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent); - - int offset = dec->mSize; - if (dt == DT_TYPE_UNION) - offset = 0; - - if (mdec->mBase->mType == DT_TYPE_FUNCTION) + if (ConsumeTokenIf(TK_PUBLIC)) { - mdec->mType = DT_CONST_FUNCTION; - mdec->mSection = mCodeSection; - mdec->mFlags |= DTF_GLOBAL; - mdec->mBase->mFlags |= DTF_FUNC_THIS; - - if (mCompilerOptions & COPT_NATIVE) - mdec->mFlags |= DTF_NATIVE; - - if (!(mdec->mFlags & DTF_DEFINED)) - ConsumeToken(TK_SEMICOLON); - - AddMemberFunction(dec, mdec); + flags &= ~(DTF_PRIVATE | DTF_PROTECTED); + ConsumeToken(TK_COLON); + } + else if (ConsumeTokenIf(TK_PROTECTED)) + { + flags &= ~DTF_PRIVATE; + flags |= DTF_PROTECTED; + ConsumeToken(TK_COLON); + } + else if (ConsumeTokenIf(TK_PRIVATE)) + { + flags |= DTF_PRIVATE | DTF_PROTECTED; + ConsumeToken(TK_COLON); } else { - while (mdec) + Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis); + + mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED); + + mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent); + + int offset = dec->mSize; + if (dt == DT_TYPE_UNION) + offset = 0; + + if (mdec->mBase->mType == DT_TYPE_FUNCTION) { - if (!(mdec->mBase->mFlags & DTF_DEFINED)) - mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); + if (mdec->mBase->mFlags & DTF_VIRTUAL) + needVTable = true; - if (mdec->mType != DT_VARIABLE) - { - mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected"); - break; - } + mdec->mType = DT_CONST_FUNCTION; + mdec->mSection = mCodeSection; + mdec->mFlags |= DTF_GLOBAL; + mdec->mBase->mFlags |= DTF_FUNC_THIS; - mdec->mType = DT_ELEMENT; - mdec->mOffset = offset; + if (mCompilerOptions & COPT_NATIVE) + mdec->mFlags |= DTF_NATIVE; - offset += mdec->mBase->mSize; - if (offset > dec->mSize) - dec->mSize = offset; + if (!(mdec->mFlags & DTF_DEFINED)) + ConsumeToken(TK_SEMICOLON); - if (dec->mScope->Insert(mdec->mIdent, mdec)) - mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); - - if (mlast) - mlast->mNext = mdec; - else - dec->mParams = mdec; - mlast = mdec; - mdec = mdec->mNext; + AddMemberFunction(dec, mdec); } - - if (mScanner->mToken == TK_SEMICOLON) - mScanner->NextToken(); else { - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); + while (mdec) + { + if (!(mdec->mBase->mFlags & DTF_DEFINED)) + mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); + + if (mdec->mType != DT_VARIABLE) + { + mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected"); + break; + } + + mdec->mType = DT_ELEMENT; + mdec->mOffset = offset; + + offset += mdec->mBase->mSize; + if (offset > dec->mSize) + dec->mSize = offset; + + if (dec->mScope->Insert(mdec->mIdent, mdec)) + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + + if (mlast) + mlast->mNext = mdec; + else + dec->mParams = mdec; + mlast = mdec; + mdec = mdec->mNext; + } + + if (mScanner->mToken == TK_SEMICOLON) + mScanner->NextToken(); + else + { + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); + break; + } + } + + if (mScanner->mToken == TK_CLOSE_BRACE) + { + mScanner->NextToken(); break; } } - - if (mScanner->mToken == TK_CLOSE_BRACE) - { - mScanner->NextToken(); - break; - } } - } - if (mlast) - mlast->mNext = nullptr; - else - dec->mParams = nullptr; + if (mlast) + mlast->mNext = nullptr; + else + dec->mParams = nullptr; + } dec->SetDefined(); if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mType == DT_TYPE_STRUCT && dec->mIdent) { + if (needVTable) + { + Declaration* vdec = mCompilationUnits->mVTableScope->Lookup(dec->mQualIdent); + if (!vdec) + { + vdec = new Declaration(dec->mLocation, DT_VTABLE); + + if (dec->mBase) + { + vdec->mBase = dec->mBase->mBase->mVTable; + vdec->mSize = vdec->mBase->mSize; + vdec->mOffset = vdec->mBase->mOffset; + } + else + { + Declaration* mdec = dec->mParams; + while (mdec) + { + mdec->mOffset++; + mdec = mdec->mNext; + } + vdec->mOffset = 0; + dec->mSize++; + } + + vdec->mDefaultConstructor = new Declaration(dec->mLocation, DT_CONST_INTEGER); + vdec->mDefaultConstructor->mBase = TheConstCharTypeDeclaration; + vdec->mDefaultConstructor->mSize = 1; + vdec->mDefaultConstructor->mInteger = -1; + + vdec->mClass = dec; + vdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS); + vdec->mIdent = dec->mIdent; + vdec->mQualIdent = dec->mQualIdent; + mCompilationUnits->mVTableScope->Insert(vdec->mQualIdent, vdec); + + dec->mVTable = vdec; + } + + dec->mScope->Iterate([=](const Ident* ident, Declaration* mdec) + { + if (mdec->mType == DT_CONST_FUNCTION) + { + while (mdec) + { + if (mdec->mBase->mFlags & DTF_VIRTUAL) + { + Declaration* vpdec = vdec; + Declaration* vmdec = vpdec->mScope->Lookup(ident); + while (!vmdec && vpdec->mBase) + { + vpdec = vpdec->mBase; + vmdec = vpdec->mScope->Lookup(ident); + } + + Declaration* vmpdec = nullptr; + + while (vmdec && vmdec->mBase->IsSame(mdec->mBase)) + { + vmpdec = vmdec; + vmdec = vmdec->mNext; + } + + if (!vmdec) + { + vmdec = mdec->Clone(); + vmdec->mNext = nullptr; + vmdec->mDefaultConstructor = dec->mVTable; + vmdec->mFlags |= DTF_NATIVE; + + if (vmpdec) + vmpdec->mNext = vmdec; + else + vdec->mScope->Insert(ident, vmdec); + } + + mdec->mVTable = vmdec; + } + + mdec = mdec->mNext; + } + } + } + ); + } + AddDefaultConstructors(pthis); // Lookup constructors, have same name as class @@ -256,6 +357,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) } AppendMemberDestructor(pthis); + } } @@ -1409,6 +1511,31 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) dec = dec->mPrev; } } + + if (pthis->mBase->mVTable) + { + Expression* sexp = new Expression(cfunc->mLocation, EX_SEQUENCE); + sexp->mLeft = cfunc->mValue; + + Expression* vexp = new Expression(pthis->mLocation, EX_QUALIFY); + vexp->mLeft = thisexp; + vexp->mDecValue = new Declaration(pthis->mLocation, DT_ELEMENT); + vexp->mDecValue->mBase = TheCharTypeDeclaration; + vexp->mDecValue->mOffset = pthis->mBase->mVTable->mOffset; + vexp->mDecValue->mSize = 1; + vexp->mDecType = TheCharTypeDeclaration; + + Expression* nexp = new Expression(cfunc->mLocation, EX_INITIALIZATION); + nexp->mToken = TK_ASSIGN; + nexp->mDecType = TheCharTypeDeclaration; + nexp->mLeft = vexp; + nexp->mRight = new Expression(cfunc->mLocation, EX_CONSTANT); + nexp->mRight->mDecType = TheCharTypeDeclaration; + nexp->mRight->mDecValue = pthis->mBase->mVTable->mDefaultConstructor; + + sexp->mRight = nexp; + cfunc->mValue = sexp; + } } void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc) @@ -1492,6 +1619,7 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc) void Parser::AddDefaultConstructors(Declaration* pthis) { bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true; + bool inlineConstructor = true; char dname[100]; strcpy_s(dname, "~"); @@ -1537,7 +1665,11 @@ void Parser::AddDefaultConstructors(Declaration* pthis) if (bcdec->mBase->mDestructor) simpleDestructor = false; if (bcdec->mBase->mDefaultConstructor) + { simpleConstructor = false; + if (!(bcdec->mBase->mDefaultConstructor->mBase->mFlags & DTF_REQUEST_INLINE)) + inlineConstructor = false; + } if (bcdec->mBase->mCopyConstructor) simpleCopy = false; if (bcdec->mBase->mCopyAssignment) @@ -1545,6 +1677,9 @@ void Parser::AddDefaultConstructors(Declaration* pthis) bcdec = bcdec->mNext; } + if (pthis->mBase->mVTable) + simpleConstructor = false; + Declaration* dec = pthis->mBase->mParams; while (dec) { @@ -1561,7 +1696,11 @@ void Parser::AddDefaultConstructors(Declaration* pthis) if (bdec->mDestructor) simpleDestructor = false; if (bdec->mDefaultConstructor) + { simpleConstructor = false; + if (!(bdec->mDefaultConstructor->mBase->mFlags & DTF_REQUEST_INLINE)) + inlineConstructor = false; + } if (bdec->mCopyConstructor) simpleCopy = false; if (bdec->mCopyAssignment) @@ -1616,6 +1755,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) { Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION); ctdec->mSize = 0; + Declaration* pdec = nullptr; ctdec->mBase = TheVoidTypeDeclaration; ctdec->mFlags |= DTF_DEFINED; @@ -1626,6 +1766,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + if (inlineConstructor) + cdec->mFlags |= DTF_REQUEST_INLINE; cdec->mSection = mCodeSection; @@ -2782,7 +2924,12 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { for (;;) { - if (mScanner->mToken == TK_STATIC) + if (mScanner->mToken == TK_VIRTUAL) + { + storageFlags |= DTF_VIRTUAL; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_STATIC) { storageFlags |= DTF_STATIC; mScanner->NextToken(); @@ -3120,7 +3267,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } if (npdec->mBase->mType == DT_TYPE_FUNCTION) - npdec->mBase->mFlags |= storageFlags & (DTF_INTERRUPT | DTF_NATIVE | TK_FASTCALL); + npdec->mBase->mFlags |= storageFlags & (DTF_INTERRUPT | DTF_NATIVE | DTF_FASTCALL | DTF_VIRTUAL); if (definingType) { @@ -3850,9 +3997,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs) mScanner->NextToken(); break; case TK_IDENT: - if (mThisPointer && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION)) + if (mThisPointer && mThisPointer->mType == DT_ARGUMENT && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION)) { - dec = mThisPointer->mBase->mBase->mScope->Lookup(mScanner->mTokenIdent); + int offset; + uint64 flags; + + dec = MemberLookup(mThisPointer->mBase->mBase, mScanner->mTokenIdent, offset, flags); if (dec) { Expression * texp = new Expression(mScanner->mLocation, EX_VARIABLE); @@ -4115,6 +4265,9 @@ Expression* Parser::ParseQualify(Expression* exp) ResolveOverloadCall(nexp->mLeft, nexp->mRight); nexp->mDecType = nexp->mLeft->mDecType->mBase; + if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL) + nexp->mType = EX_VCALL; + exp = nexp; } } @@ -4408,6 +4561,9 @@ Expression* Parser::ParsePostfixExpression(bool lhs) ResolveOverloadCall(exp, nexp->mRight); nexp->mDecType = exp->mDecType->mBase; + if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL) + nexp->mType = EX_VCALL; + exp = nexp; } } @@ -4593,6 +4749,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); sexp->mLeft = iexp; sexp->mRight = coexp; + sexp->mDecType = coexp->mDecType; nexp = sexp; } @@ -4653,6 +4810,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) sexp->mLeft = dexp; sexp->mRight = vexp; + sexp->mDecType = vexp->mDecType; Expression * coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); @@ -4670,6 +4828,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) nexp = new Expression(mScanner->mLocation, EX_SEQUENCE); nexp->mLeft = iexp; nexp->mRight = coexp; + nexp->mDecType = coexp->mDecType; } } } @@ -7337,6 +7496,10 @@ void Parser::ParsePragma(void) mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE; else if (ConsumeIdentIf("maxinline")) mCompilerOptions |= COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL; + else if (ConsumeIdentIf("constparams")) + mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS; + else if (ConsumeIdentIf("noconstparams")) + mCompilerOptions &= ~COPT_OPTIMIZE_CONST_PARAMS; else mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid option"); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index a072620..b27e571 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -160,6 +160,7 @@ const char* TokenNames[] = "'private'", "'new'", "'delete'", + "'virtual'", }; @@ -1412,6 +1413,8 @@ void Scanner::NextRawToken(void) mToken = TK_NEW; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "delete")) mToken = TK_DELETE; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "virtual")) + mToken = TK_VIRTUAL; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 580c5ee..580ef40 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -159,6 +159,7 @@ enum Token TK_PRIVATE, TK_NEW, TK_DELETE, + TK_VIRTUAL, NUM_TOKENS }; diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 18aa475..18bcde9 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.21.209"); + strcpy(strProductVersion, "1.22.210"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); @@ -202,6 +202,8 @@ int main2(int argc, const char** argv) compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE; else if (arg[2] == 'z') compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_ZEROPAGE; + else if (arg[2] == 'p') + compiler->mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS; } else if (arg[1] == 'e') { diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index abb5828..3dca3fd 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,21,209,0 - PRODUCTVERSION 1,21,209,0 + FILEVERSION 1,22,210,0 + PRODUCTVERSION 1,22,210,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.21.209.0" + VALUE "FileVersion", "1.22.210.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.21.209.0" + VALUE "ProductVersion", "1.22.210.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 9350e86..6d0410c 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5296,15 +5296,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{30BEED33-B5ED-4443-B82C-B365168D7780}" - "PackageCode" = "8:{46BC17E9-3B6D-4E1E-A1E7-42B0AD7512D8}" + "ProductCode" = "8:{9E7AB7F5-BA83-4377-B177-3D121EF176EB}" + "PackageCode" = "8:{2B7BCA1C-B5B7-47D2-8A8A-A8C694463BE0}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.21.209" + "ProductVersion" = "8:1.22.210" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" diff --git a/samples/sprites/sprmux64.c b/samples/sprites/sprmux64.c index 8191f0b..09099c2 100644 --- a/samples/sprites/sprmux64.c +++ b/samples/sprites/sprmux64.c @@ -100,7 +100,7 @@ __interrupt void setspr(void) // Wait for end of current sprite, xpos will take effect // at start of line, so we need to patch it after the last // pixel line has started - vic_waitLine(yoffset - 4); + vic_waitLine(yoffset - 3); // Left to right or right to left to get a matching z order if (phase & 0x80) From a46cf3a0d3b07a7ad6723d3c219ed56a530ff354 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 8 Jul 2023 22:04:55 +0200 Subject: [PATCH 030/169] Add virtual destructor --- autotest/autotest.bat | 3 ++ autotest/virtualdestruct.cpp | 63 ++++++++++++++++++++++++++++++++++++ oscar64/Ident.cpp | 8 +++++ oscar64/Ident.h | 1 + oscar64/Parser.cpp | 50 ++++++++++++++++++++++++++-- 5 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 autotest/virtualdestruct.cpp diff --git a/autotest/autotest.bat b/autotest/autotest.bat index f6aca82..48958b2 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -1,5 +1,8 @@ rem @echo off +@call :test virtualdestruct.cpp +@if %errorlevel% neq 0 goto :error + @call :test vcalltest.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/virtualdestruct.cpp b/autotest/virtualdestruct.cpp new file mode 100644 index 0000000..a9bd394 --- /dev/null +++ b/autotest/virtualdestruct.cpp @@ -0,0 +1,63 @@ +#include + +int a, b, c; + +struct A +{ + A(void) + { + a++; + } + + virtual ~A(void) + { + a--; + } +}; + +struct B : A +{ + B(void) + { + b++; + } + + virtual ~B(void) + { + b--; + } +}; + + +struct C : B +{ + C(void) + { + c++; + } + + virtual ~C(void) + { + c--; + } +}; + + +int main() +{ + A * t[3]; + + t[0] = new A(); + t[1] = new B(); + t[2] = new C(); + + assert(a == 3 && b == 2 && c == 1); + + delete t[0]; + delete t[1]; + delete t[2]; + + assert(a == 0 && b == 0 && c == 0); + + return 0; +} diff --git a/oscar64/Ident.cpp b/oscar64/Ident.cpp index daabd53..29e89f6 100644 --- a/oscar64/Ident.cpp +++ b/oscar64/Ident.cpp @@ -45,6 +45,14 @@ const Ident* Ident::Unique(const char* str) } +const Ident* Ident::PreMangle(const char* str) const +{ + char buffer[100]; + strcpy_s(buffer, str); + strcat_s(buffer, mString); + return Unique(buffer); +} + const Ident* Ident::Mangle(const char* str) const { char buffer[100]; diff --git a/oscar64/Ident.h b/oscar64/Ident.h index 661c83c..de44870 100644 --- a/oscar64/Ident.h +++ b/oscar64/Ident.h @@ -10,6 +10,7 @@ public: static const Ident* Unique(const char* str); const Ident* Mangle(const char* str) const; + const Ident* PreMangle(const char* str) const; protected: Ident(const char* str, unsigned int hash); }; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index dcedd38..e0e6013 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -307,11 +307,26 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mdec->mBase->mFlags & DTF_VIRTUAL) { Declaration* vpdec = vdec; - Declaration* vmdec = vpdec->mScope->Lookup(ident); - while (!vmdec && vpdec->mBase) + Declaration* vmdec; + if (mdec->mIdent->mString[0] == '~') + { + // this is the destructor, need special search + + vmdec = vpdec->mScope->Lookup(vpdec->mIdent->PreMangle("~")); + while (!vmdec && vpdec->mBase) + { + vpdec = vpdec->mBase; + vmdec = vpdec->mScope->Lookup(vpdec->mIdent->PreMangle("~")); + } + } + else { - vpdec = vpdec->mBase; vmdec = vpdec->mScope->Lookup(ident); + while (!vmdec && vpdec->mBase) + { + vpdec = vpdec->mBase; + vmdec = vpdec->mScope->Lookup(ident); + } } Declaration* vmpdec = nullptr; @@ -2585,6 +2600,31 @@ void Parser::AppendMemberDestructor(Declaration* pthis) dec = dec->mPrev; } } + + Declaration* bcdec = pthis->mBase->mBase; + while (bcdec) + { + if (bcdec->mBase->mDestructor) + { + Declaration* mdec = bcdec->mBase->mDestructor; + + Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pthisexp; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = pthis->mBase->mDestructor->mValue; + sexp->mRight = dexp; + pthis->mBase->mDestructor->mValue = sexp; + } + + bcdec = bcdec->mNext; + } } } } @@ -3018,6 +3058,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + ctdec->mFlags |= storageFlags & DTF_VIRTUAL; cdec->mSection = mCodeSection; cdec->mBase->mFlags |= typeFlags; @@ -4904,6 +4945,9 @@ Expression* Parser::ParsePrefixExpression(bool lhs) dexp->mLeft = cexp; dexp->mRight = pexp; + if (cexp->mDecValue->mBase->mFlags & DTF_VIRTUAL) + dexp->mType = EX_VCALL; + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); sexp->mLeft = iexp; sexp->mRight = new Expression(mScanner->mLocation, EX_IF); From 0bab98ccc6d9a36edf284c194f7b2c1e6c1b5ff7 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 8 Jul 2023 22:20:42 +0200 Subject: [PATCH 031/169] Optimize short signed table access --- oscar64/InterCode.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 874252d..ff056cf 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -6376,12 +6376,16 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray { if (ins->mDst.mType == IT_INT8) { - bool isUnsigned = false; - if (i + 1 < mInstructions.Size() && mInstructions[i + 1]->mCode == IC_CONVERSION_OPERATOR && mInstructions[i + 1]->mOperator == IA_EXT8TO16U && - mInstructions[i + 1]->mSrc[0].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mFinal) - isUnsigned = true; + bool isUnsigned = false, isSigned = false; + if (i + 1 < mInstructions.Size() && mInstructions[i + 1]->mCode == IC_CONVERSION_OPERATOR && mInstructions[i + 1]->mSrc[0].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mFinal) + { + if (mInstructions[i + 1]->mOperator == IA_EXT8TO16U) + isUnsigned = true; + else if (mInstructions[i + 1]->mOperator == IA_EXT8TO16S) + isSigned = true; + } - int mi = 0, ma = 0; + int mi = 255, ma = 0; if (vr.mMinState == IntegerValueRange::S_BOUND && vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMinValue >= -128 && vr.mMaxValue <= 127) @@ -6400,8 +6404,15 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray for (int j = 0; j < lo->mSize; j++) { int v = lo->mData[j]; - if (!isUnsigned && (v & 0x80)) + if (isUnsigned) + ; + else if (isSigned) + v = (int8)v; + else if (v & 0x80) mi = -128; + + if (v < mi) + mi = v; if (v > ma) ma = v; } From 66631c915b0c105d4cb87d1d35f6e6a444a3a05c Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 9 Jul 2023 10:52:11 +0200 Subject: [PATCH 032/169] Prefix and inc operator overload --- autotest/autotest.bat | 3 + autotest/operatoroverload.cpp | 90 ++++++++++++++ oscar64/Parser.cpp | 215 +++++++++++++++++++++++++++++++++- oscar64/Scanner.cpp | 7 ++ 4 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 autotest/operatoroverload.cpp diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 48958b2..0dbf0f6 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -1,5 +1,8 @@ rem @echo off +@call :test operatoroverload.cpp +@if %errorlevel% neq 0 goto :error + @call :test virtualdestruct.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/operatoroverload.cpp b/autotest/operatoroverload.cpp new file mode 100644 index 0000000..93c02bb --- /dev/null +++ b/autotest/operatoroverload.cpp @@ -0,0 +1,90 @@ +#include + +struct A +{ + int n; + + A(int n_) + : n(n_) {} + + A(const A & a) + : n(a.n) {} + + A operator+(const A & a) const + { + return A(n + a.n); + } + + A operator-(const A & a) const + { + return A(n - a.n); + } + + A & operator+=(const A & a) + { + n += a.n; + return *this; + } + + A & operator-=(const A & a) + { + n -= a.n; + return *this; + } + + A operator-(void) const + { + return A(-n); + } + + A & operator++(void) + { + n++; + return *this; + } + + A & operator--(void) + { + n--; + return *this; + } + + A operator++(int); + + A operator--(int); + +}; + +A A::operator++(int) +{ + A a(*this); + n++; + return a; +} + +A A::operator--(int) +{ + A a(*this); + n--; + return a; +} + +int main(void) +{ + A a(7), b(8), c(9); + + assert((++a).n == 8); + assert(a.n == 8); + + assert((--a).n == 7); + assert(a.n == 7); + + assert((a++).n == 7); + assert(a.n == 8); + assert((a--).n == 8); + assert(a.n == 7); + + assert((a + b - c + -a + -b - -c).n == 0); + + return 0; +} diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index e0e6013..cb9c3fa 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2693,7 +2693,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) { Expression* lexp = nullptr, * rexp = nullptr; - if (exp->mType == EX_PREFIX && exp->mToken == TK_BINARY_AND && exp->mLeft->mType == EX_CALL) + if (exp->mType == EX_PREFIX && exp->mToken == TK_BINARY_AND && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE) { lexp = AddFunctionCallRefReturned(exp->mLeft); @@ -2714,7 +2714,58 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) vexp->mDecType = rtdec; vexp->mDecValue = vdec; - Expression * pex = new Expression(exp->mLocation, EX_INITIALIZATION); + Expression* pex = new Expression(exp->mLocation, EX_INITIALIZATION); + pex->mToken = TK_ASSIGN; + pex->mLeft = vexp; + pex->mRight = exp->mLeft; + pex->mDecValue = nullptr; + pex->mDecType = vdec->mBase; + + exp->mLeft = pex; + + if (rtdec->mDestructor) + { + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = vdec->mBase; + texp->mDecType->mSize = 2; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = rtdec->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + + rexp = ConcatExpression(rexp, dexp); + } + } + else if (exp->mType == EX_QUALIFY && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE) + { + lexp = AddFunctionCallRefReturned(exp->mLeft); + + // Returning a value object for pass by address + // add a temporary variable + + int nindex = mLocalIndex++; + + Declaration* rtdec = exp->mLeft->mDecType; + + Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + vdec->mVarIndex = nindex; + vdec->mBase = rtdec; + vdec->mSize = rtdec->mSize; + + Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE); + vexp->mDecType = rtdec; + vexp->mDecValue = vdec; + + Expression* pex = new Expression(exp->mLocation, EX_INITIALIZATION); pex->mToken = TK_ASSIGN; pex->mLeft = vexp; pex->mRight = exp->mLeft; @@ -4614,8 +4665,8 @@ Expression* Parser::ParsePostfixExpression(bool lhs) nexp->mToken = mScanner->mToken; nexp->mLeft = exp; nexp->mDecType = exp->mDecType; - exp = nexp; mScanner->NextToken(); + exp = CheckOperatorOverload(nexp); } else if (mScanner->mToken == TK_ARROW) { @@ -4698,6 +4749,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) mScanner->NextToken(); nexp->mLeft = ParsePrefixExpression(false);; nexp->mDecType = nexp->mLeft->mDecType; + nexp = CheckOperatorOverload(nexp); } else if (mScanner->mToken == TK_NEW) { @@ -5002,6 +5054,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) else nexp->mDecType = nexp->mLeft->mDecType; } + nexp = CheckOperatorOverload(nexp); return nexp->ConstantFold(mErrors); } else @@ -5384,6 +5437,108 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) } } } + else if (exp->mType == EX_PREINCDEC) + { + const Ident* opident = nullptr; + switch (exp->mToken) + { + case TK_INC: + opident = Ident::Unique("operator++"); + break; + case TK_DEC: + opident = Ident::Unique("operator--"); + break; + } + + if (opident) + { + Declaration* tdec = exp->mLeft->mDecType; + if (tdec->mType == DT_TYPE_STRUCT) + { + Declaration* mdec = tdec->mScope->Lookup(opident); + if (mdec) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_CALL); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + nexp->mRight = exp->mRight; + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp->mLeft; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = exp->mLeft->mDecType; + texp->mDecType->mSize = 2; + + nexp->mRight = texp; + + ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + + exp = nexp; + } + } + } + } + else if (exp->mType == EX_POSTINCDEC) + { + const Ident* opident = nullptr; + switch (exp->mToken) + { + case TK_INC: + opident = Ident::Unique("operator++"); + break; + case TK_DEC: + opident = Ident::Unique("operator--"); + break; + } + + if (opident) + { + Declaration* tdec = exp->mLeft->mDecType; + if (tdec->mType == DT_TYPE_STRUCT) + { + Declaration* mdec = tdec->mScope->Lookup(opident); + if (mdec) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_CALL); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + nexp->mRight = exp->mRight; + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp->mLeft; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = exp->mLeft->mDecType; + texp->mDecType->mSize = 2; + + Expression* lexp = new Expression(nexp->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = new Expression(nexp->mLocation, EX_CONSTANT); + lexp->mRight->mDecType = TheSignedIntTypeDeclaration; + lexp->mRight->mDecValue = new Declaration(nexp->mLocation, DT_CONST_INTEGER); + lexp->mRight->mDecValue->mBase = TheSignedIntTypeDeclaration; + nexp->mRight = lexp; + + ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + + exp = nexp; + } + } + } + } else if (exp->mType == EX_BINARY || exp->mType == EX_RELATIONAL) { const Ident* opident = nullptr; @@ -5472,6 +5627,60 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) ResolveOverloadCall(nexp->mLeft, nexp->mRight); nexp->mDecType = nexp->mLeft->mDecType->mBase; + exp = nexp; + } + } + } + } + else if (exp->mType == EX_PREFIX) + { + const Ident* opident = nullptr; + switch (exp->mToken) + { + case TK_ADD: + opident = Ident::Unique("operator+"); + break; + case TK_SUB: + opident = Ident::Unique("operator-"); + break; + case TK_MUL: + opident = Ident::Unique("operator*"); + break; + case TK_BINARY_NOT: + opident = Ident::Unique("operator~"); + break; + } + + if (opident) + { + Declaration* tdec = exp->mLeft->mDecType; + if (tdec->mType == DT_TYPE_STRUCT) + { + Declaration* mdec = tdec->mScope->Lookup(opident); + if (mdec) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_CALL); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + nexp->mRight = exp->mRight; + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp->mLeft; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = exp->mLeft->mDecType; + texp->mDecType->mSize = 2; + + nexp->mRight = texp; + + ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + exp = nexp; } } diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index b27e571..06bc2fb 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1507,6 +1507,13 @@ void Scanner::NextRawToken(void) mTokenIdent = Ident::Unique("operator<="); break; + case TK_INC: + mTokenIdent = Ident::Unique("operator++"); + break; + case TK_DEC: + mTokenIdent = Ident::Unique("operator--"); + break; + case TK_OPEN_BRACKET: NextRawToken(); if (mToken != TK_CLOSE_BRACKET) From 00ded29b35130192293c7861d4a8963419cdfda7 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 9 Jul 2023 21:35:49 +0200 Subject: [PATCH 033/169] Improve opp string library --- autotest/autotest.bat | 3 + autotest/opp_string.cpp | 96 +++++++ include/opp/string.cpp | 435 ++++++++++++++++++++++++++++---- include/opp/string.h | 34 ++- include/stdlib.c | 16 ++ include/stdlib.h | 2 + oscar64/InterCode.cpp | 5 +- oscar64/InterCodeGenerator.cpp | 4 +- oscar64/NativeCodeGenerator.cpp | 43 +++- 9 files changed, 583 insertions(+), 55 deletions(-) create mode 100644 autotest/opp_string.cpp diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 0dbf0f6..c18d90d 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -1,5 +1,8 @@ rem @echo off +@call :test opp_string.cpp +@if %errorlevel% neq 0 goto :error + @call :test operatoroverload.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/opp_string.cpp b/autotest/opp_string.cpp new file mode 100644 index 0000000..8df38de --- /dev/null +++ b/autotest/opp_string.cpp @@ -0,0 +1,96 @@ +#include +#include +#include +#include + +static const char HelloWorld[] = "Hello World"; +static const char AndBeyond[] = "And Beyond"; +static const char And[] = "And"; +static const char HelloWorldAndBeyond[] = "Hello World And Beyond"; + +void test_create(void) +{ + string s1(); + string s2(HelloWorld); + string s3(s2); + string s4('a'); + + assert(!strcmp(s2.tocstr(), HelloWorld)); + assert(!strcmp(s3.tocstr(), HelloWorld)); + assert(s4.size() == 1 && s4[0] == 'a'); +} + +void test_concat(void) +{ + string s1(); + string s2(HelloWorld); + string s3(AndBeyond); + + string s4 = s1 + s2; + string s5 = s2 + " " + s3; + string s6 = s2 + " " + AndBeyond; + + assert(!strcmp(s4.tocstr(), HelloWorld)); + assert(!strcmp(s5.tocstr(), HelloWorldAndBeyond)); + assert(!strcmp(s6.tocstr(), HelloWorldAndBeyond)); +} + +__noinline void test_find(void) +{ + string s1(HelloWorldAndBeyond); + string s2(And); + + assert(s1.find(HelloWorld) == 0); + assert(s1.find(AndBeyond) == 12); + assert(s1.find(And) == 12); + assert(s1.find(s2) == 12); + + assert(s1.find(' ') == 5); + assert(s1.find(' ', 6) == 11); +} + +void test_assign(void) +{ + string s1(HelloWorld); + string s2(AndBeyond); + string s3; + s3 = s1; + s3 = s2; + s3 = s1; + s3 += " "; + s3 += s2; + + assert(!strcmp(s3.tocstr(), HelloWorldAndBeyond)); + + s3 <<= 12; + + assert(!strcmp(s3.tocstr(), AndBeyond)); + + s3 = HelloWorldAndBeyond; + + assert(!strcmp(s3.tocstr(), HelloWorldAndBeyond)); + + s3 >>= 11; + + assert(!strcmp(s3.tocstr(), HelloWorld)); +} + +int main(void) +{ + char * p = new char; + unsigned avail = heapfree(); + + test_create(); + assert(avail == heapfree()); + + test_concat(); + assert(avail == heapfree()); + + test_find(); + assert(avail == heapfree()); + + test_assign(); + assert(avail == heapfree()); + + return 0; +} diff --git a/include/opp/string.cpp b/include/opp/string.cpp index b64136f..f5468d6 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -2,26 +2,53 @@ #include #include +static inline void smemcpy(char * dp, const char * sp, char s) +{ + for(char i=0; i 0 && cstr) + { + if (n >= cstr[0]) + { + free(cstr); + cstr = nullptr; + } + else + { + char i = 1; + n++; + while (cstr[n]) + cstr[i++] = cstr[n++]; + cstr[i] = 0; + cstr[0] = i - 1; + } + } + return *this; +} + +string & string::operator>>=(char n) +{ + if (n > 0 && cstr) + { + if (n >= cstr[0]) + { + free(cstr); + cstr = nullptr; + } + else + { + cstr[0] -= n; + cstr[n + 1] = 0; + } + } + return *this; +} + +string string::operator<<(char n) const +{ + if (n > 0 && cstr) + { + if (n >= cstr[0]) + return string(); + else + { + + } + } + else + return *this; +} + +string string::operator>>(char n) const +{ + +} + +static int scmp(const char * s1, const char * s2) +{ + char n = 0; + while (s1[n]) + { + if (s1[n] != s2[n]) + return s1[n] - s2[n]; + n++; + } + return 0; +} inline bool string::operator==(const string & s) const { - return strcmp(cstr, s.cstr) == 0; + if (cstr && s.cstr) + return scmp(cstr + 1, s.cstr + 1) == 0; + else + return !cstr && !s.cstr; } inline bool string::operator==(const char * s) const { - return strcmp(cstr, s) == 0; + if (cstr) + return scmp(cstr + 1, s) == 0; + else + return s[0] == 0; } inline bool string::operator!=(const string & s) const { - return strcmp(cstr, s.cstr) != 0; + if (cstr && s.cstr) + return scmp(cstr + 1, s.cstr + 1) != 0; + else + return cstr || s.cstr; } inline bool string::operator!=(const char * s) const { - return strcmp(cstr, s) == 0; + if (cstr) + return scmp(cstr + 1, s) == 0; + else + return s[0] != 0; } inline bool string::operator<(const string & s) const { - return strcmp(cstr, s.cstr) < 0; + if (cstr && s.cstr) + return scmp(cstr + 1, s.cstr + 1) < 0; + else + return s.cstr; } inline bool string::operator<(const char * s) const { - return strcmp(cstr, s) < 0; + if (cstr) + return scmp(cstr + 1, s) < 0; + else + return s[0] != 0; } inline bool string::operator<=(const string & s) const { - return strcmp(cstr, s.cstr) <= 0; + if (cstr && s.cstr) + return scmp(cstr + 1, s.cstr + 1) <= 0; + else + return !cstr || s.cstr; } inline bool string::operator<=(const char * s) const { - return strcmp(cstr, s) <= 0; + if (cstr) + return scmp(cstr + 1, s) <= 0; + else + return true; } inline bool string::operator>(const string & s) const { - return strcmp(cstr, s.cstr) > 0; + if (cstr && s.cstr) + return scmp(cstr + 1, s.cstr + 1) > 0; + else + return cstr; } inline bool string::operator>(const char * s) const { - return strcmp(cstr, s) > 0; + if (cstr) + return scmp(cstr + 1, s) > 0; + else + return false; } inline bool string::operator>=(const string & s) const { - return strcmp(cstr, s.cstr) >= 0; + if (cstr && s.cstr) + return scmp(cstr + 1, s.cstr + 1) >= 0; + else + return cstr || !s.cstr; } inline bool string::operator>=(const char * s) const { - return strcmp(cstr, s) >= 0; + if (cstr) + return scmp(cstr + 1, s) >= 0; + else + return s[0] == 0; } -inline char & string::operator[](unsigned t) +inline char & string::operator[](char t) { - return cstr[t]; + return cstr[t + 1]; } -inline char string::operator[](unsigned t) const +inline char string::operator[](char t) const { - return cstr[t]; + return cstr[t + 1]; +} + +string string::substr(char pos, char len) const +{ + if (!cstr || len == 0 || pos >= cstr[0]) + return string; + else + { + char l = cstr[0]; + if (pos + len > l) + len = l - pos; + + char * p = malloc(len + 2); + memcpy(p + 1, cstr + 1 + pos, len); + return string(len, p); + } +} + +inline int string::find(const string & s) const +{ + return find(s, 0); +} + +inline int string::find(const char * s) const +{ + return find(s, 0); +} + +inline int string::find(char c) const +{ + return find(c, 0); +} + +int string::find(const string & s, char pos) const +{ + if (!s.cstr) + return pos; + if (cstr) + { + char l = cstr[0]; + char sl = s.cstr[0]; + if (sl <= l) + { + l -= sl; + + while (pos <= l) + { + char i = 1; + while (s.cstr[i] && s.cstr[i] == cstr[pos + i]) + i++; + if (!s.cstr[i]) + return pos; + pos++; + } + } + } + + return -1; +} + +int string::find(const char * s, char pos) const +{ + if (cstr) + { + char l = cstr[0]; + char sl = strlen(s); + if (sl <= l) + { + l -= sl; + + while (pos <= l) + { + char i = 0; + while (s[i] && s[i] == cstr[pos + i + 1]) + i++; + if (!s[i]) + return pos; + pos++; + } + } + } + + return -1; +} + +int string::find(char c, char pos) const +{ + if (cstr) + { + char l = cstr[0]; + while (pos < l) + { + if (cstr[pos + 1] == c) + return pos; + pos++; + } + } + + return -1; } diff --git a/include/opp/string.h b/include/opp/string.h index bde2f0a..ac4f784 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -9,20 +9,28 @@ private: public: string(void); string(const string & s); - string(const char * s); - string(const char * s1, const char * s2); + __noinline string(const char * s); + string(char c); ~string(void); unsigned size(void) const; - + string & operator=(const string & s); string & operator=(const char * s); string & operator+=(const string & s); string & operator+=(const char * s); + string & operator+=(char c); - string operator+(const string & s); - string operator+(const char * s); + string operator+(const string & s) const; + string operator+(const char * s) const; + string operator+(char c) const; + + string & operator<<=(char n); + string & operator>>=(char n); + + string operator<<(char n) const; + string operator>>(char n) const; bool operator==(const string & s) const; bool operator==(const char * s) const; @@ -39,10 +47,22 @@ public: bool operator>=(const string & s) const; bool operator>=(const char * s) const; - char & operator[](unsigned t); - char operator[](unsigned t) const; + char & operator[](char t); + char operator[](char t) const; const char * tocstr(void) const; + + string substr(char pos, char len) const; + + int find(const string & s) const; + int find(const char * s) const; + int find(char c) const; + + int find(const string & s, char pos) const; + int find(const char * s, char pos) const; + int find(char c, char pos) const; +protected: + string(char l, char * b); }; #pragma compile("string.cpp") diff --git a/include/stdlib.c b/include/stdlib.c index a181c0a..7b5709e 100644 --- a/include/stdlib.c +++ b/include/stdlib.c @@ -524,6 +524,22 @@ void exit(int status) } } +extern struct Heap { + Heap * next, * end; +} HeapNode; + +unsigned heapfree(void) +{ + unsigned avail = 0; + Heap * h = HeapNode.next; + while (h) + { + avail += (h->end - h) * sizeof(Heap); + h = h->next; + } + return avail; +} + #if 0 struct Heap { unsigned int size; diff --git a/include/stdlib.h b/include/stdlib.h index 7384454..4d4eac5 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -43,6 +43,8 @@ void free(void * ptr); void * calloc(int num, int size); +unsigned heapfree(void); + unsigned int rand(void); void srand(unsigned int seed); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index ff056cf..91b1108 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4428,6 +4428,9 @@ void InterCodeBasicBlock::Append(InterInstruction * code) assert(code->mSrc[1].mType != IT_POINTER); } + for (int i = 0; i < code->mNumOperands; i++) + assert(code->mSrc[i].mType != IT_NONE); + assert(!(code->mInUse)); code->mInUse = true; this->mInstructions.Push(code); @@ -16126,7 +16129,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "setspr"); + CheckFunc = !strcmp(mIdent->mString, "test_find"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index bd1a538..8908ed9 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1007,8 +1007,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro InterInstruction* wins = new InterInstruction(texp->mLocation, IC_STORE); wins->mSrc[1].mMemory = IM_INDIRECT; - wins->mSrc[0].mType = InterTypeOf(vr.mType);; + wins->mSrc[0].mType = vr.mReference > 0 ? IT_POINTER : InterTypeOf(vr.mType); wins->mSrc[0].mTemp = vr.mTemp; + assert(wins->mSrc[0].mType != IT_NONE); wins->mSrc[1].mType = IT_POINTER; wins->mSrc[1].mTemp = ains->mDst.mTemp; if (pdec) @@ -3195,6 +3196,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block->Append(defins[i]); InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CALL); + cins->mNumOperands = 1; if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_NATIVE)) cins->mCode = IC_CALL_NATIVE; else diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index b0a1fe5..95f6dcc 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -28951,7 +28951,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc i++; while (i < mIns.Size() && !mIns[i].ReferencesZeroPage(mIns[si].mAddress)) i++; - if (i < mIns.Size() && (mIns[i].mType == ASMIT_DEC || mIns[i].mType == ASMIT_INC)) + if (i < mIns.Size() && (mIns[i].mType == ASMIT_DEC || mIns[i].mType == ASMIT_INC) && (!(mIns[ei].mLive & LIVE_CPU_REG_Z) || mIns[ei].ChangesAccuAndFlag())) { int j = i + 1; while (j < mIns.Size() && !mIns[j].ReferencesZeroPage(mIns[si].mAddress)) @@ -28961,6 +28961,9 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc // So we have an LDX from ZP, and exactly one INC/DECof this ZP and X never changes in the loop if (!prevBlock) return OptimizeSimpleLoopInvariant(proc, full); + + bool needRecheck = mIns[ei].mLive & LIVE_CPU_REG_Z; + prevBlock->mIns.Push(mIns[si]); exitBlock->mIns.Insert(0, NativeCodeInstruction(mIns[si].mIns, ASMIT_STX, mIns[si])); mIns[si].mType = ASMIT_NOP; @@ -28975,6 +28978,12 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED; + if (needRecheck) + { + mIns[ei].mLive |= LIVE_CPU_REG_A; + mIns.Insert(ei + 1, NativeCodeInstruction(mIns[ei].mIns, ASMIT_ORA, ASMIM_IMMEDIATE, 0)); + } + mIns.Insert(ei + 1, NativeCodeInstruction(mIns[i].mIns, t)); for (int i = 0; i < mIns.Size(); i++) @@ -31171,6 +31180,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) NativeCodeBasicBlock* block = lblocks[i]; int yoffset = 0, xoffset = 0, aoffset = 0; + int yskew = 0, xskew = 0; for (int j = 0; j < block->mIns.Size(); j++) { @@ -31189,6 +31199,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) zareg[ins.mAddress] = -1; } yoffset = 0; + yskew = 0; zareg[CPU_REG_Y] = -1; break; case ASMIT_LDX: @@ -31202,6 +31213,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) zareg[ins.mAddress] = -1; } xoffset = 0; + xskew = 0; zareg[CPU_REG_X] = -1; break; case ASMIT_STY: @@ -31235,13 +31247,35 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) zareg[CPU_REG_X] = -1; break; case ASMIT_INC: + if (ins.mMode == ASMIM_ZERO_PAGE) + { + if (zxreg[ins.mAddress] >= 0) + { + zxreg[ins.mAddress] += 3; + xskew++; + } + if (zyreg[ins.mAddress] >= 0) + { + zyreg[ins.mAddress] += 3; + yskew++; + } + + zareg[ins.mAddress] = -1; + } + break; case ASMIT_DEC: if (ins.mMode == ASMIM_ZERO_PAGE) { if (zxreg[ins.mAddress] >= 0) + { zxreg[ins.mAddress] += 3; + xskew--; + } if (zyreg[ins.mAddress] >= 0) + { zyreg[ins.mAddress] += 3; + yskew--; + } zareg[ins.mAddress] = -1; } @@ -31335,6 +31369,11 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) areg = -2; } + if (xreg >= 0 && ins.mMode == ASMIM_ABSOLUTE_X && xskew != xoffset) + zxreg[xreg] = -1; + if (yreg >= 0 && (ins.mMode == ASMIM_ABSOLUTE_Y || ins.mMode == ASMIM_INDIRECT_Y) && yskew != yoffset) + zyreg[yreg] = -1; + if (!(ins.mLive & LIVE_CPU_REG_Y)) yoffset = 0; if (!(ins.mLive & LIVE_CPU_REG_X)) @@ -40154,7 +40193,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "heapcheck"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "test_find"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; From 6178bb1f9dac557c3cf3651c16c76dfe2db57c64 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 10 Jul 2023 22:12:41 +0200 Subject: [PATCH 034/169] Shortcut jump cascades --- include/opp/string.cpp | 42 ++++++++++++--------- oscar64/InterCode.cpp | 21 +++++++++-- oscar64/InterCodeGenerator.cpp | 27 ++++++++++++- oscar64/NativeCodeGenerator.cpp | 67 ++++++++++++++++++++++++++++++++- oscar64/NativeCodeGenerator.h | 1 + oscar64/Parser.cpp | 20 +++++----- oscar64/Parser.h | 2 +- 7 files changed, 146 insertions(+), 34 deletions(-) diff --git a/include/opp/string.cpp b/include/opp/string.cpp index f5468d6..5c15b2e 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -8,6 +8,14 @@ static inline void smemcpy(char * dp, const char * sp, char s) dp[i] = sp[i]; } +static inline char sstrlen(const char * sp) +{ + char n = 0; + while (sp[n]) + n++; + return n; +} + string::string(void) : cstr(nullptr) {} @@ -16,7 +24,7 @@ string::string(const string & s) if (s.cstr) { char l = s.cstr[0]; - cstr = malloc(l + 2); + cstr = malloc(char(l + 2)); smemcpy(cstr, s.cstr, l + 2); } else @@ -25,10 +33,10 @@ string::string(const string & s) string::string(const char * s) { - char l = strlen(s); + char l = sstrlen(s); if (l) { - cstr = malloc(l + 2); + cstr = malloc(char(l + 2)); cstr[0] = l; smemcpy(cstr + 1, s, l + 1); } @@ -64,7 +72,7 @@ string & string::operator=(const string & s) if (s.cstr) { char l = s.cstr[0]; - cstr = malloc(l + 2); + cstr = malloc(char(l + 2)); smemcpy(cstr, s.cstr, l + 2); } else @@ -77,10 +85,10 @@ string & string::operator=(const string & s) string & string::operator=(const char * s) { free(cstr); - char l = strlen(s); + char l = sstrlen(s); if (l) { - cstr = malloc(l + 2); + cstr = malloc(char(l + 2)); cstr[0] = l; smemcpy(cstr + 1, s, l + 1); } @@ -97,7 +105,7 @@ string & string::operator+=(const string & s) if (cstr) { char l = cstr[0] + s.cstr[0]; - char * c = malloc(l + 2); + char * c = malloc(char(l + 2)); c[0] = l; smemcpy(c + 1, cstr + 1, cstr[0]); smemcpy(c + 1 + cstr[0], s.cstr + 1, s.cstr[0] + 1); @@ -107,7 +115,7 @@ string & string::operator+=(const string & s) else { char l = s.cstr[0]; - cstr = malloc(l + 2); + cstr = malloc(char(l + 2)); smemcpy(cstr, s.cstr, l + 2); } } @@ -116,13 +124,13 @@ string & string::operator+=(const string & s) string & string::operator+=(const char * s) { - char sl = strlen(s); + char sl = sstrlen(s); if (sl) { if (cstr) { char l = sl + cstr[0]; - char * c = malloc(l + 2); + char * c = malloc(char(l + 2)); c[0] = l; smemcpy(c + 1, cstr + 1, cstr[0]); smemcpy(c + 1 + cstr[0], s, sl + 1); @@ -131,7 +139,7 @@ string & string::operator+=(const char * s) } else { - cstr = malloc(sl + 2); + cstr = malloc(char(sl + 2)); cstr[0] = sl; smemcpy(cstr + 1, s, sl + 1); } @@ -144,7 +152,7 @@ string & string::operator+=(char c) if (cstr) { char l = cstr[0] + 1; - char * p = malloc(l + 2); + char * p = malloc(char(l + 2)); p[0] = l; smemcpy(p + 1, cstr + 1, cstr[0]); p[l] = c; @@ -185,7 +193,7 @@ string string::operator+(const string & s) const if (s.cstr) { char l = cstr[0] + s.cstr[0]; - char * p = malloc(l + 2); + char * p = malloc(char(l + 2)); smemcpy(p + 1, cstr + 1, cstr[0]); smemcpy(p + 1 + cstr[0], s.cstr + 1, s.cstr[0]); return string(l, p); @@ -201,11 +209,11 @@ string string::operator+(const char * s) const { if (cstr) { - char sl = strlen(s); + char sl = sstrlen(s); if (sl) { char l = cstr[0] + sl; - char * p = malloc(l + 2); + char * p = malloc(char(l + 2)); smemcpy(p + 1, cstr + 1, cstr[0]); smemcpy(p + 1 + cstr[0], s, sl); return string(l, p); @@ -222,7 +230,7 @@ string string::operator+(char c) const if (cstr) { char l = cstr[0] + 1; - char * p = malloc(l + 2); + char * p = malloc(char(l + 2)); smemcpy(p + 1, cstr + 1, cstr[0]); p[l] = c; return string(l, p); @@ -472,7 +480,7 @@ int string::find(const char * s, char pos) const if (cstr) { char l = cstr[0]; - char sl = strlen(s); + char sl = sstrlen(s); if (sl <= l) { l -= sl; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 91b1108..4c209e4 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -11863,7 +11863,7 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) for (int i = 0; i < path.Size(); i++) printf("path %d\n", path[i]->mIndex); #endif - bool hasCall = false, hasFrame = false; + bool hasCall = false, hasFrame = false, hasStore = false; for (int bi = 0; bi < body.Size(); bi++) { InterCodeBasicBlock* block = body[bi]; @@ -11877,6 +11877,17 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) hasCall = true; else if (ins->mCode == IC_PUSH_FRAME) hasFrame = true; + else if (ins->mCode == IC_STORE) + { + if (ins->mSrc[1].mTemp >= 0) + hasStore = true; + else if ((ins->mSrc[1].mMemory == IM_PARAM || ins->mSrc[1].mMemory == IM_FPARAM) && !aliasedParams[ins->mSrc[1].mVarIndex]) + ; + else + hasStore = true; + } + else if (ins->mCode == IC_COPY || ins->mCode == IC_STRCPY) + hasStore = true; } } @@ -11897,7 +11908,11 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) ins->mInvariant = false; else if (ins->mCode == IC_LOAD) { - if (ins->mSrc[0].mTemp >= 0 || ins->mVolatile) + if (ins->mVolatile) + { + ins->mInvariant = false; + } + else if (ins->mSrc[0].mTemp >= 0 && (hasStore || hasCall)) { ins->mInvariant = false; } @@ -16129,7 +16144,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "test_find"); + CheckFunc = !strcmp(mIdent->mString, "string::find"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 8908ed9..1403b4c 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -969,6 +969,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro if (vp.mTemp != vr.mTemp) { InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + cins->mNumOperands = 2; cins->mSrc[0].mType = IT_POINTER; cins->mSrc[0].mTemp = vr.mTemp; @@ -1276,6 +1277,8 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I else { InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + cins->mNumOperands = 2; + cins->mSrc[0].mType = IT_POINTER; cins->mSrc[0].mTemp = vr.mTemp; cins->mSrc[0].mMemory = IM_INDIRECT; @@ -1753,6 +1756,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vr.mTemp != vl.mTemp) { InterInstruction* ins = new InterInstruction(exp->mLocation, IC_COPY); + ins->mNumOperands = 2; + ins->mSrc[0].mType = IT_POINTER; ins->mSrc[0].mTemp = vr.mTemp; ins->mSrc[0].mMemory = IM_INDIRECT; @@ -2118,8 +2123,21 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* crins->mDst.mTemp = proc->AddTemporary(crins->mDst.mType); block->Append(crins); + int s = vl.mType->Stride(); + bool binary = !(s & (s - 1)); + if (binary) + { + int n = 0; + while (s > 1) + { + s >>= 1; + n++; + } + s = n; + } + InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); - cins->mConst.mIntConst = vl.mType->Stride(); + cins->mConst.mIntConst = s; cins->mDst.mType = IT_INT16; cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); block->Append(cins); @@ -2134,7 +2152,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* sins->mDst.mTemp = proc->AddTemporary(sins->mDst.mType); block->Append(sins); - dins->mOperator = IA_DIVS; + dins->mOperator = binary ? IA_SAR : IA_DIVS; dins->mSrc[0].mType = IT_INT16; dins->mSrc[0].mTemp = cins->mDst.mTemp; dins->mSrc[1].mType = IT_INT16; @@ -2834,6 +2852,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(sex->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); InterInstruction* ins = new InterInstruction(exp->mLocation, IC_COPY); + ins->mNumOperands = 2; + ins->mSrc[0].mType = IT_POINTER; ins->mSrc[0].mMemory = IM_INDIRECT; ins->mSrc[0].mTemp = vr.mTemp; @@ -2931,6 +2951,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else { fins = new InterInstruction(exp->mLocation, IC_PUSH_FRAME); + fins->mNumOperands = 0; fins->mConst.mIntConst = atotal; block->Append(fins); } @@ -3228,6 +3249,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* fins->mConst.mIntConst = atotal; InterInstruction* xins = new InterInstruction(exp->mLocation, IC_POP_FRAME); + xins->mNumOperands = 0; xins->mConst.mIntConst = atotal; block->Append(xins); } @@ -3690,6 +3712,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, destack, inlineMapper); InterInstruction* ins = new InterInstruction(exp->mLocation, IC_UNREACHABLE); + ins->mNumOperands = 0; fblock->Append(ins); fblock->Close(nullptr, nullptr); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 95f6dcc..2ed7b73 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -34974,7 +34974,31 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } #endif - + else if ( + mIns[i + 0].mType == ASMIT_INC && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 1].mAddress && !(mIns[i + 1].mLive & LIVE_MEM)) + { + if (!(mIns[i + 0].mLive & LIVE_CPU_REG_X)) + { + mIns[i + 0].mType = ASMIT_LDX; mIns[i + 0].mLive |= LIVE_CPU_REG_X; + mIns.Insert(i + 1, NativeCodeInstruction(mIns[i + 1].mIns, ASMIT_INX)); + mIns[i + 2].mType = ASMIT_TXA; mIns[i + 2].mMode = ASMIM_IMPLIED; + progress = true; + } + else if (!(mIns[i + 0].mLive & LIVE_CPU_REG_Y)) + { + mIns[i + 0].mType = ASMIT_LDY; mIns[i + 0].mLive |= LIVE_CPU_REG_Y; + mIns.Insert(i + 1, NativeCodeInstruction(mIns[i + 1].mIns, ASMIT_INY)); + mIns[i + 2].mType = ASMIT_TYA; mIns[i + 2].mMode = ASMIM_IMPLIED; + progress = true; + } + else if (!(mIns[i + 0].mLive & LIVE_CPU_REG_C)) + { + mIns.Insert(i + 1, NativeCodeInstruction(mIns[i + 1].mIns, ASMIT_CLC)); + mIns[i + 2].mType = ASMIT_ADC; mIns[i + 2].mMode = ASMIM_IMMEDIATE; mIns[i + 2].mAddress = 1; + progress = true; + } + } #if 0 else if ( mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && @@ -39859,6 +39883,45 @@ bool NativeCodeBasicBlock::CalculateOffset(int& total) return changed; } +void NativeCodeBasicBlock::ShortcutJump(int offset) +{ + if (mCode[offset] == 0x4c) + { + int i = 0; + while (i < mRelocations.Size() && mRelocations[i].mOffset != offset + 1) + i++; + if (i < mRelocations.Size()) + { + LinkerReference& ref(mRelocations[i]); + if (ref.mRefObject && ref.mRefObject->mData) + { + LinkerObject* lo = ref.mRefObject; + + if (lo->mData[ref.mRefOffset] == 0x4c || lo->mData[ref.mRefOffset] == 0x6c) + { + int j = 0; + while (j < lo->mReferences.Size() && lo->mReferences[j]->mOffset != ref.mRefOffset + 1) + j++; + if (j < lo->mReferences.Size()) + { + mCode[offset] = lo->mData[ref.mRefOffset]; + ref.mRefObject = lo->mReferences[j]->mRefObject; + ref.mRefOffset = lo->mReferences[j]->mRefOffset; + ref.mFlags = lo->mReferences[j]->mFlags; + } + else + { + mCode[offset] = lo->mData[ref.mRefOffset]; + mCode[offset + 1] = lo->mData[ref.mRefOffset + 1]; + mCode[offset + 2] = lo->mData[ref.mRefOffset + 2]; + mRelocations.Remove(i); + } + } + } + } + } +} + void NativeCodeBasicBlock::ShortcutTailRecursion() { if (!mVisited) @@ -39869,6 +39932,7 @@ void NativeCodeBasicBlock::ShortcutTailRecursion() this->mCode[this->mCode.Size() - 3] = 0x4c; mTrueJump->mNumEntries--; mTrueJump = nullptr; + ShortcutJump(this->mCode.Size() - 3); } else if (!mFalseJump && !mTrueJump) { @@ -39877,6 +39941,7 @@ void NativeCodeBasicBlock::ShortcutTailRecursion() { this->mCode.Remove(this->mCode.Size() - 1); this->mCode[this->mCode.Size() - 3] = 0x4c; + ShortcutJump(this->mCode.Size() - 3); } } diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 6db7ec7..5be97e3 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -269,6 +269,7 @@ public: void PrependInstruction(const NativeCodeInstruction& ins); void ShortcutTailRecursion(); + void ShortcutJump(int offset); bool ReferencesAccu(int from = 0, int to = 65536) const; bool ReferencesYReg(int from = 0, int to = 65536) const; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index cb9c3fa..623cb0a 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1337,7 +1337,7 @@ Expression* Parser::BuildMemberInitializer(Expression* vexp) mScanner->NextToken(); if (mScanner->mToken != TK_CLOSE_PARENTHESIS) { - fexp->mRight = ParseListExpression(); + fexp->mRight = ParseListExpression(false); ConsumeToken(TK_CLOSE_PARENTHESIS); } else @@ -2887,7 +2887,7 @@ void Parser::ParseVariableInit(Declaration* ndec) mScanner->NextToken(); if (mScanner->mToken != TK_CLOSE_PARENTHESIS) { - pexp = ParseListExpression(); + pexp = ParseListExpression(false); ConsumeToken(TK_CLOSE_PARENTHESIS); } else @@ -4332,7 +4332,7 @@ Expression* Parser::ParseQualify(Expression* exp) nexp->mRight = nullptr; else { - nexp->mRight = ParseListExpression(); + nexp->mRight = ParseListExpression(false); ConsumeToken(TK_CLOSE_PARENTHESIS); } @@ -4530,7 +4530,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) mScanner->NextToken(); if (mScanner->mToken != TK_CLOSE_PARENTHESIS) { - pexp = ParseListExpression(); + pexp = ParseListExpression(false); ConsumeToken(TK_CLOSE_PARENTHESIS); } else @@ -4641,7 +4641,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) nexp->mLeft = exp; if (mScanner->mToken != TK_CLOSE_PARENTHESIS) { - nexp->mRight = ParseListExpression(); + nexp->mRight = ParseListExpression(false); ConsumeToken(TK_CLOSE_PARENTHESIS); } else @@ -4876,7 +4876,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) { if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) { - pexp = ParseListExpression(); + pexp = ParseListExpression(false); mdec = dec->mScope->Lookup(dec->mIdent); @@ -5717,16 +5717,16 @@ Expression* Parser::ParseExpression(bool lhs) return ParseAssignmentExpression(lhs); } -Expression* Parser::ParseListExpression(void) +Expression* Parser::ParseListExpression(bool lhs) { - Expression* exp = ParseExpression(true); + Expression* exp = ParseExpression(lhs); if (mScanner->mToken == TK_COMMA) { Expression* nexp = new Expression(mScanner->mLocation, EX_LIST); nexp->mToken = mScanner->mToken; nexp->mLeft = exp; mScanner->NextToken(); - nexp->mRight = ParseListExpression(); + nexp->mRight = ParseListExpression(false); exp = nexp; } return exp; @@ -6183,7 +6183,7 @@ Expression* Parser::ParseStatement(void) break; default: - exp = CleanupExpression(ParseListExpression()); + exp = CleanupExpression(ParseListExpression(true)); ConsumeToken(TK_SEMICOLON); } } diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 8691e9e..ee0bcc4 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -105,7 +105,7 @@ protected: Expression* ParseAssignmentExpression(bool lhs); Expression* ParseExpression(bool lhs); Expression* ParseRExpression(void); - Expression* ParseListExpression(void); + Expression* ParseListExpression(bool lhs); Expression* ParseParenthesisExpression(void); From fa60c2e658007c0a968f94fbcd7cf0f338b83227 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 14 Jul 2023 07:48:48 +0200 Subject: [PATCH 035/169] Improve operator overloading --- include/opp/string.h | 2 +- oscar64/Compiler.cpp | 1 + oscar64/Declaration.cpp | 32 ++- oscar64/Declaration.h | 5 +- oscar64/Errors.h | 1 + oscar64/GlobalAnalyzer.cpp | 25 +- oscar64/InterCodeGenerator.cpp | 13 +- oscar64/NativeCodeGenerator.cpp | 26 +- oscar64/NativeCodeGenerator.h | 2 +- oscar64/Parser.cpp | 404 ++++++++++++++++++++++++-------- oscar64/Parser.h | 4 +- 11 files changed, 387 insertions(+), 128 deletions(-) diff --git a/include/opp/string.h b/include/opp/string.h index ac4f784..b2132f0 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -9,7 +9,7 @@ private: public: string(void); string(const string & s); - __noinline string(const char * s); + string(const char * s); string(char c); ~string(void); diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index ad59d05..06b66e2 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -334,6 +334,7 @@ void Compiler::BuildVTables(void) Expression* ecall = new Expression(mdec->mLocation, EX_DISPATCH); ecall->mLeft = new Expression(mdec->mLocation, EX_INDEX); + ecall->mLeft->mDecType = mdec->mBase; ecall->mDecType = vtabt->mBase; ecall->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE); ecall->mLeft->mLeft->mDecType = vtabt; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 925ad2f..c278df5 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -92,8 +92,8 @@ Declaration* DeclarationScope::Lookup(const Ident* ident, ScopeLevel limit) if (mHashSize > 0) { - int hm = mHashSize - 1; - int hi = ident->mHash & hm; + unsigned int hm = mHashSize - 1; + unsigned int hi = ident->mHash & hm; while (mHash[hi].mIdent) { @@ -103,14 +103,17 @@ Declaration* DeclarationScope::Lookup(const Ident* ident, ScopeLevel limit) } } + if (limit == SLEVEL_SCOPE) + return nullptr; + for (int i = 0; i < mUsed.Size(); i++) { - Declaration* dec = mUsed[i]->Lookup(ident); + Declaration* dec = mUsed[i]->Lookup(ident, limit); if (dec) return dec; } - return mParent ? mParent->Lookup(ident) : nullptr; + return mParent ? mParent->Lookup(ident, limit) : nullptr; } void DeclarationScope::End(const Location& loc) @@ -811,6 +814,24 @@ int Declaration::Stride(void) const return mStride > 0 ? mStride : mBase->mSize; } +Declaration* Declaration::BuildConstPointer(const Location& loc) +{ + Declaration* pdec = new Declaration(loc, DT_TYPE_POINTER); + pdec->mBase = this; + pdec->mFlags = DTF_DEFINED | DTF_CONST; + pdec->mSize = 2; + return pdec; +} + +Declaration* Declaration::BuildConstReference(const Location& loc) +{ + Declaration* pdec = new Declaration(loc, DT_TYPE_REFERENCE); + pdec->mBase = this; + pdec->mFlags = DTF_DEFINED | DTF_CONST; + pdec->mSize = 2; + return pdec; +} + Declaration* Declaration::BuildPointer(const Location& loc) { Declaration* pdec = new Declaration(loc, DT_TYPE_POINTER); @@ -1022,6 +1043,9 @@ bool Declaration::IsSubType(const Declaration* dec) const if (this == dec) return true; + if (mType == DT_TYPE_REFERENCE && dec->mType == DT_TYPE_REFERENCE) + return mBase->IsSubType(dec->mBase); + if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) { if (dec->mType == DT_TYPE_POINTER) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 360a62a..c13bfc5 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -109,12 +109,13 @@ class Declaration; enum ScopeLevel { + SLEVEL_SCOPE, SLEVEL_GLOBAL, SLEVEL_STATIC, SLEVEL_NAMESPACE, SLEVEL_CLASS, SLEVEL_FUNCTION, - SLEVEL_LOCAL + SLEVEL_LOCAL, }; class DeclarationScope @@ -283,6 +284,8 @@ public: Declaration* BuildPointer(const Location& loc); Declaration* BuildReference(const Location& loc); + Declaration* BuildConstPointer(const Location& loc); + Declaration* BuildConstReference(const Location& loc); int Stride(void) const; }; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 8d7f14d..dcf4a97 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -80,6 +80,7 @@ enum ErrorID EERR_NO_DEFAULT_CONSTRUCTOR, EERR_INVALID_OPERATOR, EERR_MISSING_TEMP, + EERR_NON_STATIC_MEMBER, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 20fd213..64d3be3 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -293,9 +293,26 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head) Declaration* cf = procDec->mCalled[i]; if (cf->mType == DT_TYPE_FUNCTION) - procDec->mFlags |= DTF_DYNSTACK; + { + for (int i = 0; i < mVariableFunctions.Size(); i++) + { + Declaration* vf = mVariableFunctions[i]; + CheckFastcall(vf, false); - CheckFastcall(cf, false); + if (vf->mBase->IsSame(cf)) + { + int n = vf->mBase->mFastCallBase + vf->mBase->mFastCallSize; + if (n > nbase) + nbase = n; + } + } +// procDec->mFlags |= DTF_DYNSTACK; + } + else + CheckFastcall(cf, false); + + if (cf->mFlags & DTF_DYNSTACK) + procDec->mFlags |= DTF_DYNSTACK; // if (!(cf->mBase->mFlags & DTF_FASTCALL)) // procDec->mBase->mFlags |= DTF_STACKCALL; @@ -658,6 +675,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo return exp->mDecValue->mBase; case EX_DISPATCH: Analyze(exp->mLeft, procDec, lhs); + RegisterCall(procDec, exp->mLeft->mDecType); break; case EX_VCALL: exp->mType = EX_CALL; @@ -893,6 +911,9 @@ void GlobalAnalyzer::RegisterCall(Declaration* from, Declaration* to) { if (from) { + if (to->mType == DT_VARIABLE || to->mType == DT_ARGUMENT) + to = to->mBase; + if (to->mType == DT_CONST_FUNCTION) { if (to->mFlags & DTF_DYNSTACK) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 1403b4c..aedb37d 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1153,8 +1153,9 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I block->Append(ains); InterInstruction* wins = new InterInstruction(exp->mLocation, IC_STORE); + wins->mNumOperands = 2; wins->mSrc[1].mMemory = IM_INDIRECT; - wins->mSrc[0].mType = InterTypeOf(vl.mType);; + wins->mSrc[0].mType = vl.mReference > 0 ? IT_POINTER : InterTypeOf(vl.mType); wins->mSrc[0].mTemp = vl.mTemp; wins->mSrc[1].mType = IT_POINTER; wins->mSrc[1].mTemp = ains->mDst.mTemp; @@ -1168,6 +1169,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I vdec = new Declaration(exp->mLocation, DT_VARIABLE); ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains->mNumOperands = 0; ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); ains->mConst.mMemory = IM_LOCAL; @@ -1185,8 +1187,9 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I block->Append(ains); wins = new InterInstruction(exp->mLocation, IC_STORE); + wins->mNumOperands = 2; wins->mSrc[1].mMemory = IM_INDIRECT; - wins->mSrc[0].mType = InterTypeOf(vr.mType);; + wins->mSrc[0].mType = vr.mReference > 0 ? IT_POINTER : InterTypeOf(vr.mType);; wins->mSrc[0].mTemp = vr.mTemp; wins->mSrc[1].mType = IT_POINTER; wins->mSrc[1].mTemp = ains->mDst.mTemp; @@ -3082,7 +3085,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ExValue vp(ptype ? ptype : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); - if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE && texp->mType == EX_CALL) + if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE && texp->mType == EX_CALL && texp->mDecType->mType != DT_TYPE_REFERENCE) { mErrors->Error(texp->mLocation, EERR_MISSING_TEMP, "Missing temporary variable"); #if 0 @@ -4030,7 +4033,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { vr = Dereference(proc, exp, block, vr); ins->mCode = IC_TYPECAST; - ins->mSrc[0].mType = InterTypeOf(vr.mType); + ins->mSrc[0].mType = vr.mReference > 0 ? IT_POINTER : InterTypeOf(vr.mType); ins->mSrc[0].mTemp = vr.mTemp; ins->mDst.mType = InterTypeOf(exp->mDecType); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); @@ -4564,7 +4567,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)); #if 0 - if (proc->mIdent && !strcmp(proc->mIdent->mString, "A::func")) + if (proc->mIdent && !strcmp(proc->mIdent->mString, "main")) exp->Dump(0); #endif #if 0 diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 2ed7b73..50db1b2 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -12929,7 +12929,7 @@ void NativeCodeBasicBlock::FindZeroPageAlias(const NumberSet& statics, NumberSet } } -bool NativeCodeBasicBlock::CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet& global) +bool NativeCodeBasicBlock::CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet& global, bool ignorefcall) { if (!mVisited) { @@ -12946,12 +12946,20 @@ bool NativeCodeBasicBlock::CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet& case ASMIM_ABSOLUTE: if (mIns[i].mType == ASMIT_JSR) { - if ((mIns[i].mFlags & NCIF_RUNTIME) && !(mIns[i].mFlags & NCIF_FEXEC)) + if (mIns[i].mFlags & NCIF_RUNTIME) { - for (int j = 0; j < 4; j++) + if (mIns[i].mFlags & NCIF_FEXEC) { - locals += BC_REG_ACCU + j; - locals += BC_REG_WORK + j; + if (!ignorefcall) + return false; + } + else + { + for (int j = 0; j < 4; j++) + { + locals += BC_REG_ACCU + j; + locals += BC_REG_WORK + j; + } } } @@ -12996,9 +13004,9 @@ bool NativeCodeBasicBlock::CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet& } } - if (mTrueJump && !mTrueJump->CollectZeroPageSet(locals, global)) + if (mTrueJump && !mTrueJump->CollectZeroPageSet(locals, global, ignorefcall)) return false; - if (mFalseJump && !mFalseJump->CollectZeroPageSet(locals, global)) + if (mFalseJump && !mFalseJump->CollectZeroPageSet(locals, global, ignorefcall)) return false; } @@ -40372,7 +40380,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) ZeroPageSet zpLocal, zpGlobal; ResetVisited(); - if (mEntryBlock->CollectZeroPageSet(zpLocal, zpGlobal)) + if (mEntryBlock->CollectZeroPageSet(zpLocal, zpGlobal, true)) zpLocal |= zpGlobal; else mGenerator->mErrors->Error(mInterProc->mLocation, ERRR_INTERRUPT_TO_COMPLEX, "No recursive functions in interrupt"); @@ -40660,7 +40668,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) ZeroPageSet zpLocal, zpGlobal; ResetVisited(); - if (mEntryBlock->CollectZeroPageSet(zpLocal, zpGlobal)) + if (mEntryBlock->CollectZeroPageSet(zpLocal, zpGlobal, false)) { zpLocal |= zpGlobal; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 5be97e3..9968ad7 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -550,7 +550,7 @@ public: void BuildEntryDataSet(const NativeRegisterDataSet& set); bool ApplyEntryDataSet(void); - bool CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet& global); + bool CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet& global, bool ignorefcall); void CollectZeroPageUsage(NumberSet& used, NumberSet& modified, NumberSet& pairs); void FindZeroPageAlias(const NumberSet& statics, NumberSet& invalid, uint8* alias, int accu); bool RemapZeroPage(const uint8* remap); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 623cb0a..07dd308 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -121,6 +121,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) bcdec->mBase = pdec; bcdec->mFlags = pflags; + dec->mScope->UseScope(pdec->mScope); + if (pdec->mVTable) needVTable = true; @@ -137,12 +139,17 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) { Declaration* pthis = nullptr; + DeclarationScope* oscope = mScope; + if (mCompilerOptions & COPT_CPLUSPLUS) { pthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); pthis->mFlags |= DTF_CONST | DTF_DEFINED; pthis->mBase = dec; pthis->mSize = 2; + + dec->mScope->mParent = mScope; + mScope = dec->mScope; } mScanner->NextToken(); @@ -171,6 +178,10 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) flags |= DTF_PRIVATE | DTF_PROTECTED; ConsumeToken(TK_COLON); } + else if (ConsumeTokenIf(TK_CLOSE_BRACE)) + { + break; + } else { Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis); @@ -201,6 +212,11 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) AddMemberFunction(dec, mdec); } + else if ((mCompilerOptions & COPT_CPLUSPLUS) && mdec->mType == DT_ANON) + { + ConsumeToken(TK_SEMICOLON); + // anon element + } else { while (mdec) @@ -240,12 +256,6 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) break; } } - - if (mScanner->mToken == TK_CLOSE_BRACE) - { - mScanner->NextToken(); - break; - } } } @@ -363,7 +373,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) AddDefaultConstructors(pthis); // Lookup constructors, have same name as class - Declaration* cdec = dec->mScope->Lookup(dec->mIdent); + Declaration* cdec = dec->mScope->Lookup(dec->mIdent, SLEVEL_SCOPE); while (cdec) { if (cdec->mFlags & DTF_DEFINED) @@ -374,12 +384,14 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) AppendMemberDestructor(pthis); } + + mScope = oscope; } return dec; } -Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) +Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) { Declaration* dec = nullptr; @@ -434,11 +446,11 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) case TK_CONST: mScanner->NextToken(); - return ParseBaseTypeDeclaration(flags | DTF_CONST); + return ParseBaseTypeDeclaration(flags | DTF_CONST, qualified); case TK_VOLATILE: mScanner->NextToken(); - return ParseBaseTypeDeclaration(flags | DTF_VOLATILE); + return ParseBaseTypeDeclaration(flags | DTF_VOLATILE, qualified); case TK_LONG: dec = new Declaration(mScanner->mLocation, DT_TYPE_INTEGER); @@ -492,6 +504,19 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) case TK_IDENT: dec = mScope->Lookup(mScanner->mTokenIdent); + if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS) + dec = mScope->mParent->Lookup(mScanner->mTokenIdent); + + mScanner->NextToken(); + while (qualified && dec && dec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON)) + { + if (ExpectToken(TK_IDENT)) + { + dec = dec->mScope->Lookup(mScanner->mTokenIdent); + mScanner->NextToken(); + } + } + if (dec && dec->mType <= DT_TYPE_FUNCTION) { if (dec->IsSimpleType() && (flags & ~dec->mFlags)) @@ -519,7 +544,6 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags) dec = ndec; } } - mScanner->NextToken(); } else if (!dec) { @@ -811,7 +835,7 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) break; } - Declaration* bdec = ParseBaseTypeDeclaration(0); + Declaration* bdec = ParseBaseTypeDeclaration(0, true); Declaration* adec = ParsePostfixDeclaration(); adec = ReverseDeclaration(adec, bdec); @@ -1364,7 +1388,7 @@ Expression* Parser::BuildMemberInitializer(Expression* vexp) else fexp->mRight = texp; - ResolveOverloadCall(cexp, fexp->mRight); + fexp = ResolveOverloadCall(fexp); return fexp; } @@ -1644,7 +1668,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) // Extract constructor and destructor from scope - Declaration* cdec = pthis->mBase->mScope->Lookup(pthis->mBase->mIdent); + Declaration* cdec = pthis->mBase->mScope->Lookup(pthis->mBase->mIdent, SLEVEL_SCOPE); while (cdec) { Declaration* ctdec = cdec->mBase; @@ -1658,11 +1682,11 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec = cdec->mNext; } - Declaration* ddec = pthis->mBase->mScope->Lookup(dtorident); + Declaration* ddec = pthis->mBase->mScope->Lookup(dtorident, SLEVEL_SCOPE); if (ddec) pthis->mBase->mDestructor = ddec; - Declaration* adec = pthis->mBase->mScope->Lookup(Ident::Unique("operator=")); + Declaration* adec = pthis->mBase->mScope->Lookup(Ident::Unique("operator="), SLEVEL_SCOPE); while (adec) { Declaration* atdec = adec->mBase; @@ -2893,7 +2917,7 @@ void Parser::ParseVariableInit(Declaration* ndec) else mScanner->NextToken(); - Declaration* fcons = ndec->mBase->mScope ? ndec->mBase->mScope->Lookup(ndec->mBase->mIdent) : nullptr; + Declaration* fcons = ndec->mBase->mScope ? ndec->mBase->mScope->Lookup(ndec->mBase->mIdent, SLEVEL_CLASS) : nullptr; if (fcons) { @@ -2929,7 +2953,7 @@ void Parser::ParseVariableInit(Declaration* ndec) else fexp->mRight = texp; - ResolveOverloadCall(cexp, fexp->mRight); + fexp = ResolveOverloadCall(fexp); Expression* dexp = nullptr; if (ndec->mBase->mDestructor) @@ -3139,7 +3163,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex return cdec; } - bdec = ParseBaseTypeDeclaration(typeFlags); + bdec = ParseBaseTypeDeclaration(typeFlags, false); } Declaration* rdec = nullptr, * ldec = nullptr; @@ -3164,7 +3188,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (mCompilerOptions & COPT_NATIVE) cdec->mFlags |= DTF_NATIVE; - Declaration* pdec = pthis->mBase->mScope ? pthis->mBase->mScope->Lookup(pthis->mBase->mIdent) : nullptr; + Declaration* pdec = pthis->mBase->mScope ? pthis->mBase->mScope->Lookup(pthis->mBase->mIdent, SLEVEL_CLASS) : nullptr; if (pdec) { while (pdec && !cdec->mBase->IsSameParams(pdec->mBase)) @@ -3228,63 +3252,75 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (bdec && bdec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON)) { - if (mScanner->mToken == TK_IDENT && mScanner->mTokenIdent == bdec->mIdent) + if (mScanner->mToken == TK_IDENT) { - mScanner->NextToken(); - - Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); - - Declaration * bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); - bthis->mFlags |= DTF_CONST | DTF_DEFINED; - if (ConsumeTokenIf(TK_CONST)) - bthis->mBase = bdec->ToConstType(); - else - bthis->mBase = bdec; - bthis->mSize = 2; - - PrependThisArgument(ctdec, bthis); - - Declaration* cdec = bdec->mScope->Lookup(bdec->mIdent); - if (cdec) + if (mScanner->mTokenIdent == bdec->mIdent) { - while (cdec && !cdec->mBase->IsSameParams(ctdec)) - cdec = cdec->mNext; - } + mScanner->NextToken(); - if (cdec) - { - cdec->mFlags |= storageFlags & DTF_REQUEST_INLINE; + Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); - // Initializer list - if (mScanner->mToken == TK_COLON) + Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + bthis->mFlags |= DTF_CONST | DTF_DEFINED; + if (ConsumeTokenIf(TK_CONST)) + bthis->mBase = bdec->ToConstType(); + else + bthis->mBase = bdec; + bthis->mSize = 2; + + PrependThisArgument(ctdec, bthis); + + Declaration* cdec = bdec->mScope->Lookup(bdec->mIdent, SLEVEL_CLASS); + if (cdec) { - BuildMemberConstructor(bthis, cdec); + while (cdec && !cdec->mBase->IsSameParams(ctdec)) + cdec = cdec->mNext; } - if (mScanner->mToken == TK_OPEN_BRACE) + if (cdec) { - if (cdec->mFlags & DTF_DEFINED) - mErrors->Error(cdec->mLocation, EERR_DUPLICATE_DEFINITION, "Function already has a body"); + cdec->mFlags |= storageFlags & DTF_REQUEST_INLINE; - cdec->mCompilerOptions = mCompilerOptions; - cdec->mBase->mCompilerOptions = mCompilerOptions; + // Initializer list + if (mScanner->mToken == TK_COLON) + { + BuildMemberConstructor(bthis, cdec); + } - cdec->mVarIndex = -1; + if (mScanner->mToken == TK_OPEN_BRACE) + { + if (cdec->mFlags & DTF_DEFINED) + mErrors->Error(cdec->mLocation, EERR_DUPLICATE_DEFINITION, "Function already has a body"); - cdec->mValue = ParseFunction(cdec->mBase); + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; - cdec->mFlags |= DTF_DEFINED; - cdec->mNumVars = mLocalIndex; + cdec->mVarIndex = -1; - PrependMemberConstructor(bthis, cdec); + cdec->mValue = ParseFunction(cdec->mBase); + + cdec->mFlags |= DTF_DEFINED; + cdec->mNumVars = mLocalIndex; + + PrependMemberConstructor(bthis, cdec); + } + + return cdec; + } + else + { + mErrors->Error(bdec->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor"); + return bdec; } - - return cdec; } else { - mErrors->Error(bdec->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor"); - return bdec; + Declaration* mdec = bdec->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS); + if (mdec) + bdec = mdec; + else + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Member not found", mScanner->mTokenIdent); + mScanner->NextToken(); } } @@ -3375,7 +3411,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) { if (ConsumeTokenIf(TK_CONST)) - PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildPointer(ndec->mLocation)); + PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildConstPointer(ndec->mLocation)); else PrependThisArgument(ndec->mBase, pthis); } @@ -3431,7 +3467,15 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex adec->mNext = ndec->mBase->mParams; if (ConsumeTokenIf(TK_CONST)) - adec->mBase = adec->mBase->mBase->ToConstType()->BuildPointer(adec->mLocation); + { + if (!(adec->mBase->mBase->mFlags & DTF_CONST)) + adec->mBase = adec->mBase->mBase->ToConstType()->BuildConstPointer(adec->mLocation); + } + else + { + if (adec->mBase->mBase->mFlags & DTF_CONST) + adec->mBase = adec->mBase->mBase->ToMutableType()->BuildConstPointer(adec->mLocation); + } Declaration* p = adec->mBase->mParams; while (p) @@ -3866,9 +3910,9 @@ Declaration* Parser::ParseQualIdent(void) { if (mScanner->mToken == TK_IDENT) { - if (dec->mType == DT_NAMESPACE) + if (dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_STRUCT) { - Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent); + Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS); if (ndec) dec = ndec; @@ -3896,7 +3940,7 @@ Declaration* Parser::ParseQualIdent(void) Expression* Parser::ParseSimpleExpression(bool lhs) { - Declaration* dec; + Declaration* dec = nullptr; Expression* exp = nullptr, * rexp = nullptr; switch (mScanner->mToken) @@ -3916,7 +3960,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) { exp = new Expression(mScanner->mLocation, EX_TYPE); exp->mDecValue = nullptr; - exp->mDecType = ParseBaseTypeDeclaration(0); + exp->mDecType = ParseBaseTypeDeclaration(0, true); } break; case TK_CONST: @@ -4097,22 +4141,28 @@ Expression* Parser::ParseSimpleExpression(bool lhs) dec = MemberLookup(mThisPointer->mBase->mBase, mScanner->mTokenIdent, offset, flags); if (dec) { - Expression * texp = new Expression(mScanner->mLocation, EX_VARIABLE); - texp->mDecType = mThisPointer->mBase; - texp->mDecValue = mThisPointer; + if (dec->mType == DT_ELEMENT || dec->mType == DT_CONST_FUNCTION) + { + Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE); + texp->mDecType = mThisPointer->mBase; + texp->mDecValue = mThisPointer; - Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX); - dexp->mToken = TK_MUL; - dexp->mDecType = texp->mDecType->mBase; - dexp->mLeft = texp; + Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX); + dexp->mToken = TK_MUL; + dexp->mDecType = texp->mDecType->mBase; + dexp->mLeft = texp; - exp = ParseQualify(dexp); + exp = ParseQualify(dexp); + } + else + mScanner->NextToken(); } } if (!exp) { - dec = ParseQualIdent(); + if (!dec) + dec = ParseQualIdent(); if (dec) { if (dec->mType == DT_CONST_INTEGER || dec->mType == DT_CONST_FLOAT || dec->mType == DT_CONST_FUNCTION || dec->mType == DT_CONST_ASSEMBLER || dec->mType == DT_LABEL || dec->mType == DT_LABEL_REF) @@ -4156,6 +4206,10 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp->mDecType = dec; } } + else if (dec->mType == DT_ELEMENT) + { + mErrors->Error(mScanner->mLocation, EERR_NON_STATIC_MEMBER, "Non static member access", mScanner->mTokenIdent); + } else { mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid identifier", mScanner->mTokenIdent); @@ -4244,7 +4298,10 @@ Expression* Parser::ParseSimpleExpression(bool lhs) Declaration* Parser::MemberLookup(Declaration* dtype, const Ident* ident, int & offset, uint64& flags) { - Declaration* mdec = dtype->mScope->Lookup(ident); + if (ident == dtype->mIdent) + return nullptr; + + Declaration* mdec = dtype->mScope->Lookup(ident, SLEVEL_CLASS); offset = 0; flags = 0; @@ -4341,7 +4398,10 @@ Expression* Parser::ParseQualify(Expression* exp) texp->mLeft = exp; texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = exp->mDecType; + if (exp->mDecType->mType == DT_TYPE_REFERENCE) + texp->mDecType->mBase = exp->mDecType->mBase; + else + texp->mDecType->mBase = exp->mDecType; texp->mDecType->mSize = 2; if (nexp->mRight) @@ -4354,7 +4414,8 @@ Expression* Parser::ParseQualify(Expression* exp) else nexp->mRight = texp; - ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp = ResolveOverloadCall(nexp); + nexp->mDecType = nexp->mLeft->mDecType->mBase; if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL) @@ -4406,13 +4467,65 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) etype = etype->mBase; if (ptype->mType == DT_TYPE_INTEGER && etype->mType == DT_TYPE_INTEGER) - ; + { + if (ptype->mSize == etype->mSize) + { + if ((ptype->mFlags & DTF_SIGNED) == (etype->mFlags & DTF_SIGNED)) + dist += 0; + else + dist += 4; + } + else if (ptype->mSize > etype->mSize) + { + if (ptype->mFlags & DTF_SIGNED) + { + dist += 1; + } + else if (etype->mFlags & DTF_SIGNED) + { + dist += 4; + } + else + dist += 1; + } + else if (ex->mType == EX_CONSTANT && ex->mDecValue->mType == DT_CONST_INTEGER) + { + int64 v = ex->mDecValue->mInteger; + + if (ptype->mFlags & DTF_SIGNED) + { + if (v >= -128 && v <= 127) + dist += 1; + else if (ptype->mSize >= 2 && v >= -32768 && v <= 32767) + dist += 1; + else if (ptype->mSize == 4) + dist += 1; + else + dist += 16; + } + else if (v >= 0) + { + if (v <= 255) + dist += 1; + else if (ptype->mSize >= 2 && v <= 65535) + dist += 1; + else if (ptype->mSize == 4) + dist += 1; + else + dist += 16; + } + else + dist += 16; + } + else + dist += 16; + } else if (ptype->mType == DT_TYPE_FLOAT && etype->mType == DT_TYPE_FLOAT) - ; + dist += 0; else if (ptype->mType == DT_TYPE_INTEGER && etype->mType == DT_TYPE_FLOAT) dist += 8; else if (ptype->mType == DT_TYPE_FLOAT && etype->mType == DT_TYPE_INTEGER) - dist++; + dist += 4; else if (ptype->IsSame(ex->mDecType)) ; else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_TYPE_STRUCT && etype->mType == DT_TYPE_STRUCT) @@ -4434,6 +4547,8 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) } else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_ARRAY && ptype->mBase->IsSameMutable(etype->mBase)) dist += 1; + else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_FUNCTION && ptype->mBase->IsSame(etype)) + dist += 0; else if (ptype->IsSubType(etype)) dist += 256; else @@ -4456,22 +4571,26 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) return dist; } -void Parser::ResolveOverloadCall(Expression* cexp, Expression* pexp) +Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) { - if (cexp->mDecValue) + if (exp->mType == EX_CALL && exp->mLeft->mDecValue) { - Declaration* fdec = cexp->mDecValue; - if (fdec->mType == DT_CONST_FUNCTION && fdec->mNext) + Declaration* fdec = exp->mLeft->mDecValue; + Declaration* fdec2 = exp2 ? exp2->mLeft->mDecValue : nullptr; + + if (fdec->mType == DT_CONST_FUNCTION && fdec->mNext || fdec2) { Declaration* dbest = nullptr; + Expression* pbest = nullptr; int ibest = NOOVERLOAD, nbest = 0; while (fdec) { - int d = OverloadDistance(fdec->mBase, pexp); + int d = OverloadDistance(fdec->mBase, exp->mRight); if (d < ibest) { dbest = fdec; + pbest = exp->mRight; ibest = d; nbest = 1; } @@ -4480,17 +4599,36 @@ void Parser::ResolveOverloadCall(Expression* cexp, Expression* pexp) fdec = fdec->mNext; } + while (fdec2) + { + int d = OverloadDistance(fdec2->mBase, exp2->mRight); + if (d < ibest) + { + dbest = fdec2; + pbest = exp2->mRight; + ibest = d; + nbest = 1; + } + else if (d == ibest) + nbest++; + fdec2 = fdec2->mNext; + } + if (ibest == NOOVERLOAD) - mErrors->Error(cexp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call"); + mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call"); else if (nbest > 1) - mErrors->Error(cexp->mLocation, ERRO_AMBIGUOUS_FUNCTION_CALL, "Ambiguous function call"); + mErrors->Error(exp->mLocation, ERRO_AMBIGUOUS_FUNCTION_CALL, "Ambiguous function call"); else { - cexp->mDecValue = dbest; - cexp->mDecType = dbest->mBase; + exp->mLeft->mDecValue = dbest; + exp->mLeft->mDecType = dbest->mBase; + exp->mDecType = dbest->mBase->mBase; + exp->mRight = pbest; } } } + + return exp; } Expression* Parser::ParsePostfixExpression(bool lhs) @@ -4584,7 +4722,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) else fexp->mRight = texp; - ResolveOverloadCall(cexp, fexp->mRight); + fexp = ResolveOverloadCall(fexp); Expression* dexp = nullptr; if (exp->mDecType->mDestructor) @@ -4650,7 +4788,24 @@ Expression* Parser::ParsePostfixExpression(bool lhs) mScanner->NextToken(); } - ResolveOverloadCall(exp, nexp->mRight); + if ((exp->mDecType->mFlags & DTF_FUNC_THIS) && mThisPointer && mThisPointer->mType == DT_ARGUMENT) + { + Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE); + texp->mDecType = mThisPointer->mBase; + texp->mDecValue = mThisPointer; + + if (nexp->mRight) + { + Expression* lexp = new Expression(nexp->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = nexp->mRight; + nexp->mRight = lexp; + } + else + nexp->mRight = texp; + } + + nexp = ResolveOverloadCall(nexp); nexp->mDecType = exp->mDecType->mBase; if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL) @@ -4756,7 +4911,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) nexp = new Expression(mScanner->mLocation, EX_PREFIX); nexp->mToken = TK_NEW; mScanner->NextToken(); - Declaration * dec = ParseBaseTypeDeclaration(0); + Declaration * dec = ParseBaseTypeDeclaration(0, true); Declaration* sconst = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); sconst->mBase = TheUnsignedIntTypeDeclaration; @@ -4897,7 +5052,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) dexp->mLeft = cexp; dexp->mRight = pexp; - ResolveOverloadCall(cexp, pexp); + dexp = ResolveOverloadCall(dexp); Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); @@ -5367,6 +5522,23 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) if (opident) { + Expression* nexp2 = nullptr; + + Declaration* mdec2 = mScope->Lookup(opident); + if (mdec2) + { + nexp2 = new Expression(mScanner->mLocation, EX_CALL); + + nexp2->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp2->mLeft->mDecType = mdec2->mBase; + nexp2->mLeft->mDecValue = mdec2; + + nexp2->mDecType = mdec2->mBase; + nexp2->mRight = new Expression(mScanner->mLocation, EX_LIST); + nexp2->mRight->mLeft = exp->mLeft; + nexp2->mRight->mRight = exp->mRight; + } + Declaration* mdec = tdec->mScope->Lookup(opident); if (mdec) { @@ -5392,7 +5564,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) lexp->mRight = nexp->mRight; nexp->mRight = lexp; - ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp = ResolveOverloadCall(nexp, nexp2); nexp->mDecType = nexp->mLeft->mDecType->mBase; exp = nexp; @@ -5405,7 +5577,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) Declaration* tdec = exp->mLeft->mDecType; if (tdec->mType == DT_TYPE_STRUCT) { - Declaration* mdec = tdec->mScope->Lookup(Ident::Unique("operator[]")); + const Ident* opident = Ident::Unique("operator[]"); + + Declaration* mdec = tdec->mScope->Lookup(opident); if (mdec) { Expression* nexp = new Expression(mScanner->mLocation, EX_CALL); @@ -5430,7 +5604,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) lexp->mRight = nexp->mRight; nexp->mRight = lexp; - ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp = ResolveOverloadCall(nexp); nexp->mDecType = nexp->mLeft->mDecType->mBase; exp = nexp; @@ -5477,7 +5651,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) nexp->mRight = texp; - ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp = ResolveOverloadCall(nexp); nexp->mDecType = nexp->mLeft->mDecType->mBase; exp = nexp; @@ -5531,7 +5705,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) lexp->mRight->mDecValue->mBase = TheSignedIntTypeDeclaration; nexp->mRight = lexp; - ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp = ResolveOverloadCall(nexp); nexp->mDecType = nexp->mLeft->mDecType->mBase; exp = nexp; @@ -5596,7 +5770,27 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) if (opident) { + Expression* nexp2 = nullptr; + + Declaration* mdec2 = mScope->Lookup(opident); + if (mdec2) + { + nexp2 = new Expression(mScanner->mLocation, EX_CALL); + + nexp2->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp2->mLeft->mDecType = mdec2->mBase; + nexp2->mLeft->mDecValue = mdec2; + + nexp2->mDecType = mdec2->mBase; + nexp2->mRight = new Expression(mScanner->mLocation, EX_LIST); + nexp2->mRight->mLeft = exp->mLeft; + nexp2->mRight->mRight = exp->mRight; + } + Declaration* tdec = exp->mLeft->mDecType; + while (tdec->mType == DT_TYPE_REFERENCE) + tdec = tdec->mBase; + if (tdec->mType == DT_TYPE_STRUCT) { Declaration* mdec = tdec->mScope->Lookup(opident); @@ -5616,7 +5810,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mLeft = exp->mLeft; texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = exp->mLeft->mDecType; + texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); @@ -5624,7 +5818,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) lexp->mRight = nexp->mRight; nexp->mRight = lexp; - ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp = ResolveOverloadCall(nexp, nexp2); nexp->mDecType = nexp->mLeft->mDecType->mBase; exp = nexp; @@ -5678,7 +5872,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) nexp->mRight = texp; - ResolveOverloadCall(nexp->mLeft, nexp->mRight); + nexp = ResolveOverloadCall(nexp); nexp->mDecType = nexp->mLeft->mDecType->mBase; exp = nexp; @@ -5741,6 +5935,10 @@ Expression* Parser::ParseFunction(Declaration * dec) mReturnType = dec->mBase; + DeclarationScope* oscope = mScope; + while (mScope->mLevel == SLEVEL_CLASS) + mScope = mScope->mParent; + DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_FUNCTION); mScope = scope; @@ -5803,7 +6001,7 @@ Expression* Parser::ParseFunction(Declaration * dec) } mScope->End(mScanner->mLocation); - mScope = mScope->mParent; + mScope = oscope; mThisPointer = othis; diff --git a/oscar64/Parser.h b/oscar64/Parser.h index ee0bcc4..326787a 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -54,7 +54,7 @@ protected: Expression * AddFunctionCallRefReturned(Expression * exp); Expression* CleanupExpression(Expression* exp); - Declaration* ParseBaseTypeDeclaration(uint64 flags); + Declaration* ParseBaseTypeDeclaration(uint64 flags, bool qualified); Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr); Declaration* ParseStructDeclaration(uint64 flags, DecType dt); @@ -87,7 +87,7 @@ protected: Expression* ParseQualify(Expression * exp); int OverloadDistance(Declaration* pdec, Expression* pexp); - void ResolveOverloadCall(Expression* cexp, Expression* pexp); + Expression * ResolveOverloadCall(Expression* exp, Expression * exp2 = nullptr); Expression* ParseSimpleExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs); From 76b60392565b8fbc857d8ae52bfbdc9e79eb3aa2 Mon Sep 17 00:00:00 2001 From: polluks Date: Sat, 15 Jul 2023 18:52:22 +0200 Subject: [PATCH 036/169] Added makefile for autotest --- .gitignore | 5 +--- autotest/makefile | 50 +++++++++++++++++++++++++++++++++ samples/memmap/charsetload.d64 | Bin 174848 -> 0 bytes 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 autotest/makefile delete mode 100644 samples/memmap/charsetload.d64 diff --git a/.gitignore b/.gitignore index 102aef8..ad6600a 100644 --- a/.gitignore +++ b/.gitignore @@ -343,12 +343,9 @@ make/oscar64 *.int *.bcs *.crt -*.crt -*.d64 +**/*.d64 *.tlog *.res *.recipe *.exe -*.d64 -*.d64 *.dbj diff --git a/autotest/makefile b/autotest/makefile new file mode 100644 index 0000000..570d208 --- /dev/null +++ b/autotest/makefile @@ -0,0 +1,50 @@ +CC=../bin/oscar64 +CXX=$(CC) +SRCS=$(wildcard *.c *.cpp) +EXES=$(patsubst %.c,%,$(SRCS)) +EXES:=$(patsubst %.cpp,%,$(EXES)) + +all: $(EXES) + +%: %.c + $(CC) -e -bc $< + $(CC) -e -n $< + $(CC) -e -O2 -bc $< + $(CC) -e -O2 -n $< + $(CC) -e -O0 -bc $< + $(CC) -e -O0 -n $< + $(CC) -e -Os -bc $< + $(CC) -e -Os -n $< + $(CC) -e -O3 -bc $< + $(CC) -e -O3 -n $< + +%: %.cpp + $(CXX) -e -bc $< + $(CXX) -e -n $< + $(CXX) -e -O2 -bc $< + $(CXX) -e -O2 -n $< + $(CXX) -e -O0 -bc $< + $(CXX) -e -O0 -n $< + $(CXX) -e -Os -bc $< + $(CXX) -e -Os -n $< + $(CXX) -e -O3 -bc $< + $(CXX) -e -O3 -n $< + +# testb +bitshifttes: bitshifttest.c + $(CC) -e -bc $< + $(CC) -e -bc -O2 $< + $(CC) -e -bc -O0 $< + $(CC) -e -bc -Os $< + $(CC) -e -bc -O3 $< + $(CC) -e -n $< + +# testn +stripedarraytes: stripedarraytest.c + $(CC) -e -O2 -n $< + $(CC) -e -O0 -n $< + $(CC) -e -Os -n $< + $(CC) -e -O3 -n $< + +clean: + $(RM) *.asm *.bcs *.int *.lbl *.map *.prg diff --git a/samples/memmap/charsetload.d64 b/samples/memmap/charsetload.d64 deleted file mode 100644 index ea91a386155aba5183c7a05d6e7a7fb6eb237590..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174848 zcmeI$acCRY9l-H-XW2QcmVHXxOsQOY@ytlF7Tm(RG!?FNmgUHpE@Ul~H4HCZApK*I zzg9y%C$8VKvp`nokFgHw&1)i)3v_cSO>o6oHEOzggjs(q$seBQfLYwk6d3|LimJU~ zHSI|JTxv$o`q_`a`4eP7neqpgL4U)1Ay-}m$5dZbVo zFBC?`Eu$bE;|)1z`u^Bnb2X60wpBe}tyZhct2%$_H!okx`??^Ft^SCfd-cM_xw$#* zPrm-vtnbSi!hgxw(rM zUY*l(%j?1V@|=tr>vC7aNVO7_SL9!`p^fv#m-6I*|9er(uX6qiS~UY4l7LQ7xXOnw^Il zbMcK<&s5ExP%Yj&%66V^^i1cmuqRYRH7nb@Qac`XQsLLcSb9o~Wn$iyBWcxp>P#l~ zym29yeqN~bLS52u+ z|FM2oh)&zK?Y%;XA7-=Jln~;X@4K$64j8T)Y&dk-9ZDw04;ZGjjihXeh(t1BCWNqu zY}=N{OxGPdd2c$M-en6RQmO2oRv|=Ym%S^koaW5F(4Y{*p_nr)5{@+Fz?fksLei*D z2odX$KRRg``edV=-Xer8Iy&|%d;8X{#~(f3(IKp^qlxW9n^(nMEZXFK^YqQIGCZN; zs%;<_sc+t}ru6%7L`s!crX%N?9bXT0?@t~4cF$7}9(eGe@Wgav^4exB#Z_A_GTnTx z#d%vh@8}6D7jcTZ|EWgLQ1OB3X8&4vAz2D}Vxws+eadMG=i;R;p017K3Du)As@vHa z&c#))^Yw5pz7bkTmh4=2=M$y-bG;i4syi3o_){)Eou0fFcD@nL^{99*(|@cn*Q2tr zoP8vt`f|PJTFzu|_LR(X|TaW~M|mB1GDEof07)}nE(r!w)$syNGh+#Km$v5i~t}E-LWpqhL9a5WFnPoTGPV!Dx)@g;zT2^L@ zT2>b8aED#j6+^XdM_ZGdQ`lhIb=~x!7)~Y!lgZ(6%ScMccv22-&LexxHcJ}Y+C-OW znr3^ONbf&z>@NQFvFVR*^q$GS|893F@Wf`omCp3P*r+1Y5$8Sa3Dq`Z)}q;2)GEHY zKj2*YZ0m|1P?1{D59A`}S{CX`A@A{0&&0#t2V@K+Sj+cxjue6RvKs&rH~gdg%^z4@4WZy<^`;h@0<;PI_{$W_0{kV zW8!NIk&@|!Z&h9!y;GOCZeMy|tu9Hp$%HH!UFsRbs?{a!?d|QYt(Hio zQrV}UONmr_tJT_`k};!I?rIpWO%0#cC2d7N_p8nFN$b_>{Oo0|3x!dC@~qan=&M-h zqw2gbWA(b|j})Zc9n1$optZg{>(5tHAs-dMyZ6wXW#fmCDkZF61x0{HCw< zV!2!{|5j`Lt(I=+}y>h>sssC>*ect38>5{UyfB4~vg%e9lI+*`i@z!Wr>wHjN$;&6K_4j7;@9Ih*i&|e@J+XRKYaImhK`qY+)I-L|sTXzzTGtji3c5J^*6WjgQ3q?+ zgCLmKMZbD`(I1gkbhYXi_3iRf{zRpsM+&1=X*U)9!l>^T^@v{ysSL+An+>#7q_ii*L_ioYHfVJ-Kn(tzm-Z)eWLrxsYg Date: Sat, 15 Jul 2023 22:32:07 +0200 Subject: [PATCH 037/169] Optimize long shifts --- oscar64/Declaration.cpp | 4 +- oscar64/InterCode.cpp | 36 +++++++- oscar64/InterCodeGenerator.cpp | 12 ++- oscar64/NativeCodeGenerator.cpp | 142 +++++++++++++++++++++++++++----- oscar64/NativeCodeGenerator.h | 1 + oscar64/Parser.cpp | 3 + 6 files changed, 173 insertions(+), 25 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index c278df5..a8ecab6 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1311,10 +1311,10 @@ bool Declaration::IsSameValue(const Declaration* dec) const bool Declaration::CanAssign(const Declaration* fromType) const { + if (fromType->mType == DT_TYPE_REFERENCE) + return this->CanAssign(fromType->mBase); if (mType == DT_TYPE_REFERENCE) return mBase->IsSubType(fromType); - else if (fromType->mType == DT_TYPE_REFERENCE) - return this->CanAssign(fromType->mBase); if (this->IsSame(fromType)) return true; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 4c209e4..91ce94e 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4682,7 +4682,7 @@ bool InterCodeBasicBlock::MergeSameConditionTraces(void) if (mb1 && mb1->mNumEntries == 2 && mb0 != mb1) { int tc = mInstructions.Last()->mSrc[0].mTemp; - if (tc == mb0->mInstructions.Last()->mSrc[0].mTemp) + if (tc >= 0 && tc == mb0->mInstructions.Last()->mSrc[0].mTemp) { if (!mTrueJump->mLocalModifiedTemps[tc] && !mFalseJump->mLocalModifiedTemps[tc] && !mb0->mLocalModifiedTemps[tc]) { @@ -6464,6 +6464,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray switch (ins->mOperator) { case IA_EXT8TO16S: + case IA_EXT8TO32S: vr = ins->mSrc[0].mRange; if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < -128 || vr.mMaxValue > 127) { @@ -6477,7 +6478,22 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray } break; + case IA_EXT16TO32S: + vr = ins->mSrc[0].mRange; + if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < -65536 || vr.mMaxValue > 65535) + { + vr.mMaxState = IntegerValueRange::S_BOUND; + vr.mMaxValue = 65535; + } + if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < -65536 || vr.mMinValue > 65535) + { + vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMinValue = -65536; + } + break; + case IA_EXT8TO16U: + case IA_EXT8TO32U: vr = ins->mSrc[0].mRange; if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < 0 || vr.mMaxValue > 255 || vr.mMinValue < 0 || vr.mMinState != IntegerValueRange::S_BOUND) @@ -6493,6 +6509,22 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray vr.mMinValue = 0; } break; + case IA_EXT16TO32U: + vr = ins->mSrc[0].mRange; + if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < 0 || vr.mMaxValue > 65535 || vr.mMinValue < 0 || + vr.mMinState != IntegerValueRange::S_BOUND) + { + vr.mMaxState = IntegerValueRange::S_BOUND; + vr.mMaxValue = 65535; + vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMinValue = 0; + } + if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < 0 || vr.mMinValue > 65535) + { + vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMinValue = 0; + } + break; default: vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND; @@ -10502,7 +10534,7 @@ bool InterCodeBasicBlock::ForwardDiamondMovedTemp(void) if (fblock && tblock) { - if (tblock->mInstructions[0]->IsEqual(fblock->mInstructions.Last()) && !fblock->mLocalModifiedTemps[tblock->mInstructions[0]->mSrc[0].mTemp]) + if (tblock->mInstructions[0]->IsEqual(fblock->mInstructions.Last()) && (tblock->mInstructions[0]->mSrc[0].mTemp < 0 || !fblock->mLocalModifiedTemps[tblock->mInstructions[0]->mSrc[0].mTemp])) { fblock->mTrueJump = tblock; fblock->mFalseJump = nullptr; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index aedb37d..6778906 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -83,7 +83,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p if (type->mType == DT_TYPE_REFERENCE) { - if (!type->mBase->IsSubType(v.mType)) + if (v.mType->mType == DT_TYPE_REFERENCE) + { + if (!type->mBase->IsSubType(v.mType->mBase)) + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Incompatible type for reference"); + } + else if (!type->mBase->IsSubType(v.mType)) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Incompatible type for reference"); return v; @@ -998,7 +1003,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro if (pdec) { if (!pdec->mBase->CanAssign(vr.mType)) + { + pdec->mBase->CanAssign(vr.mType); mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + } vr = CoerceType(proc, texp, block, vr, pdec->mBase); } else if (vr.mType->IsIntegerType() && vr.mType->mSize < 2) @@ -3221,7 +3229,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CALL); cins->mNumOperands = 1; - if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_NATIVE)) + if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_NATIVE) || (mCompilerOptions & COPT_NATIVE)) cins->mCode = IC_CALL_NATIVE; else cins->mCode = IC_CALL; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 50db1b2..16b1567 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -7434,6 +7434,75 @@ bool NativeCodeBasicBlock::CheckPredAccuStore(int reg) return true; } +void NativeCodeBasicBlock::ShiftRegisterRight(const InterInstruction* ins, int reg, int shift) +{ + if (shift == 0) + { + } + else if (shift == 1) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_ZERO_PAGE, reg + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, reg)); + } + else if (shift == 15) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 0)); + } + else if (shift == 14) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_AND, ASMIM_IMMEDIATE, 3)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); + } + else if (shift >= 8) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1)); + for (int i = 8; i < shift; i++) + mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0x00)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); + } + else if (shift >= 5) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, reg)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_ZERO_PAGE, reg + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STX, ASMIM_ZERO_PAGE, reg)); + + mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED)); + for (int i = shift; i < 8; i++) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_ZERO_PAGE, reg)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED)); + } + mIns.Push(NativeCodeInstruction(ins, ASMIT_AND, ASMIM_IMMEDIATE, 0xff >> shift)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, reg)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_ZERO_PAGE, reg + 1)); + + mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_IMPLIED)); + for (int i = 1; i < shift; i++) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_ZERO_PAGE, reg + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_IMPLIED)); + } + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); + } +} + void NativeCodeBasicBlock::ShiftRegisterLeft(InterCodeProcedure* proc, const InterInstruction* ins, int reg, int shift) { if (shift == 0) @@ -8687,7 +8756,23 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p int shift = ins->mSrc[0].mIntConst & 31; int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; - int nregs = 4; + int nvbits = 32; + if (ins->mSrc[1].IsUnsigned() && ins->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND) + { + int64 mv = ins->mSrc[1].mRange.mMaxValue; + while (nvbits > 0 && mv < (1LL << (nvbits - 1))) + nvbits--; + } + + if (shift >= nvbits) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3)); + return this; + } if (shift >= 24) { @@ -8699,7 +8784,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3)); sreg = treg; shift -= 24; - nregs = 1; + nvbits -= 24; } else if (shift >= 16) { @@ -8712,7 +8797,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3)); sreg = treg; shift -= 16; - nregs = 2; + nvbits -= 16; } else if (shift >= 8) { @@ -8727,7 +8812,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3)); sreg = treg; shift -= 8; - nregs = 3; + nvbits -= 8; } if (shift == 0) @@ -8800,9 +8885,6 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p } else { - NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); - NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); - if (sreg != treg) { mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, sreg)); @@ -8815,22 +8897,44 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3)); } - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, treg + nregs - 1)); + int nregs = (nvbits + 7) >> 3; - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_IMMEDIATE, shift)); - this->Close(ins, lblock, nullptr, ASMIT_JMP); + if ((nvbits & 7) == 1) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_ZERO_PAGE, treg + nregs - 1)); + for (int i = nregs - 1; i > 0; i--) + mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + i - 1)); + nvbits--; + nregs--; + shift--; + } - lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED)); - for(int i=nregs -1; i>0 ; i--) - lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + i - 1)); + if (nregs <= 2) + { + ShiftRegisterRight(ins, treg, shift); + } + else + { + NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); + NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); -// lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1)); -// lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0)); - lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_DEX, ASMIM_IMPLIED)); - lblock->Close(ins, lblock, eblock, ASMIT_BNE); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, treg + nregs - 1)); - eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + nregs - 1)); - return eblock; + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_IMMEDIATE, shift)); + this->Close(ins, lblock, nullptr, ASMIT_JMP); + + lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED)); + for (int i = nregs - 1; i > 0; i--) + lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + i - 1)); + + // lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1)); + // lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0)); + lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_DEX, ASMIM_IMPLIED)); + lblock->Close(ins, lblock, eblock, ASMIT_BNE); + + eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + nregs - 1)); + return eblock; + } } } else diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 9968ad7..6a37d13 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -352,6 +352,7 @@ public: void CallAssembler(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); + void ShiftRegisterRight( const InterInstruction* ins, int reg, int shift); void ShiftRegisterLeft(InterCodeProcedure* proc, const InterInstruction* ins, int reg, int shift); void ShiftRegisterLeftByte(InterCodeProcedure* proc, const InterInstruction* ins, int reg, int shift); void ShiftRegisterLeftFromByte(InterCodeProcedure* proc, const InterInstruction* ins, int reg, int shift, int max); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 07dd308..99507e2 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3453,6 +3453,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ldec && ldec != pdec) mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); } + else if (!pdec) + mErrors->Error(ndec->mLocation, EERR_OBJECT_NOT_FOUND, "Object not declarared in scope", ndec->mQualIdent); + } else pdec = mScope->Insert(ndec->mIdent, ndec); From 9cdfad7d34a9a2b9a329a2fdc4c5acb615655716 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 17 Jul 2023 07:52:59 +0200 Subject: [PATCH 038/169] Improve cpp code generation --- include/opp/string.cpp | 17 +++ include/opp/string.h | 3 + oscar64/Declaration.cpp | 25 ++++ oscar64/Declaration.h | 1 + oscar64/GlobalAnalyzer.cpp | 2 +- oscar64/InterCode.cpp | 2 +- oscar64/InterCode.h | 2 +- oscar64/InterCodeGenerator.cpp | 4 + oscar64/NativeCodeGenerator.cpp | 29 +++- oscar64/Parser.cpp | 246 ++++++++++++++++++++++++++++++-- oscar64/Parser.h | 2 + oscar64/Scanner.cpp | 18 ++- oscar64/Scanner.h | 3 + 13 files changed, 331 insertions(+), 23 deletions(-) diff --git a/include/opp/string.cpp b/include/opp/string.cpp index 5c15b2e..4973fda 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -44,6 +44,18 @@ string::string(const char * s) cstr = nullptr; } +string::string(const char * s, char size) +{ + if (size) + { + cstr = malloc(char(size + 2)); + cstr[0] = size; + smemcpy(cstr + 1, s, size + 1); + } + else + cstr = nullptr; +} + string::string(char c) { cstr = malloc(3); @@ -64,6 +76,11 @@ string::~string(void) free(cstr); } +void string::copyseg(char * p, char at, char num) const +{ + smemcpy(p, cstr + 1 + at, num); +} + string & string::operator=(const string & s) { if (cstr != s.cstr) diff --git a/include/opp/string.h b/include/opp/string.h index b2132f0..747c120 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -10,6 +10,7 @@ public: string(void); string(const string & s); string(const char * s); + string(const char * s, char size); string(char c); ~string(void); @@ -61,6 +62,8 @@ public: int find(const string & s, char pos) const; int find(const char * s, char pos) const; int find(char c, char pos) const; + + void copyseg(char * p, char at, char num) const; protected: string(char l, char * b); }; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index a8ecab6..21953ac 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1238,6 +1238,31 @@ bool Declaration::IsSameParams(const Declaration* dec) const return false; } +bool Declaration::IsDerivedFrom(const Declaration* dec) const +{ + if (mType != DT_TYPE_FUNCTION || dec->mType != DT_TYPE_FUNCTION) + return false; + + if (!(mFlags & DTF_FUNC_THIS) || !(dec->mFlags & DTF_FUNC_THIS)) + return false; + + if (!mBase->IsSame(dec->mBase)) + return false; + Declaration* dl = mParams->mNext, * dr = dec->mParams->mNext; + while (dl && dr) + { + if (!dl->mBase->IsSame(dr->mBase)) + return false; + dl = dl->mNext; + dr = dr->mNext; + } + + if (dl || dr) + return false; + + return true; +} + bool Declaration::IsSame(const Declaration* dec) const { if (this == dec) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index c13bfc5..89075ca 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -262,6 +262,7 @@ public: bool CanAssign(const Declaration* fromType) const; bool IsSame(const Declaration* dec) const; + bool IsDerivedFrom(const Declaration* dec) const; bool IsSubType(const Declaration* dec) const; bool IsConstSame(const Declaration* dec) const; bool IsSameValue(const Declaration* dec) const; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 64d3be3..d9d11fe 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -284,7 +284,7 @@ void GlobalAnalyzer::MarkRecursions(void) void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head) { - if (!(procDec->mBase->mFlags & DTF_FASTCALL) && !(procDec->mBase->mFlags & DTF_STACKCALL) && (procDec->mType == DT_CONST_FUNCTION) && !(procDec->mFlags & DTF_FUNC_ANALYZING)) + if (!(procDec->mBase->mFlags & DTF_FASTCALL) && (procDec->mType == DT_CONST_FUNCTION) && !(procDec->mFlags & DTF_FUNC_ANALYZING)) { procDec->mFlags |= DTF_FUNC_ANALYZING; int nbase = 0; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 91ce94e..d1f3d71 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -15331,7 +15331,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false), mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), - mCheckUnreachable(true), + mCheckUnreachable(true), mReturnType(IT_NONE), mDeclaration(nullptr) { mID = mModule->mProcedures.Size(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index b54cee6..d6ff5ea 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -604,7 +604,7 @@ public: LinkerObject * mLinkerObject, * mSaveTempsLinkerObject; Declaration * mDeclaration; - + InterType mReturnType; uint64 mCompilerOptions; InterCodeProcedure(InterCodeModule * module, const Location & location, const Ident * ident, LinkerObject* linkerObject); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 6778906..b939d3c 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -4591,6 +4591,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod proc->mCompilerOptions = mCompilerOptions; + dec->mVarIndex = proc->mID; dec->mLinkerObject = proc->mLinkerObject; proc->mNumLocals = dec->mNumVars; @@ -4632,7 +4633,10 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod proc->mFastCallBase = BC_REG_FPARAMS_END - BC_REG_FPARAMS; if (dec->mBase->mBase->mType != DT_TYPE_VOID && dec->mBase->mBase->mType != DT_TYPE_STRUCT) + { proc->mValueReturn = true; + proc->mReturnType = InterTypeOf(dec->mBase->mBase); + } InterCodeBasicBlock* entryBlock = new InterCodeBasicBlock(proc); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 16b1567..c854b74 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -40370,7 +40370,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "test_find"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "getchar"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -40425,7 +40425,25 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) // Place a temporary RTS - mExitBlock->mIns.Push(NativeCodeInstruction(nullptr, ASMIT_RTS, ASMIM_IMPLIED, 0, nullptr, 0)); + uint32 rflags = 0; + switch (proc->mReturnType) + { + case IT_BOOL: + case IT_INT8: + rflags = NCIF_LOWER; + break; + case IT_INT16: + case IT_POINTER: + rflags = NCIF_LOWER | NCIF_UPPER; + break; + case IT_INT32: + case IT_FLOAT: + rflags = NCIF_LOWER | NCIF_UPPER | NCIF_LONG; + break; + + } + + mExitBlock->mIns.Push(NativeCodeInstruction(nullptr, ASMIT_RTS, ASMIM_IMPLIED, 0, nullptr, rflags)); mEntryBlock->mTrueJump = CompileBlock(mInterProc, mInterProc->mBlocks[0]); mEntryBlock->mBranch = ASMIT_JMP; @@ -40443,7 +40461,6 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) } #endif #if 1 - if (mExitBlock->mIns[0].mFlags == NCIF_LOWER) if (mExitBlock->mIns[0].mFlags == NCIF_LOWER) { mExitBlock->mIns[0].mFlags = 0; @@ -41021,6 +41038,8 @@ void NativeCodeProcedure::Optimize(void) mEntryBlock->ReplaceFinalZeroPageUse(this); } #endif + + int t = 0; #if 1 do @@ -41029,8 +41048,8 @@ void NativeCodeProcedure::Optimize(void) BuildDataFlowSets(); ResetVisited(); - changed = mEntryBlock->RemoveUnusedResultInstructions(); + changed = mEntryBlock->RemoveUnusedResultInstructions(); if (step == 0) { @@ -41646,8 +41665,10 @@ void NativeCodeProcedure::Optimize(void) else cnt++; + } while (changed); + #if 1 ResetVisited(); mEntryBlock->ReduceLocalYPressure(); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 99507e2..8edbff8 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -28,8 +28,52 @@ Parser::~Parser(void) } +Declaration* Parser::FindBaseMemberFunction(Declaration* dec, Declaration* mdec) +{ + const Ident* ident = mdec->mIdent; + + if (ident->mString[0] == '~') + { + // this is the destructor, need special search + + Declaration * pdec = dec; + Declaration * pmdec = nullptr; + + while (pdec->mBase && !pmdec) + { + pdec = pdec->mBase->mBase; + pmdec = pdec->mScope->Lookup(pdec->mIdent->PreMangle("~")); + } + + return pmdec; + } + else + { + Declaration * pdec = dec; + Declaration * pmdec = nullptr; + + while (pdec->mBase && !pmdec) + { + pdec = pdec->mBase->mBase; + pmdec = pdec->mScope->Lookup(ident); + + while (pmdec && !mdec->mBase->IsDerivedFrom(pmdec->mBase)) + pmdec = pmdec->mNext; + + if (pmdec) + return pmdec; + } + + return pmdec; + } +} + void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec) { + Declaration* pmdec = FindBaseMemberFunction(dec, mdec); + if (pmdec) + mdec->mBase->mFlags |= pmdec->mBase->mFlags & DTF_VIRTUAL; + Declaration* gdec = mCompilationUnits->mScope->Insert(mdec->mQualIdent, mdec); if (gdec) { @@ -50,6 +94,7 @@ void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec) dec->mScope->Insert(mdec->mIdent, gdec); if (dec->mConst) dec->mConst->mScope->Insert(mdec->mIdent, gdec); + } else mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); @@ -341,7 +386,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) Declaration* vmpdec = nullptr; - while (vmdec && vmdec->mBase->IsSame(mdec->mBase)) + while (vmdec && !mdec->mBase->IsDerivedFrom(vmdec->mBase)) { vmpdec = vmdec; vmdec = vmdec->mNext; @@ -3162,6 +3207,48 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex return cdec; } + if ((mCompilerOptions & COPT_CPLUSPLUS) && pthis && mScanner->mToken == TK_OPERATOR) + { + mScanner->NextToken(); + bdec = ParseBaseTypeDeclaration(typeFlags, false); + + Declaration* ctdec = ParseFunctionDeclaration(bdec); + + if (ctdec->mParams) + mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Cast operators can't have parameter"); + + PrependThisArgument(ctdec, pthis); + + Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + cdec->mBase = ctdec; + + cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + ctdec->mFlags |= storageFlags & DTF_VIRTUAL; + + cdec->mSection = mCodeSection; + cdec->mBase->mFlags |= typeFlags; + + if (mCompilerOptions & COPT_NATIVE) + cdec->mFlags |= DTF_NATIVE; + + cdec->mIdent = Ident::Unique("(cast)"); + cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); + + if (mScanner->mToken == TK_OPEN_BRACE) + { + cdec->mCompilerOptions = mCompilerOptions; + cdec->mBase->mCompilerOptions = mCompilerOptions; + + cdec->mVarIndex = -1; + + cdec->mValue = ParseFunction(cdec->mBase); + + cdec->mFlags |= DTF_DEFINED | DTF_REQUEST_INLINE; + cdec->mNumVars = mLocalIndex; + } + + return cdec; + } bdec = ParseBaseTypeDeclaration(typeFlags, false); } @@ -3366,6 +3453,46 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex return bdec->mDestructor; } + else if (ConsumeTokenIf(TK_OPERATOR)) + { + Declaration* tdec = ParseBaseTypeDeclaration(0, true); + + Declaration* ctdec = ParseFunctionDeclaration(tdec); + + if (ctdec->mParams) + mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Cast operators can't have parameter"); + + Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + bthis->mFlags |= DTF_CONST | DTF_DEFINED; + if (ConsumeTokenIf(TK_CONST)) + bthis->mBase = bdec->ToConstType(); + else + bthis->mBase = bdec; + bthis->mSize = 2; + + PrependThisArgument(ctdec, bthis); + + Declaration* fdec = bdec->mScope->Lookup(Ident::Unique("(cast)")); + while (fdec && !fdec->mBase->IsSame(ctdec)) + fdec = fdec->mNext; + + if (fdec) + { + fdec->mCompilerOptions = mCompilerOptions; + fdec->mBase->mCompilerOptions = mCompilerOptions; + + fdec->mVarIndex = -1; + + fdec->mValue = ParseFunction(fdec->mBase); + + fdec->mFlags |= DTF_DEFINED; + fdec->mNumVars = mLocalIndex; + } + else + mErrors->Error(ctdec->mLocation, EERR_DUPLICATE_DEFINITION, "Cast operator not declared", tdec->mIdent); + + return fdec; + } } } @@ -4536,7 +4663,10 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) int ncast = 0; Declaration* ext = ex->mDecType; while (ext && !ext->IsConstSame(ptype->mBase)) + { + ncast++; ext = ext->mBase; + } if (ext) { @@ -4548,12 +4678,19 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) else return NOOVERLOAD; } - else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_ARRAY && ptype->mBase->IsSameMutable(etype->mBase)) + else if (ptype->mType == DT_TYPE_POINTER && (etype->mType == DT_TYPE_ARRAY || etype->mType == DT_TYPE_POINTER) && ptype->mBase->IsSameMutable(etype->mBase)) dist += 1; else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_FUNCTION && ptype->mBase->IsSame(etype)) dist += 0; else if (ptype->IsSubType(etype)) dist += 256; + else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->IsSame(etype)) + { + if (ex->mType == EX_VARIABLE) + dist += 1; + else + return NOOVERLOAD; + } else return NOOVERLOAD; @@ -4574,6 +4711,41 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) return dist; } +Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) +{ + Declaration* tdec = exp->mDecType; + while (tdec->mType == DT_TYPE_REFERENCE) + tdec = tdec->mBase; + + + if (tdec->mType == DT_TYPE_STRUCT) + { + Declaration* fexp = tdec->mScope->Lookup(Ident::Unique("(cast)")); + if (fexp) + { + while (fexp && !fexp->mBase->mBase->IsSame(type)) + fexp = fexp->mNext; + if (fexp) + { + Expression* aexp = new Expression(exp->mLocation, EX_PREFIX); + aexp->mToken = TK_BINARY_AND; + aexp->mDecType = tdec->BuildPointer(exp->mLocation); + aexp->mLeft = exp; + + Expression* nexp = new Expression(exp->mLocation, EX_CALL); + nexp->mLeft = new Expression(exp->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = fexp->mBase; + nexp->mLeft->mDecValue = fexp; + nexp->mRight = aexp; + + return nexp; + } + } + } + + return exp; +} + Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) { if (exp->mType == EX_CALL && exp->mLeft->mDecValue) @@ -4647,7 +4819,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) nexp->mRight = ParseExpression(false); ConsumeToken(TK_CLOSE_BRACKET); - if (exp->mDecType->mType == DT_TYPE_STRUCT) + if (exp->mDecType->mType == DT_TYPE_STRUCT || exp->mDecType->mType == DT_TYPE_REFERENCE && exp->mDecType->mBase->mType == DT_TYPE_STRUCT) { nexp = CheckOperatorOverload(nexp); } @@ -4899,6 +5071,8 @@ Expression* Parser::ParsePrefixExpression(bool lhs) mScanner->NextToken(); nexp = ParsePrefixExpression(false); nexp = nexp->LogicInvertExpression(); + nexp = CheckOperatorOverload(nexp); + } else if (mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC) { @@ -5403,9 +5577,9 @@ Expression* Parser::ParseLogicAndExpression(bool lhs) { Expression* nexp = new Expression(mScanner->mLocation, EX_LOGICAL_AND); nexp->mToken = mScanner->mToken; - nexp->mLeft = exp; + nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration); mScanner->NextToken(); - nexp->mRight = ParseBinaryOrExpression(false); + nexp->mRight = CoerceExpression(ParseBinaryOrExpression(false), TheBoolTypeDeclaration); nexp->mDecType = TheBoolTypeDeclaration; exp = nexp->ConstantFold(mErrors); } @@ -5421,9 +5595,9 @@ Expression* Parser::ParseLogicOrExpression(bool lhs) { Expression* nexp = new Expression(mScanner->mLocation, EX_LOGICAL_OR); nexp->mToken = mScanner->mToken; - nexp->mLeft = exp; + nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration); mScanner->NextToken(); - nexp->mRight = ParseLogicAndExpression(false); + nexp->mRight = CoerceExpression(ParseLogicAndExpression(false), TheBoolTypeDeclaration); nexp->mDecType = TheBoolTypeDeclaration; exp = nexp->ConstantFold(mErrors); } @@ -5438,7 +5612,7 @@ Expression* Parser::ParseConditionalExpression(bool lhs) if (mScanner->mToken == TK_QUESTIONMARK) { Expression* nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); - nexp->mLeft = exp; + nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration); mScanner->NextToken(); Expression* texp = new Expression(mScanner->mLocation, EX_SEQUENCE); nexp->mRight = texp; @@ -5578,6 +5752,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) else if (exp->mType == EX_INDEX) { Declaration* tdec = exp->mLeft->mDecType; + while (tdec->mType == DT_TYPE_REFERENCE) + tdec = tdec->mBase; + if (tdec->mType == DT_TYPE_STRUCT) { const Ident* opident = Ident::Unique("operator[]"); @@ -5599,7 +5776,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mLeft = exp->mLeft; texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = exp->mLeft->mDecType; + texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); @@ -5851,6 +6028,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) if (opident) { Declaration* tdec = exp->mLeft->mDecType; + while (tdec->mType == DT_TYPE_REFERENCE) + tdec = tdec->mBase; + if (tdec->mType == DT_TYPE_STRUCT) { Declaration* mdec = tdec->mScope->Lookup(opident); @@ -5870,7 +6050,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mLeft = exp->mLeft; texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = exp->mLeft->mDecType; + texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; nexp->mRight = texp; @@ -5883,6 +6063,44 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) } } } + else if (exp->mType == EX_LOGICAL_NOT) + { + const Ident* opident = Ident::Unique("operator!"); + Declaration* tdec = exp->mLeft->mDecType; + while (tdec->mType == DT_TYPE_REFERENCE) + tdec = tdec->mBase; + + if (tdec->mType == DT_TYPE_STRUCT) + { + Declaration* mdec = tdec->mScope->Lookup(opident); + if (mdec) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_CALL); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + nexp->mRight = exp->mRight; + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp->mLeft; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = tdec; + texp->mDecType->mSize = 2; + + nexp->mRight = texp; + + nexp = ResolveOverloadCall(nexp); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + + exp = nexp; + } + } + } } return exp; @@ -6080,7 +6298,7 @@ Expression* Parser::ParseStatement(void) case TK_IF: mScanner->NextToken(); exp = new Expression(mScanner->mLocation, EX_IF); - exp->mLeft = CleanupExpression(ParseParenthesisExpression()); + exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration); exp->mRight = new Expression(mScanner->mLocation, EX_ELSE); exp->mRight->mLeft = ParseStatement(); if (mScanner->mToken == TK_ELSE) @@ -6099,7 +6317,7 @@ Expression* Parser::ParseStatement(void) mScope = scope; exp = new Expression(mScanner->mLocation, EX_WHILE); - exp->mLeft = CleanupExpression(ParseParenthesisExpression()); + exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration); exp->mRight = ParseStatement(); mScope->End(mScanner->mLocation); @@ -6113,7 +6331,7 @@ Expression* Parser::ParseStatement(void) if (mScanner->mToken == TK_WHILE) { mScanner->NextToken(); - exp->mLeft = CleanupExpression(ParseParenthesisExpression()); + exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration); ConsumeToken(TK_SEMICOLON); } else @@ -6147,7 +6365,7 @@ Expression* Parser::ParseStatement(void) // Condition if (mScanner->mToken != TK_SEMICOLON) - conditionExp = CleanupExpression(ParseExpression(false)); + conditionExp = CoerceExpression(CleanupExpression(ParseExpression(false)), TheBoolTypeDeclaration); if (mScanner->mToken == TK_SEMICOLON) mScanner->NextToken(); diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 326787a..66f153c 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -50,6 +50,7 @@ protected: void ParseVariableInit(Declaration* ndec); void AddMemberFunction(Declaration* dec, Declaration* mdec); + Declaration* FindBaseMemberFunction(Declaration* dec, Declaration* mdec); Expression * AddFunctionCallRefReturned(Expression * exp); Expression* CleanupExpression(Expression* exp); @@ -88,6 +89,7 @@ protected: int OverloadDistance(Declaration* pdec, Expression* pexp); Expression * ResolveOverloadCall(Expression* exp, Expression * exp2 = nullptr); + Expression* CoerceExpression(Expression* exp, Declaration* type); Expression* ParseSimpleExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 06bc2fb..535736b 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -161,6 +161,7 @@ const char* TokenNames[] = "'new'", "'delete'", "'virtual'", + "'operator'", }; @@ -321,6 +322,7 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor) mDefines = new MacroDict(); mDefineArguments = nullptr; mToken = TK_NONE; + mUngetToken = TK_NONE; NextChar(); @@ -873,7 +875,12 @@ void Scanner::NextToken(void) void Scanner::NextRawToken(void) { - if (mToken != TK_EOF) + if (mUngetToken) + { + mToken = mUngetToken; + mUngetToken = TK_NONE; + } + else if (mToken != TK_EOF) { mToken = TK_ERROR; @@ -1480,6 +1487,9 @@ void Scanner::NextRawToken(void) case TK_BINARY_XOR: mTokenIdent = Ident::Unique("operator^"); break; + case TK_LOGICAL_NOT: + mTokenIdent = Ident::Unique("operator!"); + break; case TK_LEFT_SHIFT: mTokenIdent = Ident::Unique("operator<<"); @@ -1522,7 +1532,11 @@ void Scanner::NextRawToken(void) break; default: - mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "Invalid operator token"); + // dirty little hack to implement token preview, got to fix + // this with an infinit preview sequence at one point + mUngetToken = mToken; + mToken = TK_OPERATOR; + return; } mToken = TK_IDENT; diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 580ef40..51d8b0a 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -160,6 +160,7 @@ enum Token TK_NEW, TK_DELETE, TK_VIRTUAL, + TK_OPERATOR, NUM_TOKENS }; @@ -260,6 +261,8 @@ protected: MacroDict* mDefines, * mDefineArguments; + Token mUngetToken; + void StringToken(char terminator, char mode); void CharToken(char mode); bool NextChar(void); From 7b1b81aeb702974f3b82d4951b525111403088b4 Mon Sep 17 00:00:00 2001 From: Stefan Date: Tue, 18 Jul 2023 12:09:18 +0200 Subject: [PATCH 039/169] Fixed makefile (stupid typo) --- autotest/makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autotest/makefile b/autotest/makefile index 570d208..d54b0d5 100644 --- a/autotest/makefile +++ b/autotest/makefile @@ -31,7 +31,7 @@ all: $(EXES) $(CXX) -e -O3 -n $< # testb -bitshifttes: bitshifttest.c +bitshifttest: bitshifttest.c $(CC) -e -bc $< $(CC) -e -bc -O2 $< $(CC) -e -bc -O0 $< @@ -40,7 +40,7 @@ bitshifttes: bitshifttest.c $(CC) -e -n $< # testn -stripedarraytes: stripedarraytest.c +stripedarraytest: stripedarraytest.c $(CC) -e -O2 -n $< $(CC) -e -O0 -n $< $(CC) -e -Os -n $< From bd6db608023d3f53c1f52dd25c3f5ef4b2dd46c7 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 20 Jul 2023 14:46:10 +0200 Subject: [PATCH 040/169] Add iostream library --- include/opp/iostream.cpp | 1046 +++++++++++++++++++++++++++++++ include/opp/iostream.h | 238 +++++++ oscar64/Declaration.cpp | 13 +- oscar64/NativeCodeGenerator.cpp | 13 +- oscar64/Parser.cpp | 29 +- 5 files changed, 1325 insertions(+), 14 deletions(-) create mode 100644 include/opp/iostream.cpp create mode 100644 include/opp/iostream.h diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp new file mode 100644 index 0000000..88cc988 --- /dev/null +++ b/include/opp/iostream.cpp @@ -0,0 +1,1046 @@ +#include "iostream.h" + +ios::ios(void) + : mFlags(0), mState(0), mWidth(0), mPrecision(6), mFill(' ') +{} + +ios::~ios(void) +{ + +} + +char ios::fill(void) +{ + return mFill; +} + +char ios::fill(char fillch) +{ + char c = mFill; + mFill = fillch; + return c; +} + +char ios::width() const +{ + return mWidth; +} + +char ios::width(char wide) +{ + char w = mWidth; + mWidth = wide; + return w; +} + +char ios::precision() const +{ + return mPrecision; +} + +char ios::precision(char wide) +{ + char w = mPrecision; + mPrecision = wide; + return w; +} + +ios::fmtflags ios::flags(void) const +{ + return mFlags; +} + +ios::fmtflags ios::flags(ios::fmtflags f) +{ + fmtflags pf = mFlags; + mFlags = f; + return pf; +} + +ios::fmtflags ios::setf(ios::fmtflags f) +{ + fmtflags pf = mFlags; + mFlags |= f; + return pf; +} + +ios::fmtflags ios::setf(ios::fmtflags f, ios::fmtflags m) +{ + fmtflags pf = mFlags; + mFlags = (mFlags & ~m) | f; + return pf; +} + +ios::fmtflags ios::unsetf(ios::fmtflags f) +{ + fmtflags pf = mFlags; + mFlags &= ~f; + return pf; +} + +bool ios::good(void) const +{ + return mState == goodbit; +} + +bool ios::eof(void) const +{ + return (mState & eofbit) != 0; +} + +bool ios::fail(void) const +{ + return (mState & (badbit | failbit)) != 0; +} + +bool ios::bad(void) const +{ + return (mState & badbit) != 0; +} + +bool ios::operator!(void) const +{ + return fail(); +} + +ios::operator bool(void) +{ + return !fail(); +} + + +ios::statebits ios::rdstate(void) const +{ + return mState; +} + +void ios::clear(void) +{ + mState = goodbit; +} + + + + +ostream & endl(ostream & os) +{ + os.put('\n'); + return os; +} + + +iosetf setf(ios::fmtflags flags) +{ + return iosetf(flags); +} + +ostream & operator<<(ostream & os, const iosetf & s) +{ + os.setf(s.flags); + return os; +} + +iosetw setw(char width) +{ + return iosetw(width); +} + +ostream & operator<<(ostream & os, const iosetw & s) +{ + os.width(s.width); + return os; +} + + +iosetprecision setprecision(char precision) +{ + return iosetprecision(precision); +} + +ostream & operator<<(ostream & os, const iosetprecision & s) +{ + os.precision(s.precision); + return os; +} + + +iosetfill setfill(char fill) +{ + return iosetfill(fill); +} + +ostream & operator<<(ostream & os, const iosetfill & s) +{ + os.fill(s.fill); + return os; +} + +ostream::ostream(void) + {} + + +void ostream::bput(char ch) +{ +} + +ostream & ostream::put(char c) +{ + bput(c); + return * this; +} + +ostream & ostream::write(const char * s, int n) +{ + for(int i=0; i prefix) + bput(buffer[--size]); + } + + if (adj != left) + { + while (r > 0) + { + bput(mFill); + r--; + } + } + + while (size > 0) + bput(buffer[--size]); + + while (r > 0) + { + bput(mFill); + r--; + } + + mFlags = 0; + mWidth = 0; + mFill = ' '; +} + +void ostream::numput(unsigned n, char sign) +{ + char buffer[10]; + + char base = 10; + if (mFlags & hex) + base = 16; + else if (mFlags & oct) + base = 8; + + char i = 0; + char o = 'a' - 10; + if (mFlags & uppercase) + o = 'A' - 10; + + while (n) + { + char d = n % base; + n /= base; + + if (d < 10) + d += '0'; + else + d += o; + buffer[i++] = d; + } + + if (!i) + buffer[i++] = '0'; + char prefix = i; + if (sign) + buffer[i++] = sign; + + putnum(buffer, prefix, i); +} + +void ostream::numput(unsigned long n, char sign) +{ + char buffer[20]; + + char base = 10; + if (mFlags & hex) + base = 16; + else if (mFlags & oct) + base = 8; + + char i = 0; + char o = 'a' - 10; + if (mFlags & uppercase) + o = 'A' - 10; + + while (n) + { + char d = n % base; + n /= base; + + if (d < 10) + d += '0'; + else + d += o; + buffer[i++] = d; + } + + if (!i) + buffer[i++] = '0'; + char prefix = i; + if (sign) + buffer[i++] = sign; + + putnum(buffer, prefix, i); +} + + +ostream & ostream::operator<<(bool val) +{ + if (val) + bput('1'); + else + bput('0'); + return *this; +} + +ostream & ostream::operator<<(int val) +{ + if (val < 0) + numput((unsigned)-val, '-'); + else if (mFlags & showpos) + numput((unsigned)val, '+'); + else + numput((unsigned)val, 0); + return *this; +} + +ostream & ostream::operator<<(unsigned val) +{ + numput(val, 0); + return *this; +} + +ostream & ostream::operator<<(long val) +{ + if (val < 0) + numput(-val, '-'); + else if (mFlags & showpos) + numput(val, '+'); + else + numput(val, 0); + return *this; +} + +ostream & ostream::operator<<(unsigned long val) +{ + numput(val, 0); + return *this; +} + +static float fround5[] = { + 0.5e-0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6 +}; + +ostream & ostream::operator<<(float val) +{ + char buffer[20]; + + char d = 0; + + float f = val; + + if (f < 0.0) + { + f = -f; + buffer[d++] = '-'; + } + else if (mFlags & showpos) + buffer[d++] = '+'; + + char prefix = d; + + if (isinf(f)) + { + buffer[d++] = 'I'; + buffer[d++] = 'N'; + buffer[d++] = 'F'; + } + else + { + int exp = 0; + + char fdigits = mPrecision; + + if (f != 0.0) + { + while (f >= 1000.0) + { + f /= 1000; + exp += 3; + } + + while (f < 1.0) + { + f *= 1000; + exp -= 3; + } + + while (f >= 10.0) + { + f /= 10; + exp ++; + } + + } + + char digits = fdigits + 1; + bool fexp = mFlags & scientific; + + if (!(mFlags & fixed)) + { + if (exp > 3 || exp < 0) + fexp = true; + } + + if (!fexp) + { + while (exp < 0) + { + f /= 10.0; + exp++; + } + + digits = fdigits + exp + 1; + + if (digits < 7) + f += fround5[digits - 1]; + else + f += fround5[6]; + + if (f >= 10.0) + { + f /= 10.0; + fdigits--; + } + } + else + { + if (digits < 7) + f += fround5[digits - 1]; + else + f += fround5[6]; + + if (f >= 10.0) + { + f /= 10.0; + exp ++; + } + } + + + char pdigits = digits - fdigits; + + if (digits > 20) + digits = 20; + + if (pdigits == 0) + buffer[d++] = '0'; + + for(char i=0; i 6) + buffer[d++] = '0'; + else + { + int c = (int)f; + f -= (float)c; + f *= 10.0; + buffer[d++] = c + '0'; + } + } + + if (fexp) + { + buffer[d++] = 'E'; + if (exp < 0) + { + buffer[d++] = '-'; + exp = -exp; + } + else + buffer[d++] = '+'; + + buffer[d++] = exp / 10 + '0'; + buffer[d++] = exp % 10 + '0'; + } + } + + char r = 0; + if (d < mWidth) + r = mWidth - d; + + fmtflags adj = mFlags & adjustfield; + + char i = 0; + if (adj == internal) + { + while (i < prefix) + bput(buffer[i++]); + } + + if (adj != left) + { + while (r > 0) + { + bput(mFill); + r--; + } + } + + while (i < d) + bput(buffer[i++]); + + while (r > 0) + { + bput(mFill); + r--; + } + + mFlags = 0; + mWidth = 0; + mFill = ' '; + + return *this; +} + +ostream & ostream::operator<<(const char * p) +{ + char i = 0; + while (p[i]) + bput(p[i++]); + return *this; +} + +ostream & ostream::operator<<(const string & s) +{ + for(char i=0; i ' ') + { + unget(); + return; + } + } +} + + + +istream & istream::get(char & c) +{ + c = get(); + return *this; +} + +istream & istream::get(char * s, char size) +{ + return get(s, size, '\n'); +} + +istream & istream::get(char * s, char size, char delim) +{ + char i = 0; + while (i + 1 < size) + { + char c = get(); + if (c == delim) + { + unget(); + break; + } + s[i++] = c; + } + if (size) + s[i++] = 0; + return *this; +} + +istream & istream::getline(char * s, char size) +{ + return getline(s, size, '\n'); +} + +istream & istream::getline(char * s, char size, char delim) +{ + char i = 0; + while (i + 1 < size) + { + char c = get(); + if (c == delim) + break; + s[i++] = c; + } + if (size) + s[i++] = 0; + return *this; +} + +istream & istream::ignore(char size) +{ + ignore(size, '\n'); + return *this; +} + +istream & istream::ignore(char size, char delim) +{ + while (size) + { + char c = get(); + if (c == delim) + break; + size--; + } + + return *this; +} + +istream & istream::operator>>(bool & val) +{ + return *this; +} + +unsigned istream::getnum(void) +{ + doskipws(); + + fmtflags bflags = mFlags & basefield; + + char base = 10; + if (bflags == hex) + base = 16; + else if (bflags == oct) + base = 8; + + unsigned n = 0; + bool sign = false; + + char ch = get(); + if (ch == '-') + { + sign = true; + ch = get(); + } + else if (ch == '+') + ch = get(); + + if (ch == '0') + { + if (bflags == 0) + { + base = 8; + ch = get(); + if (ch == 'x' || ch == 'X') + { + base = 16; + ch = get(); + } + } + } + + bool digits = false; + for(;;) + { + if (ch >= '0' && ch <= '9') + n = n * base + (ch - '0'); + else if (base > 10 && ch >= 'A' && ch <= 'F') + n = n * base + (ch - 'A' + 10); + else if (base > 10 && ch >= 'a' && ch <= 'f') + n = n * base + (ch - 'a' + 10); + else + break; + ch = get(); + digits = true; + } + unget(); + + if (!digits) + mState |= failbit; + + if (sign) + return -n; + else + return n; +} + +unsigned long istream::getnuml(void) +{ + doskipws(); + + fmtflags bflags = mFlags & basefield; + + char base = 10; + if (bflags == hex) + base = 16; + else if (bflags == oct) + base = 8; + + unsigned long n = 0; + bool sign = false; + + char ch = get(); + if (ch == '-') + { + sign = true; + ch = get(); + } + else if (ch == '+') + ch = get(); + + if (ch == '0') + { + if (bflags == 0) + { + base = 8; + ch = get(); + if (ch == 'x' || ch == 'X') + { + base = 16; + ch = get(); + } + } + } + + bool digits = false; + for(;;) + { + if (ch >= '0' && ch <= '9') + n = n * base + (ch - '0'); + else if (base > 10 && ch >= 'A' && ch <= 'F') + n = n * base + (ch - 'A' + 10); + else if (base > 10 && ch >= 'a' && ch <= 'f') + n = n * base + (ch - 'a' + 10); + else + break; + ch = get(); + digits = true; + } + unget(); + + if (!digits) + mState |= failbit; + + if (sign) + return -n; + else + return n; +} + +float istream::getnumf(void) +{ + doskipws(); + + char cs = get(); + + bool sign = false; + if (cs == '-') + { + sign = true; + cs = get(); + } + else if (cs == '+') + cs = get(); + + if (cs >= '0' && cs <= '9' || cs == '.') + { + float vf = 0; + while (cs >= '0' && cs <= '9') + { + vf = vf * 10 + (int)(cs - '0'); + cs = get(); + } + + if (cs == '.') + { + float digits = 1.0; + cs = get(); + while (cs >= '0' && cs <= '9') + { + vf = vf * 10 + (int)(cs - '0'); + digits *= 10; + cs = get(); + } + vf /= digits; + } + + char e = 0; + bool eneg = false; + + if (cs == 'e' || cs == 'E') + { + cs = get(); + if (cs == '-') + { + eneg = true; + cs = get(); + } + else if (cs == '+') + { + cs = get(); + } + + while (cs >= '0' && cs <= '9') + { + e = e * 10 + cs - '0'; + cs = get(); + } + + } + + if (e) + { + if (eneg) + { + while (e > 6) + { + vf /= 1000000.0; + e -= 6; + } + vf /= tpow10[e]; + } + else + { + while (e > 6) + { + vf *= 1000000.0; + e -= 6; + } + vf *= tpow10[e]; + } + } + + if (sign) + return -vf; + else + return vf; + } + else + mState |= failbit; + + return 0; +} + +istream & istream::operator>>(int & val) +{ + val = getnum(); + return *this; +} + +istream & istream::operator>>(unsigned & val) +{ + val = getnum(); + return *this; +} + +istream & istream::operator>>(long & val) +{ + val = getnuml(); + return *this; +} + +istream & istream::operator>>(unsigned long & val) +{ + val = getnuml(); + return *this; +} + +istream & istream::operator>>(float & val) +{ + val = getnumf(); + return *this; +} + +istream & istream::operator>>(char * p) +{ + doskipws(); + char i = 0; + char c = get(); + while (c > ' ') + { + p[i++] = c; + c = get(); + } + return *this; +} + +cistream::cistream(void) +{} + +void cistream::refill(void) +{ + mBufferFill = 0; + mBufferPos = 0; + + char ch; + while (mBufferFill < 32) + { + char ch = getchar(); + mBuffer[mBufferFill++] = ch; + if (ch == '\n') + break; + } +} + +ostringstream::ostringstream(void) +{ + mBuffer = nullptr; + mBFill = mBSize = 0; +} + +ostringstream::~ostringstream(void) +{ + free(mBuffer); +} + +void ostringstream::bput(char ch) +{ + if (!mBuffer) + { + mBSize = 16; + mBFill = 0; + mBuffer = malloc(16); + } + else if (mBFill == mBSize) + { + mBSize *= 2; + char * b = malloc(mBSize); + for(char i=0; i mBSize) + { + free(mBuffer); + mBSize = mBFill; + mBuffer = malloc(mBSize); + } + str.copyseg(mBuffer, 0, mBFill); +} + +istringstream::istringstream(const string & str) + : mString(str), mSPos(0) +{} + +istringstream::~istringstream(void) +{} + +string istringstream::str(void) const +{ + return mString; +} + +void istringstream::str(const string & str) +{ + mString = str; + mSPos = 0; +} + + +void istringstream::refill(void) +{ + mBufferFill = 0; + mBufferPos = 0; + + char ch; + while (mSPos < mString.size() && mBufferFill < 32) + { + mBuffer[mBufferFill++] = mString[mSPos++]; + } +} diff --git a/include/opp/iostream.h b/include/opp/iostream.h new file mode 100644 index 0000000..b2cb0eb --- /dev/null +++ b/include/opp/iostream.h @@ -0,0 +1,238 @@ +#ifndef OPP_IOSTREAM_H +#define OPP_IOSTREAM_H + +#include + +class ios +{ +public: + + ios(void); + virtual ~ios(void); + + char fill() const; + char fill(char cillch); + + char width() const; + char width(char wide); + + char precision() const; + char precision(char prec); + + enum fmtflags + { + boolalpha = 0x0001, + dec = 0x0002, + fixed = 0x0004, + hex = 0x0008, + internal = 0x0010, + left = 0x0020, + oct = 0x0040, + right = 0x0080, + scientific = 0x0100, + showbase = 0x0200, + showpoint = 0x0400, + showpos = 0x0800, + skipws = 0x1000, + unitbuf = 0x2000, + uppercase = 0x3000, + + adjustfield = 0x00b0, + basefield = 0x004a, + floatfield = 0x0104 + }; + + enum statebits + { + goodbit = 0, + badbit = 1, + eofbit = 2, + failbit = 4, + }; + + fmtflags flags(void) const; + fmtflags flags(fmtflags f); + + fmtflags setf(fmtflags f); + fmtflags setf(fmtflags f, fmtflags m); + fmtflags unsetf(fmtflags f); + + bool good(void) const; + bool eof(void) const; + bool fail(void) const; + bool bad(void) const; + + bool operator!(void) const; + operator bool(void); + + statebits rdstate(void) const; + void clear(void); + +protected: + fmtflags mFlags; + statebits mState; + char mWidth; + char mPrecision; + char mFill; +}; + +class ostream; + +typedef ostream & (* manip)(ostream &); + +class ostream : public ios +{ +public: + ostream(void); + + ostream & put(char c); + ostream & write(const char * s, int n); + + ostream & operator<<(bool val); + ostream & operator<<(int val); + ostream & operator<<(unsigned val); + ostream & operator<<(long val); + ostream & operator<<(unsigned long val); + ostream & operator<<(float val); + + ostream & operator<<(const char * p); + ostream & operator<<(const string & s); + + ostream & operator<<(manip m); +protected: + void putnum(const char * buffer, char prefix, char size); + void numput(unsigned n, char sign); + void numput(unsigned long n, char sign); + + virtual void bput(char ch); +}; + +class istream : public ios +{ +public: + char get(void); + istream & get(char & c); + istream & get(char * s, char size); + istream & get(char * s, char size, char delim); + istream & getline(char * s, char size); + istream & getline(char * s, char size, char delim); + istream & ignore(char size); + istream & ignore(char size, char delim); + istream & putback(char c); + istream & unget(void); + + istream & operator>>(bool & val); + istream & operator>>(int & val); + istream & operator>>(unsigned & val); + istream & operator>>(long & val); + istream & operator>>(unsigned long & val); + istream & operator>>(float & val); + + istream & operator>>(char * p); + + istream(void); +protected: + char mBuffer[32]; + char mBufferPos, mBufferFill; + + virtual void refill(void); + + unsigned getnum(void); + unsigned long getnuml(void); + float getnumf(void); + + void doskipws(void); +}; + +class costream : public ostream +{ +public: + costream(void); + +protected: + void bput(char ch); +}; + +class cistream : public istream +{ +public: + cistream(void); + +protected: + void refill(void); +}; + +class ostringstream : public ostream +{ +public: + ostringstream(void); + ~ostringstream(void); + + string str(void) const; + void str(const string & str); +protected: + void bput(char ch); + + char * mBuffer; + char mBFill, mBSize; +}; + +class istringstream : public istream +{ +public: + istringstream(const string & str); + ~istringstream(void); + + string str(void) const; + void str(const string & str); +protected: + virtual void refill(void); + + string mString; + char mSPos; +}; + +ostream & endl(ostream & os); + +struct iosetf { + ios::fmtflags flags; + iosetf(ios::fmtflags flags_) : flags(flags_) {} +}; + +ostream & operator<<(ostream & os, const iosetf & s); + +iosetf setf(ios::fmtflags flags); + +struct iosetw { + char width; + iosetw(char width_) : width(width_) {} +}; + +iosetw setw(char width); + +ostream & operator<<(ostream & os, const iosetw & s); + +struct iosetprecision { + char precision; + iosetprecision(char precision_) : precision(precision_) {} +}; + +iosetprecision setprecision(char precision); + +ostream & operator<<(ostream & os, const iosetprecision & s); + + +struct iosetfill { + char fill; + iosetfill(char fill_) : fill(fill_) {} +}; + +iosetfill setfill(char fill); + +ostream & operator<<(ostream & os, const iosetfill & s); + + + +#pragma compile("iostream.cpp"); + +#endif diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 21953ac..240ffb2 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1284,7 +1284,18 @@ bool Declaration::IsSame(const Declaration* dec) const else if (mType == DT_TYPE_ENUM) return mIdent == dec->mIdent; else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) - return this->Stride() == dec->Stride() && mBase->IsSame(dec->mBase); + { + if (mBase->mType == DT_TYPE_STRUCT && dec->mBase->mType == DT_TYPE_STRUCT) + { + if (mBase->mQualIdent == dec->mBase->mQualIdent && + (mBase->mFlags & (DTF_CONST | DTF_VOLATILE)) == (dec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE))) + return true; + else + return false; + } + else + return this->Stride() == dec->Stride() && mBase->IsSame(dec->mBase); + } else if (mType == DT_TYPE_REFERENCE) return mBase->IsSame(dec->mBase); else if (mType == DT_TYPE_STRUCT) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index c854b74..2f78137 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -478,6 +478,9 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps) if (mType == ASMIT_RTS) { #if 1 + if (mFlags & NCIF_USE_CPU_REG_A) + requiredTemps += CPU_REG_A; + if (mFlags & NCIF_LOWER) { requiredTemps += BC_REG_ACCU; @@ -4189,6 +4192,12 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet& if (mType == ASMIT_RTS) { #if 1 + if (mFlags & NCIF_USE_CPU_REG_A) + { + if (!providedTemps[CPU_REG_A]) + requiredTemps += CPU_REG_A; + } + if (mFlags & NCIF_LOWER) { if (!providedTemps[BC_REG_ACCU + 0]) requiredTemps += BC_REG_ACCU + 0; @@ -15800,7 +15809,7 @@ bool NativeCodeBasicBlock::CrossBlockStoreLoadBypass(NativeCodeProcedure* proc) { mVisited = true; - if (mTrueJump && !mFalseJump && mIns.Size() > 0 && mTrueJump->mIns.Size() > 0) + if (mTrueJump && mTrueJump->mTrueJump && !mFalseJump && mIns.Size() > 0 && mTrueJump->mIns.Size() > 0) { int sz = mIns.Size(); @@ -40463,7 +40472,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) #if 1 if (mExitBlock->mIns[0].mFlags == NCIF_LOWER) { - mExitBlock->mIns[0].mFlags = 0; + mExitBlock->mIns[0].mFlags = NCIF_USE_CPU_REG_A; mExitBlock->mIns.Insert(0, NativeCodeInstruction(nullptr, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU)); mExitBlock->mExitRegA = true; proc->mLinkerObject->mFlags |= LOBJF_RET_REG_A; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 8edbff8..4ececfa 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -207,6 +207,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) Declaration* mlast = nullptr; for (;;) { + do {} while (ConsumeTokenIf(TK_SEMICOLON)); + if (ConsumeTokenIf(TK_PUBLIC)) { flags &= ~(DTF_PRIVATE | DTF_PROTECTED); @@ -252,9 +254,6 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mCompilerOptions & COPT_NATIVE) mdec->mFlags |= DTF_NATIVE; - if (!(mdec->mFlags & DTF_DEFINED)) - ConsumeToken(TK_SEMICOLON); - AddMemberFunction(dec, mdec); } else if ((mCompilerOptions & COPT_CPLUSPLUS) && mdec->mType == DT_ANON) @@ -329,14 +328,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) } else { - Declaration* mdec = dec->mParams; - while (mdec) - { - mdec->mOffset++; - mdec = mdec->mNext; - } vdec->mOffset = 0; - dec->mSize++; } vdec->mDefaultConstructor = new Declaration(dec->mLocation, DT_CONST_INTEGER); @@ -349,8 +341,19 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) vdec->mIdent = dec->mIdent; vdec->mQualIdent = dec->mQualIdent; mCompilationUnits->mVTableScope->Insert(vdec->mQualIdent, vdec); + } - dec->mVTable = vdec; + dec->mVTable = vdec; + + if (!dec->mBase) + { + Declaration* mdec = dec->mParams; + while (mdec) + { + mdec->mOffset++; + mdec = mdec->mNext; + } + dec->mSize++; } dec->mScope->Iterate([=](const Ident* ident, Declaration* mdec) @@ -3636,7 +3639,11 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (pdec) { if (!ndec->mBase->IsSame(pdec->mBase)) + { + ndec->mBase->IsSameParams(pdec->mBase); + ndec->mBase->IsSame(pdec->mBase); mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function declaration differs", ndec->mIdent); + } else if (ndec->mFlags & ~pdec->mFlags & (DTF_HWINTERRUPT | DTF_INTERRUPT | DTF_FASTCALL | DTF_NATIVE)) mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function call type declaration differs", ndec->mIdent); else From fbde581475984bcec8844c97c9125517ee694e7e Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 21 Jul 2023 22:07:19 +0200 Subject: [PATCH 041/169] Add file and string streams --- include/opp/ifstream.cpp | 21 +++++++++++ include/opp/ifstream.h | 24 ++++++++++++ include/opp/iostream.cpp | 80 +-------------------------------------- include/opp/iostream.h | 30 --------------- include/opp/ofstream.cpp | 29 ++++++++++++++ include/opp/ofstream.h | 27 ++++++++++++++ include/opp/sstream.cpp | 81 ++++++++++++++++++++++++++++++++++++++++ include/opp/sstream.h | 39 +++++++++++++++++++ 8 files changed, 223 insertions(+), 108 deletions(-) create mode 100644 include/opp/ifstream.cpp create mode 100644 include/opp/ifstream.h create mode 100644 include/opp/ofstream.cpp create mode 100644 include/opp/ofstream.h create mode 100644 include/opp/sstream.cpp create mode 100644 include/opp/sstream.h diff --git a/include/opp/ifstream.cpp b/include/opp/ifstream.cpp new file mode 100644 index 0000000..5807711 --- /dev/null +++ b/include/opp/ifstream.cpp @@ -0,0 +1,21 @@ +#include "ifstream.h" +#include + +ifstream::ifstream(char fnum, char device, char channel, const string & name) +{ + this->fnum = fnum; + krnio_setnam(name); + krnio_open(fnum, device, channel); +} + +ifstream::~ifstream(void) +{ + krnio_close(fnum); +} + +void ifstream::refill(void) +{ + mBufferPos = 0; + mBufferFill = krnio_read(fnum, mBuffer, 32); +} + diff --git a/include/opp/ifstream.h b/include/opp/ifstream.h new file mode 100644 index 0000000..42d59cc --- /dev/null +++ b/include/opp/ifstream.h @@ -0,0 +1,24 @@ +#ifndef OPP_IFSTREAM_H +#define OPP_IFSTREAM_H + +#include "iostream.h" +#include "string.h" + + +class ifstream : public istream +{ +public: + ifstream(char fnum, char device, char channel, const string & name); + ~ifstream(void); + +protected: + virtual void refill(void); + + char fnum; +}; + + + +#pragma compile("ifstream.cpp") + +#endif \ No newline at end of file diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp index 88cc988..01ad8ef 100644 --- a/include/opp/iostream.cpp +++ b/include/opp/iostream.cpp @@ -1,4 +1,6 @@ #include "iostream.h" +#include +#include ios::ios(void) : mFlags(0), mState(0), mWidth(0), mPrecision(6), mFill(' ') @@ -966,81 +968,3 @@ void cistream::refill(void) } } -ostringstream::ostringstream(void) -{ - mBuffer = nullptr; - mBFill = mBSize = 0; -} - -ostringstream::~ostringstream(void) -{ - free(mBuffer); -} - -void ostringstream::bput(char ch) -{ - if (!mBuffer) - { - mBSize = 16; - mBFill = 0; - mBuffer = malloc(16); - } - else if (mBFill == mBSize) - { - mBSize *= 2; - char * b = malloc(mBSize); - for(char i=0; i mBSize) - { - free(mBuffer); - mBSize = mBFill; - mBuffer = malloc(mBSize); - } - str.copyseg(mBuffer, 0, mBFill); -} - -istringstream::istringstream(const string & str) - : mString(str), mSPos(0) -{} - -istringstream::~istringstream(void) -{} - -string istringstream::str(void) const -{ - return mString; -} - -void istringstream::str(const string & str) -{ - mString = str; - mSPos = 0; -} - - -void istringstream::refill(void) -{ - mBufferFill = 0; - mBufferPos = 0; - - char ch; - while (mSPos < mString.size() && mBufferFill < 32) - { - mBuffer[mBufferFill++] = mString[mSPos++]; - } -} diff --git a/include/opp/iostream.h b/include/opp/iostream.h index b2cb0eb..00577d8 100644 --- a/include/opp/iostream.h +++ b/include/opp/iostream.h @@ -162,36 +162,6 @@ protected: void refill(void); }; -class ostringstream : public ostream -{ -public: - ostringstream(void); - ~ostringstream(void); - - string str(void) const; - void str(const string & str); -protected: - void bput(char ch); - - char * mBuffer; - char mBFill, mBSize; -}; - -class istringstream : public istream -{ -public: - istringstream(const string & str); - ~istringstream(void); - - string str(void) const; - void str(const string & str); -protected: - virtual void refill(void); - - string mString; - char mSPos; -}; - ostream & endl(ostream & os); struct iosetf { diff --git a/include/opp/ofstream.cpp b/include/opp/ofstream.cpp new file mode 100644 index 0000000..a447870 --- /dev/null +++ b/include/opp/ofstream.cpp @@ -0,0 +1,29 @@ +#include "ofstream.h" +#include + +ofstream::ofstream(char fnum, char device, char channel, const string & name) +{ + this->fnum = fnum; + krnio_setnam(name.tocstr()); + krnio_open(fnum, device, channel); + + mBufferFill = 0; +} + +ofstream::~ofstream(void) +{ + if (mBufferFill > 0) + krnio_write(fnum, mBuffer, mBufferFill); + krnio_close(fnum); +} + +void ofstream::bput(char ch) +{ + mBuffer[mBufferFill++] = ch; + if (mBufferFill == 32) + { + krnio_write(fnum, mBuffer, mBufferFill); + mBufferFill = 0; + } +} + diff --git a/include/opp/ofstream.h b/include/opp/ofstream.h new file mode 100644 index 0000000..65b47d9 --- /dev/null +++ b/include/opp/ofstream.h @@ -0,0 +1,27 @@ +#ifndef OPP_OFSTREAM_H +#define OPP_OFSTREAM_H + +#include "iostream.h" +#include "string.h" + + +class ofstream : public ostream +{ +public: + ofstream(char fnum, char device, char channel, const string & name); + ~ofstream(void); + +protected: + virtual void bput(char ch); + + char mBuffer[32]; + char mBufferFill; + + char fnum; +}; + + + +#pragma compile("ofstream.cpp") + +#endif diff --git a/include/opp/sstream.cpp b/include/opp/sstream.cpp new file mode 100644 index 0000000..ddf06ab --- /dev/null +++ b/include/opp/sstream.cpp @@ -0,0 +1,81 @@ +#include "sstream.h" +#include + +ostringstream::ostringstream(void) +{ + mBuffer = nullptr; + mBFill = mBSize = 0; +} + +ostringstream::~ostringstream(void) +{ + free(mBuffer); +} + +void ostringstream::bput(char ch) +{ + if (!mBuffer) + { + mBSize = 16; + mBFill = 0; + mBuffer = malloc(16); + } + else if (mBFill == mBSize) + { + mBSize *= 2; + char * b = malloc(mBSize); + for(char i=0; i mBSize) + { + free(mBuffer); + mBSize = mBFill; + mBuffer = malloc(mBSize); + } + str.copyseg(mBuffer, 0, mBFill); +} + +istringstream::istringstream(const string & str) + : mString(str), mSPos(0) +{} + +istringstream::~istringstream(void) +{} + +string istringstream::str(void) const +{ + return mString; +} + +void istringstream::str(const string & str) +{ + mString = str; + mSPos = 0; +} + + +void istringstream::refill(void) +{ + mBufferFill = 0; + mBufferPos = 0; + + char ch; + while (mSPos < mString.size() && mBufferFill < 32) + { + mBuffer[mBufferFill++] = mString[mSPos++]; + } +} diff --git a/include/opp/sstream.h b/include/opp/sstream.h new file mode 100644 index 0000000..686f65a --- /dev/null +++ b/include/opp/sstream.h @@ -0,0 +1,39 @@ +#ifndef OPP_SSTREAM_H +#define OPP_SSTREAM_H + +#include "iostream.h" + +class ostringstream : public ostream +{ +public: + ostringstream(void); + ~ostringstream(void); + + string str(void) const; + void str(const string & str); +protected: + void bput(char ch); + + char * mBuffer; + char mBFill, mBSize; +}; + +class istringstream : public istream +{ +public: + istringstream(const string & str); + ~istringstream(void); + + string str(void) const; + void str(const string & str); +protected: + virtual void refill(void); + + string mString; + char mSPos; +}; + + +#pragma compile("sstream.cpp") + +#endif From 9b2d90ec582dd985bac979af3e98066dccfb66ad Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 23 Jul 2023 11:19:26 +0200 Subject: [PATCH 042/169] Add autotest for string stream --- autotest/autotest.bat | 3 + autotest/opp_streamtest.cpp | 81 +++++++++++++++++++++++ include/opp/iostream.cpp | 13 ++-- include/opp/sstream.cpp | 5 +- oscar64/ByteCodeGenerator.cpp | 2 +- oscar64/InterCode.cpp | 116 +++++++++++++++++++++++++++++---- oscar64/InterCode.h | 4 +- oscar64/InterCodeGenerator.cpp | 16 ++++- oscar64/Parser.cpp | 11 ++++ 9 files changed, 227 insertions(+), 24 deletions(-) create mode 100644 autotest/opp_streamtest.cpp 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; From 33b7bee0476cf4354a77ce2034453c27626a3a2e Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 23 Jul 2023 13:51:24 +0200 Subject: [PATCH 043/169] Fastcall for virtual functions --- oscar64/GlobalAnalyzer.cpp | 56 ++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index d9d11fe..9a37e7f 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -306,7 +306,7 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head) nbase = n; } } -// procDec->mFlags |= DTF_DYNSTACK; + // procDec->mFlags |= DTF_DYNSTACK; } else CheckFastcall(cf, false); @@ -314,8 +314,8 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head) if (cf->mFlags & DTF_DYNSTACK) procDec->mFlags |= DTF_DYNSTACK; -// if (!(cf->mBase->mFlags & DTF_FASTCALL)) -// procDec->mBase->mFlags |= DTF_STACKCALL; + // if (!(cf->mBase->mFlags & DTF_FASTCALL)) + // procDec->mBase->mFlags |= DTF_STACKCALL; cf = cf->mBase; int n = cf->mFastCallBase + cf->mFastCallSize; @@ -323,6 +323,50 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head) nbase = n; } + if (procDec->mValue && procDec->mValue->mType == EX_DISPATCH) + { + Declaration* maxf = nullptr; + + for (int i = 0; i < procDec->mCalled.Size(); i++) + { + Declaration* cf = procDec->mCalled[i]; + + if (!maxf) + maxf = cf; + else if (!(maxf->mBase->mFlags & DTF_STACKCALL)) + { + if (cf->mBase->mFlags & DTF_STACKCALL) + maxf = cf; + else if (cf->mBase->mFastCallBase > maxf->mBase->mFastCallBase) + maxf = cf; + } + } + + for (int i = 0; i < procDec->mCalled.Size(); i++) + { + Declaration* cf = procDec->mCalled[i]; + + if (cf != maxf) + { + if (maxf->mBase->mFlags & DTF_STACKCALL) + { + cf->mBase->mFlags &= ~DTF_FASTCALL; + cf->mBase->mFlags |= DTF_STACKCALL; + } + + cf->mParams = maxf->mParams; + cf->mBase->mFastCallBase = cf->mFastCallBase = maxf->mBase->mFastCallBase; + cf->mBase->mFastCallSize = cf->mFastCallSize = maxf->mBase->mFastCallSize; + } + } + + procDec->mFastCallBase = procDec->mBase->mFastCallBase; + procDec->mFastCallSize = procDec->mBase->mFastCallSize; + procDec->mFlags &= ~DTF_FUNC_ANALYZING; + + return; + } + procDec->mFastCallBase = nbase; procDec->mFastCallSize = 0; procDec->mBase->mFastCallBase = nbase; @@ -336,7 +380,7 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head) } else if (procDec->mFlags & DTF_FUNC_RECURSIVE) { - if (head) +// if (head) procDec->mBase->mFlags |= DTF_STACKCALL; } else if (!(procDec->mBase->mFlags & DTF_VARIADIC) && !(procDec->mFlags & DTF_FUNC_VARIABLE) && !(procDec->mFlags & DTF_DYNSTACK)) @@ -675,7 +719,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo return exp->mDecValue->mBase; case EX_DISPATCH: Analyze(exp->mLeft, procDec, lhs); - RegisterCall(procDec, exp->mLeft->mDecType); +// RegisterCall(procDec, exp->mLeft->mDecType); break; case EX_VCALL: exp->mType = EX_CALL; @@ -950,7 +994,7 @@ void GlobalAnalyzer::RegisterProc(Declaration* to) { if (to->mType == DT_CONST_FUNCTION) { -#if 0 +#if 1 if (to->mBase->mFlags & DTF_VIRTUAL) { From 893aa7effa362b8fd6945e0984c95c3fa5eeb3a9 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 23 Jul 2023 17:41:56 +0200 Subject: [PATCH 044/169] Add late inlining step --- oscar64/InterCode.cpp | 247 ++++++++++++++++++++++++++++++++++++++++-- oscar64/InterCode.h | 7 +- 2 files changed, 245 insertions(+), 9 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 85c1f28..244da88 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4197,7 +4197,7 @@ bool InterInstruction::ConstantFolding(void) } -void InterOperand::Disassemble(FILE* file) +void InterOperand::Disassemble(FILE* file, InterCodeProcedure* proc) { static char typechars[] = "NBCILFP"; @@ -4232,7 +4232,35 @@ void InterOperand::Disassemble(FILE* file) } else if (mType == IT_POINTER) { - fprintf(file, "V%d+%d", mVarIndex, int(mIntConst)); + const char* vname = ""; + + if (mMemory == IM_LOCAL) + { + if (!proc->mLocalVars[mVarIndex]) + vname = "null"; + else if (!proc->mLocalVars[mVarIndex]->mIdent) + vname = ""; + else + vname = proc->mLocalVars[mVarIndex]->mIdent->mString; + } + else if (mMemory == IM_PROCEDURE) + { + if (mLinkerObject && mLinkerObject->mIdent) + vname = mLinkerObject->mIdent->mString; + } + else if (mMemory == IM_GLOBAL || mMemory == IM_PROCEDURE) + { + if (mVarIndex < 0) + vname = ""; + else if (!proc->mModule->mGlobalVars[mVarIndex]) + vname = "null"; + else if (!proc->mModule->mGlobalVars[mVarIndex]->mIdent) + vname = ""; + else + vname = proc->mModule->mGlobalVars[mVarIndex]->mIdent->mString; + } + + fprintf(file, "V(%d '%s')+%d ", mVarIndex, vname, int(mIntConst)); } else if (IsIntegerType(mType) || mType == IT_BOOL) { @@ -4378,7 +4406,7 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc) fprintf(file, "\t"); if (mDst.mTemp >= 0) - mDst.Disassemble(file); + mDst.Disassemble(file, proc); fprintf(file, "\t<-\t"); @@ -4421,7 +4449,7 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc) fprintf(file, ", "); if (mSrc[j].mType != IT_NONE) { - mSrc[j].Disassemble(file); + mSrc[j].Disassemble(file, proc); first = false; } } @@ -12334,6 +12362,149 @@ void InterCodeBasicBlock::SingleBlockLoopUnrolling(void) } } +static int FindStore(InterCodeBasicBlock* block, int pos, const InterOperand& op) +{ + while (pos > 0) + { + pos--; + InterInstruction* ins(block->mInstructions[pos]); + if (ins->mCode == IC_STORE && ins->mSrc[1].mTemp < 0) + { + if ((op.mMemory == IM_PARAM && ins->mSrc[1].mMemory == IM_FRAME || + op.mMemory == IM_FPARAM && ins->mSrc[1].mMemory == IM_FFRAME) && + op.mVarIndex == ins->mSrc[1].mVarIndex) + return pos; + } + } + + return -1; +} + +bool InterCodeBasicBlock::CheapInlining(int & numTemps) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* ins(mInstructions[i]); + + if (ins->mCode == IC_CALL_NATIVE && ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mLinkerObject && ins->mSrc[0].mLinkerObject->mProc && ins->mSrc[0].mLinkerObject->mProc->mCheapInline) + { + InterCodeBasicBlock* block = ins->mSrc[0].mLinkerObject->mProc->mEntryBlock; + + int ntemps = numTemps; + GrowingArray tmap(-1); + + bool fail = false; + for (int j = 0; j < block->mInstructions.Size(); j++) + { + InterInstruction* nins(block->mInstructions[j]); + if (nins->mCode == IC_LOAD && FindStore(this, i, nins->mSrc[0]) < 0) + fail = true; + } + + if (!fail) + { + for (int j = 0; j < i; j++) + mInstructions[j]->mRemove = false; + + mInstructions.Remove(i); + changed = true; + + for (int j = 0; j < block->mInstructions.Size(); j++) + { + InterInstruction* nins(block->mInstructions[j]); + switch (nins->mCode) + { + case IC_LOAD: + { + int k = FindStore(this, i, nins->mSrc[0]); + InterInstruction* pins = mInstructions[k]->Clone(); + mInstructions[k]->mRemove = true; + + if (pins->mSrc[0].mTemp < 0) + { + pins->mCode = IC_CONSTANT; + pins->mConst = pins->mSrc[0]; + pins->mNumOperands = 0; + } + else + { + pins->mCode = IC_LOAD_TEMPORARY; + pins->mNumOperands = 1; + } + + pins->mDst = nins->mDst; + pins->mDst.mTemp = ntemps; + mInstructions.Insert(k + 1, pins); + i++; + } break; + case IC_STORE: + { + InterInstruction* pins = nins->Clone(); + if (pins->mSrc[0].mTemp >= 0) + pins->mSrc[0].mTemp = tmap[pins->mSrc[0].mTemp]; + mInstructions.Insert(i, pins); + i++; + } break; + case IC_CALL: + case IC_CALL_NATIVE: + { + InterInstruction* pins = nins->Clone(); + if (pins->mDst.mTemp >= 0) + pins->mDst.mTemp = ntemps; + mInstructions.Insert(i, pins); + i++; + } break; + case IC_RETURN_VALUE: + { + if (ins->mDst.mTemp >= 0) + { + InterInstruction* pins = nins->Clone(); + pins->mCode = IC_LOAD_TEMPORARY; + pins->mDst = ins->mDst; + if (pins->mSrc[0].mTemp >= 0) + pins->mSrc[0].mTemp = tmap[pins->mSrc[0].mTemp]; + pins->mNumOperands = 1; + mInstructions.Insert(i, pins); + i++; + } + } break; + } + + if (nins->mDst.mTemp >= 0) + tmap[nins->mDst.mTemp] = ntemps++; + } + + numTemps = ntemps; + + for (int j = 0; j < i; j++) + { + if (mInstructions[j]->mRemove) + { + mInstructions[j]->mCode = IC_NONE; + mInstructions[j]->mDst.mTemp = -1; + mInstructions[j]->mNumOperands = 0; + } + } + } + } + } + + if (mTrueJump && mTrueJump->CheapInlining(numTemps)) + changed = true; + if (mFalseJump && mFalseJump->CheapInlining(numTemps)) + changed = true; + } + + return changed; +} + + void InterCodeBasicBlock::PushMoveOutOfLoop(void) { if (!mVisited) @@ -15417,7 +15588,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false), mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), - mCheckUnreachable(true), mReturnType(IT_NONE), + mCheckUnreachable(true), mReturnType(IT_NONE), mCheapInline(false), mDeclaration(nullptr) { mID = mModule->mProcedures.Size(); @@ -16262,7 +16433,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "test_find"); mEntryBlock = mBlocks[0]; @@ -16366,6 +16537,22 @@ void InterCodeProcedure::Close(void) DisassembleDebug("Global Constant Propagation"); + // Check for cheap inlining + // + + if (mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE) + { + ResetVisited(); + if (mEntryBlock->CheapInlining(numTemps)) + { + mValueForwardingTable.SetSize(numTemps, true); + mTemporaries.SetSize(numTemps, true); + + DisassembleDebug("Cheap Inlining"); + } + } + + // // // Now remove needless temporary moves, that appear due to // stack evaluation @@ -17071,6 +17258,53 @@ void InterCodeProcedure::Close(void) } } } + + if (!mEntryBlock->mTrueJump) + { + int nconst = 0, nvariables = 0, nparams = 0, ncalls = 0, nret = 0, nother = 0; + for (int i = 0; i < mEntryBlock->mInstructions.Size(); i++) + { + InterInstruction* ins = mEntryBlock->mInstructions[i]; + switch (ins->mCode) + { + case IC_LOAD: + if (ins->mSrc[0].mTemp < 0) + { + if (ins->mSrc[0].mMemory == IM_FPARAM || ins->mSrc[0].mMemory == IM_PARAM) + nparams++; + else if (ins->mSrc[0].mMemory == IM_GLOBAL || ins->mSrc[0].mMemory == IM_ABSOLUTE) + nvariables++; + else + nother++; + } + else + nother++; + break; + case IC_STORE: + if (ins->mSrc[1].mTemp >= 0 || (ins->mSrc[1].mMemory != IM_FFRAME && ins->mSrc[1].mMemory != IM_FRAME)) + nother++; + if (ins->mSrc[0].mTemp < 0) + nconst++; + break; + case IC_CALL: + case IC_CALL_NATIVE: + if (ins->mSrc[0].mTemp < 0) + ncalls++; + else + nother++; + break; + case IC_RETURN: + case IC_RETURN_VALUE: + nret++; + break; + default: + nother++; + } + } + + if (nother == 0 && ncalls == 1 && nret == 1 && nconst < 2) + mCheapInline = true; + } } void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc) @@ -17138,7 +17372,6 @@ void InterCodeProcedure::SingleTailLoopOptimization(InterMemory paramMemory) } while (changed); } - void InterCodeProcedure::MapVariables(void) { ResetVisited(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 72efbf4..b39c3f5 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -285,7 +285,7 @@ public: bool IsNotUByte(void) const; - void Disassemble(FILE* file); + void Disassemble(FILE* file, InterCodeProcedure* proc); }; class InterInstruction @@ -299,7 +299,7 @@ public: InterOperator mOperator; int mNumOperands; - bool mInUse, mInvariant, mVolatile, mExpensive, mSingleAssignment, mNoSideEffects, mConstExpr; + bool mInUse, mInvariant, mVolatile, mExpensive, mSingleAssignment, mNoSideEffects, mConstExpr, mRemove; InterInstruction(const Location& loc, InterCode code); @@ -528,6 +528,8 @@ public: InterInstruction* FindTempOrigin(int temp) const; + bool CheapInlining(int & numTemps); + void CheckFinalLocal(void); void CheckFinal(void); void CheckBlocks(void); @@ -593,6 +595,7 @@ public: bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack; bool mCheckUnreachable; GrowingInterCodeProcedurePtrArray mCalledFunctions; + bool mCheapInline; InterCodeModule * mModule; int mID; From b8a993aa34b4e8e65eec9a444f89b9e9e213650e Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 23 Jul 2023 18:23:11 +0200 Subject: [PATCH 045/169] Bump version number --- README.md | 6 +- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 +- oscar64setup/oscar64setup.vdproj | 214 ++++++++++++++++++++++++++++++- 4 files changed, 220 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 4e118ca..b3f41e7 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ After extensive optimizations it turns out, that the interpreted code is not sig ## Limits and Errors -There are still several open areas, but most targets have been reached. The current Dhrystone performance is 94 iterations per second with byte code (11696) and 395 iterations with native code (10425 Bytes). This clearly shows that Dhrystone is not a valid benchmark for optimizing compilers, because it puts the 6502 on par with a 4MHz 8088 or 68k, which it clearly is not. +There are still several open areas, but most targets have been reached. The current +stone performance is 94 iterations per second with byte code (11696) and 395 iterations with native code (10425 Bytes). This clearly shows that Dhrystone is not a valid benchmark for optimizing compilers, because it puts the 6502 on par with a 4MHz 8088 or 68k, which it clearly is not. ### Language @@ -58,11 +59,12 @@ Supported Features: * reference types * member functions * constructors and destructors -* operator overloading (not complete yet) +* operator overloading * single inheritance of class and struct * const member functions * new, delete, new[] and delete[] * virtual member functions +* string and iostream classes ## Installation and Usage diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 18bcde9..825eb2b 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.22.210"); + strcpy(strProductVersion, "1.23.211"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 3dca3fd..65dc55b 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,22,210,0 - PRODUCTVERSION 1,22,210,0 + FILEVERSION 1,23,211,0 + PRODUCTVERSION 1,23,211,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.22.210.0" + VALUE "FileVersion", "1.23.211.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.22.210.0" + VALUE "ProductVersion", "1.23.211.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 6d0410c..df337d0 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -52,6 +52,12 @@ } "Entry" { + "MsmKey" = "8:_071CF34574024DBD95D2203D6E4279D0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_0819C3D33D0942EF9E319C754E6C43D8" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -130,6 +136,12 @@ } "Entry" { + "MsmKey" = "8:_1A605A19ADAD413CB754523D4FE7C32F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_1AAB1F90101E40B6937A64FD4BF9D469" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -418,6 +430,12 @@ } "Entry" { + "MsmKey" = "8:_63A827ECF1BC48CE96DB82B554FC323D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_64C12019C1114C3282B32CD6B866C20A" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -496,6 +514,12 @@ } "Entry" { + "MsmKey" = "8:_7789738FE8854CE488C5248434E47211" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_79985361F09A43299E258E1A8E5ED934" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -562,6 +586,12 @@ } "Entry" { + "MsmKey" = "8:_85AF458C41734A099F879A01E6CEB35F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_8827B6B07A1C4B32B08DF784E090381D" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -676,6 +706,12 @@ } "Entry" { + "MsmKey" = "8:_A14BC161099E420286E6A1595596D0F0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_A18504BA88CE40128ED44BD1854F0A33" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -712,6 +748,12 @@ } "Entry" { + "MsmKey" = "8:_A62BFFC051304130B85007261BC97749" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_A8820F3446B9408E88692E85817C1B07" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -952,6 +994,12 @@ } "Entry" { + "MsmKey" = "8:_D651A6B3342C4D1ABC7FE873E253A1C5" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_D76DA8C7D3964C93ABE193A7B53A0A9B" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1343,6 +1391,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_071CF34574024DBD95D2203D6E4279D0" + { + "SourcePath" = "8:..\\include\\opp\\iostream.h" + "TargetName" = "8:iostream.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0819C3D33D0942EF9E319C754E6C43D8" { "SourcePath" = "8:..\\include\\gfx\\bitmap.h" @@ -1603,6 +1671,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1A605A19ADAD413CB754523D4FE7C32F" + { + "SourcePath" = "8:..\\include\\opp\\sstream.cpp" + "TargetName" = "8:sstream.cpp" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1AAB1F90101E40B6937A64FD4BF9D469" { "SourcePath" = "8:..\\include\\setjmp.c" @@ -2563,6 +2651,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_63A827ECF1BC48CE96DB82B554FC323D" + { + "SourcePath" = "8:..\\include\\opp\\iostream.cpp" + "TargetName" = "8:iostream.cpp" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_64C12019C1114C3282B32CD6B866C20A" { "SourcePath" = "8:..\\include\\c64\\reu.h" @@ -2823,6 +2931,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7789738FE8854CE488C5248434E47211" + { + "SourcePath" = "8:..\\include\\opp\\ifstream.h" + "TargetName" = "8:ifstream.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_79985361F09A43299E258E1A8E5ED934" { "SourcePath" = "8:..\\include\\gfx\\mcbitmap.c" @@ -3043,6 +3171,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_85AF458C41734A099F879A01E6CEB35F" + { + "SourcePath" = "8:..\\include\\opp\\ofstream.cpp" + "TargetName" = "8:ofstream.cpp" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8827B6B07A1C4B32B08DF784E090381D" { "SourcePath" = "8:..\\samples\\memmap\\tsr.c" @@ -3423,6 +3571,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A14BC161099E420286E6A1595596D0F0" + { + "SourcePath" = "8:..\\include\\opp\\ofstream.h" + "TargetName" = "8:ofstream.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A18504BA88CE40128ED44BD1854F0A33" { "SourcePath" = "8:..\\samples\\memmap\\easyflashreloc.c" @@ -3543,6 +3711,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A62BFFC051304130B85007261BC97749" + { + "SourcePath" = "8:..\\include\\opp\\sstream.h" + "TargetName" = "8:sstream.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A8820F3446B9408E88692E85817C1B07" { "SourcePath" = "8:..\\samples\\make.bat" @@ -4343,6 +4531,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D651A6B3342C4D1ABC7FE873E253A1C5" + { + "SourcePath" = "8:..\\include\\opp\\ifstream.cpp" + "TargetName" = "8:ifstream.cpp" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D76DA8C7D3964C93ABE193A7B53A0A9B" { "SourcePath" = "8:..\\samples\\stdio\\make.bat" @@ -5296,15 +5504,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{9E7AB7F5-BA83-4377-B177-3D121EF176EB}" - "PackageCode" = "8:{2B7BCA1C-B5B7-47D2-8A8A-A8C694463BE0}" + "ProductCode" = "8:{E5A90B4B-CA2A-43EC-9597-90010989AF33}" + "PackageCode" = "8:{C6265FB3-0498-45EF-827C-27788C57AFAF}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.22.210" + "ProductVersion" = "8:1.23.211" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 6cfa24b8addf9e994414f25a0c52feb4ec13449f Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 24 Jul 2023 19:03:34 +0200 Subject: [PATCH 046/169] Fix over eager constant propagation --- oscar64/InterCode.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 244da88..e525c1c 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -5729,6 +5729,8 @@ void InterCodeBasicBlock::CollectConstTemps(GrowingInstructionPtrArray& ctemps, { if (mInstructions[i]->mCode == IC_CONSTANT) ltemps[ttemp] = mInstructions[i]; + else + ltemps[ttemp] = nullptr; if (assignedTemps[ttemp]) ctemps[ttemp] = nullptr; @@ -15522,7 +15524,7 @@ void InterCodeBasicBlock::Disassemble(FILE* file, bool dumpSets) 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); + fprintf(file, " %s\n", mInstructions[0]->mLocation.mFileName); else fprintf(file, "\n"); @@ -16433,7 +16435,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "test_find"); + CheckFunc = !strcmp(mIdent->mString, "tile_draw_g"); mEntryBlock = mBlocks[0]; From df28d2f83f00a9f07607507d9fc898c8d2b1f6e5 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 24 Jul 2023 22:19:35 +0200 Subject: [PATCH 047/169] Value forwarding abs,x and abs,y --- oscar64/NativeCodeGenerator.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 2f78137..74b5984 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -3928,6 +3928,12 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT mMode = ASMIM_IMPLIED; changed = true; } + else if (data.mRegs[CPU_REG_A].mMode == NRDM_ABSOLUTE_X && data.mRegs[CPU_REG_A].mLinkerObject == mLinkerObject && data.mRegs[CPU_REG_A].mValue == mAddress) + { + mType = ASMIT_TAY; + mMode = ASMIM_IMPLIED; + changed = true; + } else { data.mRegs[CPU_REG_Y].mMode = NRDM_ABSOLUTE_X; @@ -3985,6 +3991,12 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT mMode = ASMIM_IMPLIED; changed = true; } + else if (data.mRegs[CPU_REG_A].mMode == NRDM_ABSOLUTE_Y && data.mRegs[CPU_REG_A].mLinkerObject == mLinkerObject && data.mRegs[CPU_REG_A].mValue == mAddress) + { + mType = ASMIT_TAX; + mMode = ASMIM_IMPLIED; + changed = true; + } else { data.mRegs[CPU_REG_X].mMode = NRDM_ABSOLUTE_Y; From adda4044ca66c1c04744988b2531cdbe50fb8bd6 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 24 Jul 2023 22:23:37 +0200 Subject: [PATCH 048/169] Complete value forwardign abs,x and abs,y --- oscar64/NativeCodeGenerator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 74b5984..8bd9f33 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -3932,6 +3932,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT { mType = ASMIT_TAY; mMode = ASMIM_IMPLIED; + data.mRegs[CPU_REG_Y] = data.mRegs[CPU_REG_A]; changed = true; } else @@ -3995,6 +3996,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT { mType = ASMIT_TAX; mMode = ASMIM_IMPLIED; + data.mRegs[CPU_REG_X] = data.mRegs[CPU_REG_A]; changed = true; } else From 07323b12f9f4bd4983414e34163f9fc525ce48a3 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 25 Jul 2023 11:19:00 +0200 Subject: [PATCH 049/169] Static init of structs with base classes --- oscar64/Parser.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index c4175e0..97a0d18 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1215,18 +1215,37 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) } else { - Declaration* mdec = dtype->mParams; - while (mdec) + ExpandingArray path; + + Declaration* ttype = dtype; + while (ttype->mBase) + { + path.Push(ttype); + ttype = ttype->mBase->mBase; + } + + Declaration* mdec = ttype->mParams; + for(;;) { if (ConsumeTokenIf(TK_DOT)) { if (mScanner->mToken == TK_IDENT) { - Declaration* ndec = dtype->mScope->Lookup(mScanner->mTokenIdent); + ttype = dtype; + + path.SetSize(0); + Declaration* ndec = ttype->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_SCOPE); + while (!ndec && ttype->mBase) + { + path.Push(ttype); + ttype = ttype->mBase->mBase; + ndec = ttype->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_SCOPE); + } + if (ndec) mdec = ndec; else - mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "Struct member not found"); + mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "Struct member not found", mScanner->mTokenIdent); mScanner->NextToken(); ConsumeToken(TK_ASSIGN); @@ -1234,6 +1253,9 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) else mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "Identifier expected"); } + + if (!mdec) + break; Expression* texp = ParseInitExpression(mdec->mBase); @@ -1247,7 +1269,10 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) if (!ConsumeTokenIf(TK_COMMA)) break; + mdec = mdec->mNext; + while (!mdec && path.Size()) + mdec = path.Pop()->mParams; } } From d8f31b170d13c2dead6ef47f6049f50ae22c012b Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 25 Jul 2023 14:37:00 +0200 Subject: [PATCH 050/169] Mangle constructor name --- oscar64/Parser.cpp | 50 +++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 97a0d18..a2a5f9d 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -421,7 +421,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) AddDefaultConstructors(pthis); // Lookup constructors, have same name as class - Declaration* cdec = dec->mScope->Lookup(dec->mIdent, SLEVEL_SCOPE); + Declaration* cdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+"), SLEVEL_SCOPE); while (cdec) { if (cdec->mFlags & DTF_DEFINED) @@ -1420,7 +1420,7 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) Expression* Parser::BuildMemberInitializer(Expression* vexp) { - Declaration* fcons = (vexp->mDecType->mType == DT_TYPE_STRUCT && vexp->mDecType->mScope) ? vexp->mDecType->mScope->Lookup(vexp->mDecType->mIdent) : nullptr; + Declaration* fcons = (vexp->mDecType->mType == DT_TYPE_STRUCT && vexp->mDecType->mScope) ? vexp->mDecType->mScope->Lookup(vexp->mDecType->mIdent->PreMangle("+")) : nullptr; if (fcons) { @@ -1734,15 +1734,13 @@ void Parser::AddDefaultConstructors(Declaration* pthis) bool inlineDestructor = true; bool inlineConstructor = true; - char dname[100]; - strcpy_s(dname, "~"); - strcat_s(dname, pthis->mBase->mIdent->mString); - const Ident * dtorident = Ident::Unique(dname); + const Ident* dtorident = pthis->mBase->mIdent->PreMangle("~");; + const Ident* ctorident = pthis->mBase->mIdent->PreMangle("+");; // Extract constructor and destructor from scope - Declaration* cdec = pthis->mBase->mScope->Lookup(pthis->mBase->mIdent, SLEVEL_SCOPE); + Declaration* cdec = pthis->mBase->mScope->Lookup(ctorident, SLEVEL_SCOPE); while (cdec) { Declaration* ctdec = cdec->mBase; @@ -1899,7 +1897,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) pthis->mBase->mDefaultConstructor = cdec; - cdec->mIdent = pthis->mBase->mIdent; + cdec->mIdent = ctorident; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); AddMemberFunction(pthis->mBase, cdec); @@ -1951,7 +1949,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) pthis->mBase->mCopyConstructor = cdec; - cdec->mIdent = pthis->mBase->mIdent; + cdec->mIdent = ctorident; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); AddMemberFunction(pthis->mBase, cdec); @@ -2288,7 +2286,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) pthis->mBase->mVectorConstructor = cdec; - cdec->mIdent = pthis->mBase->mIdent; + cdec->mIdent = ctorident; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); cdec->mCompilerOptions = mCompilerOptions; @@ -2364,10 +2362,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) pthis->mBase->mVectorDestructor = cdec; - char dname[100]; - strcpy_s(dname, "~"); - strcat_s(dname, pthis->mBase->mIdent->mString); - cdec->mIdent = Ident::Unique(dname); + cdec->mIdent = dtorident; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); cdec->mCompilerOptions = mCompilerOptions; @@ -2452,7 +2447,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) pthis->mBase->mVectorCopyConstructor = cdec; - cdec->mIdent = pthis->mBase->mIdent; + cdec->mIdent = ctorident; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); cdec->mCompilerOptions = mCompilerOptions; @@ -2553,7 +2548,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) pthis->mBase->mVectorCopyAssignment = cdec; - cdec->mIdent = pthis->mBase->mIdent; + cdec->mIdent = ctorident; cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); cdec->mCompilerOptions = mCompilerOptions; @@ -3001,7 +2996,7 @@ void Parser::ParseVariableInit(Declaration* ndec) else mScanner->NextToken(); - Declaration* fcons = ndec->mBase->mScope ? ndec->mBase->mScope->Lookup(ndec->mBase->mIdent, SLEVEL_CLASS) : nullptr; + Declaration* fcons = ndec->mBase->mScope ? ndec->mBase->mScope->Lookup(ndec->mBase->mIdent->PreMangle("+"), SLEVEL_CLASS) : nullptr; if (fcons) { @@ -3225,10 +3220,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (mCompilerOptions & COPT_NATIVE) cdec->mFlags |= DTF_NATIVE; - char dname[100]; - strcpy_s(dname, "~"); - strcat_s(dname, pthis->mBase->mIdent->mString); - cdec->mIdent = Ident::Unique(dname); + cdec->mIdent = pthis->mBase->mIdent->PreMangle("~"); cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); if (mScanner->mToken == TK_OPEN_BRACE) @@ -3314,7 +3306,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (mCompilerOptions & COPT_NATIVE) cdec->mFlags |= DTF_NATIVE; - Declaration* pdec = pthis->mBase->mScope ? pthis->mBase->mScope->Lookup(pthis->mBase->mIdent, SLEVEL_CLASS) : nullptr; + Declaration* pdec = pthis->mBase->mScope ? pthis->mBase->mScope->Lookup(pthis->mBase->mIdent->PreMangle("+"), SLEVEL_CLASS) : nullptr; if (pdec) { while (pdec && !cdec->mBase->IsSameParams(pdec->mBase)) @@ -3348,7 +3340,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec = pdec; } - cdec->mIdent = pthis->mBase->mIdent; + cdec->mIdent = pthis->mBase->mIdent->PreMangle("+"); cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent); // Initializer list @@ -3396,7 +3388,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex PrependThisArgument(ctdec, bthis); - Declaration* cdec = bdec->mScope->Lookup(bdec->mIdent, SLEVEL_CLASS); + Declaration* cdec = bdec->mScope->Lookup(bdec->mIdent->PreMangle("+"), SLEVEL_CLASS); if (cdec) { while (cdec && !cdec->mBase->IsSameParams(ctdec)) @@ -4855,7 +4847,11 @@ Expression* Parser::ParsePostfixExpression(bool lhs) for (;;) { - if (ConsumeTokenIf(TK_OPEN_BRACKET)) + if (ConsumeTokenIf(TK_COLCOLON)) + { + + } + else if (ConsumeTokenIf(TK_OPEN_BRACKET)) { Expression* nexp = new Expression(mScanner->mLocation, EX_INDEX); nexp->mLeft = exp; @@ -4899,7 +4895,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) } else { - Declaration* fcons = exp->mDecType->mScope ? exp->mDecType->mScope->Lookup(exp->mDecType->mIdent) : nullptr; + Declaration* fcons = exp->mDecType->mScope ? exp->mDecType->mScope->Lookup(exp->mDecType->mIdent->PreMangle("+")) : nullptr; if (fcons) { Declaration* tdec = new Declaration(mScanner->mLocation, DT_VARIABLE); @@ -5253,7 +5249,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) { pexp = ParseListExpression(false); - mdec = dec->mScope->Lookup(dec->mIdent); + mdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+")); ConsumeToken(TK_CLOSE_PARENTHESIS); From 551316fe59e3c63a0d06f371cd9adbb8d3acedb0 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 26 Jul 2023 18:02:22 +0200 Subject: [PATCH 051/169] Fix autotest assert --- autotest/arrayindexintrangecheck.c | 2 +- autotest/autotest.bat | 3 ++ autotest/floatcmptest.c | 3 +- oscar64/Declaration.cpp | 2 +- oscar64/InterCode.cpp | 80 ++++++++++++++++++++++++++---- oscar64/InterCodeGenerator.cpp | 49 ++++++++++++++++++ oscar64/NativeCodeGenerator.cpp | 5 +- oscar64/Parser.cpp | 10 +++- 8 files changed, 137 insertions(+), 17 deletions(-) diff --git a/autotest/arrayindexintrangecheck.c b/autotest/arrayindexintrangecheck.c index e71ce42..946ceba 100644 --- a/autotest/arrayindexintrangecheck.c +++ b/autotest/arrayindexintrangecheck.c @@ -16,7 +16,7 @@ int main(void) put(j, j); int s = -45; for(int j=0; j<10; j++) - s += get[j]; + s += get(j); return s; } diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 16355f7..38ae467 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -87,6 +87,9 @@ rem @echo off @call :test arrayinittest.c @if %errorlevel% neq 0 goto :error +@call :test arrayindexintrangecheck.c +@if %errorlevel% neq 0 goto :error + @call :test array2stringinittest.c @if %errorlevel% neq 0 goto :error diff --git a/autotest/floatcmptest.c b/autotest/floatcmptest.c index 9afa51f..8e3b202 100644 --- a/autotest/floatcmptest.c +++ b/autotest/floatcmptest.c @@ -65,7 +65,7 @@ int main(void) cmpflt( 1.0, 0.0, false, false, true); cmpflt(-1.0, 0.0, false, true, false); -#if 1 + cmpflt( 1.0, 1.0, true, false, false); cmpflt( 1.0, 2.0, false, true, false); cmpflt( 2.0, 1.0, false, false, true); @@ -94,7 +94,6 @@ int main(void) cmpflt( -1.0, -1.000001, false, false, true); cmpflt( -1.000001, -1.0, false, true, false); cmpflt( -1.000001, -1.000001, true, false, false); -#endif return 0; } diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 240ffb2..f271383 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -126,7 +126,7 @@ void DeclarationScope::End(const Location& loc) } Expression::Expression(const Location& loc, ExpressionType type) - : mLocation(loc), mEndLocation(loc), mType(type), mLeft(nullptr), mRight(nullptr), mConst(false), mDecType(nullptr), mDecValue(nullptr) + : mLocation(loc), mEndLocation(loc), mType(type), mLeft(nullptr), mRight(nullptr), mConst(false), mDecType(nullptr), mDecValue(nullptr), mToken(TK_NONE) { } diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index e525c1c..56d7a41 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -1797,6 +1797,7 @@ InterInstruction* InterInstruction::Clone(void) const { InterInstruction* ins = new InterInstruction(mLocation, mCode); *ins = *this; + ins->mRemove = false; return ins; } @@ -3866,6 +3867,8 @@ void InterInstruction::BuildCollisionTable(NumberSet& liveTemps, NumberSet* coll { if (mDst.mTemp >= 0) { + // Ensure collision with unused destination register + UpdateCollisionSet(liveTemps, collisionSets, mDst.mTemp); // if (!liveTemps[ttemp]) __asm int 3 liveTemps -= mDst.mTemp; } @@ -4500,6 +4503,10 @@ void InterCodeBasicBlock::Append(InterInstruction * code) { assert(code->mSrc[1].mType != IT_POINTER); } + if (code->mCode == IC_CONSTANT) + { + assert(code->mDst.mType == code->mConst.mType); + } for (int i = 0; i < code->mNumOperands; i++) assert(code->mSrc[i].mType != IT_NONE); @@ -7928,7 +7935,9 @@ bool InterCodeBasicBlock::CalculateSingleAssignmentTemps(FastNumberSet& tassigne valid = false; else if (ins->mCode == IC_LOAD) { - if (ins->mSrc[0].mMemory == paramMemory) + if (ins->mVolatile) + valid = false; + else if (ins->mSrc[0].mMemory == paramMemory) { if (modifiedParams[ins->mSrc[0].mVarIndex]) valid = false; @@ -12450,6 +12459,8 @@ bool InterCodeBasicBlock::CheapInlining(int & numTemps) InterInstruction* pins = nins->Clone(); if (pins->mSrc[0].mTemp >= 0) pins->mSrc[0].mTemp = tmap[pins->mSrc[0].mTemp]; + if (pins->mSrc[1].mTemp >= 0) + pins->mSrc[1].mTemp = tmap[pins->mSrc[1].mTemp]; mInstructions.Insert(i, pins); i++; } break; @@ -12462,20 +12473,43 @@ bool InterCodeBasicBlock::CheapInlining(int & numTemps) mInstructions.Insert(i, pins); i++; } break; + case IC_RETURN: + break; case IC_RETURN_VALUE: { if (ins->mDst.mTemp >= 0) { InterInstruction* pins = nins->Clone(); - pins->mCode = IC_LOAD_TEMPORARY; + if (pins->mSrc[0].mTemp < 0) + { + pins->mCode = IC_CONSTANT; + pins->mConst = pins->mSrc[0]; + pins->mNumOperands = 0; + } + else + { + pins->mCode = IC_LOAD_TEMPORARY; + pins->mNumOperands = 1; + } + pins->mDst = ins->mDst; if (pins->mSrc[0].mTemp >= 0) pins->mSrc[0].mTemp = tmap[pins->mSrc[0].mTemp]; - pins->mNumOperands = 1; mInstructions.Insert(i, pins); i++; } } break; + default: + { + InterInstruction* pins = nins->Clone(); + for (int k = 0; k < pins->mNumOperands; k++) + if (pins->mSrc[k].mTemp >= 0) + pins->mSrc[k].mTemp = tmap[pins->mSrc[k].mTemp]; + if (pins->mDst.mTemp >= 0) + pins->mDst.mTemp = ntemps; + mInstructions.Insert(i, pins); + i++; + } break; } if (nins->mDst.mTemp >= 0) @@ -15853,12 +15887,12 @@ void InterCodeProcedure::SingleAssignmentForwarding(void) ResetVisited(); mEntryBlock->SingleAssignmentTempForwarding(tunified, tvalues); + DisassembleDebug("single assignment forwarding"); + BuildDataFlowSets(); TempForwarding(); RemoveUnusedInstructions(); - DisassembleDebug("single assignment forwarding"); - } void InterCodeProcedure::PeepholeOptimization(void) @@ -16435,7 +16469,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "tile_draw_g"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; @@ -16542,7 +16576,7 @@ void InterCodeProcedure::Close(void) // Check for cheap inlining // - if (mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE) + if (mCompilerOptions & COPT_OPTIMIZE_INLINE) { ResetVisited(); if (mEntryBlock->CheapInlining(numTemps)) @@ -16551,6 +16585,8 @@ void InterCodeProcedure::Close(void) mTemporaries.SetSize(numTemps, true); DisassembleDebug("Cheap Inlining"); + + BuildDataFlowSets(); } } @@ -17263,7 +17299,7 @@ void InterCodeProcedure::Close(void) if (!mEntryBlock->mTrueJump) { - int nconst = 0, nvariables = 0, nparams = 0, ncalls = 0, nret = 0, nother = 0; + int nconst = 0, nvariables = 0, nparams = 0, ncalls = 0, nret = 0, nother = 0, nops = 0; for (int i = 0; i < mEntryBlock->mInstructions.Size(); i++) { InterInstruction* ins = mEntryBlock->mInstructions[i]; @@ -17284,10 +17320,34 @@ void InterCodeProcedure::Close(void) break; case IC_STORE: if (ins->mSrc[1].mTemp >= 0 || (ins->mSrc[1].mMemory != IM_FFRAME && ins->mSrc[1].mMemory != IM_FRAME)) - nother++; + nops++; if (ins->mSrc[0].mTemp < 0) nconst++; break; + +#if 1 + case IC_CONSTANT: + if (ins->mConst.mType == IT_POINTER && (ins->mConst.mMemory == IM_FPARAM || ins->mConst.mMemory == IM_PARAM || ins->mConst.mMemory == IM_LOCAL)) + nother++; + else + nconst++; + break; +#endif +#if 1 + case IC_LEA: + if (ins->mSrc[1].mTemp >= 0 || (ins->mSrc[1].mMemory != IM_FPARAM && ins->mSrc[1].mMemory != IM_PARAM && ins->mSrc[1].mMemory != IM_LOCAL)) + nops++; + else + nother++; + break; +#endif +#if 1 + case IC_BINARY_OPERATOR: + case IC_UNARY_OPERATOR: + case IC_RELATIONAL_OPERATOR: + nops++; + break; +#endif case IC_CALL: case IC_CALL_NATIVE: if (ins->mSrc[0].mTemp < 0) @@ -17304,7 +17364,7 @@ void InterCodeProcedure::Close(void) } } - if (nother == 0 && ncalls == 1 && nret == 1 && nconst < 2) + if (nother == 0 && ncalls <= 1 && nret == 1 && nconst <= 1 + nparams && nops <= 1 + nparams) mCheapInline = true; } } diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index b5df555..7414ced 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -925,6 +925,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro InterInstruction* ains = new InterInstruction(pex->mLocation, IC_CONSTANT); ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); + ains->mConst.mType = IT_POINTER; ains->mConst.mMemory = IM_LOCAL; ains->mConst.mVarIndex = nindex; @@ -1090,6 +1091,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ins->mConst.mType = IT_POINTER; ins->mConst.mOperandSize = rdec->mSize; ins->mConst.mIntConst = rdec->mOffset; ins->mConst.mVarIndex = rdec->mVarIndex; @@ -1158,6 +1160,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); + ains->mConst.mType = IT_POINTER; ains->mConst.mMemory = IM_LOCAL; ains->mConst.mVarIndex = nindex; @@ -1192,6 +1195,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I ains->mNumOperands = 0; ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); + ains->mConst.mType = IT_POINTER; ains->mConst.mMemory = IM_LOCAL; ains->mConst.mVarIndex = nindex; @@ -1230,6 +1234,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I InterInstruction* psins = new InterInstruction(exp->mLocation, IC_CONSTANT); psins->mDst.mType = IT_POINTER; psins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + psins->mConst.mType = IT_POINTER; psins->mConst.mVarIndex = 0; psins->mConst.mIntConst = 0; psins->mConst.mOperandSize = 2; @@ -1253,6 +1258,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I InterInstruction* plins = new InterInstruction(exp->mLocation, IC_CONSTANT); plins->mDst.mType = IT_POINTER; plins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + plins->mConst.mType = IT_POINTER; plins->mConst.mVarIndex = 2; plins->mConst.mIntConst = 0; plins->mConst.mOperandSize = 2; @@ -1374,6 +1380,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ains->mCode = IC_CONSTANT; ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(IT_POINTER); + ains->mConst.mType = IT_POINTER; ains->mConst.mOperandSize = procType->mBase->mSize; ains->mConst.mIntConst = 0; ains->mConst.mVarIndex = inlineMapper->mResult; @@ -1386,6 +1393,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction* pins = new InterInstruction(exp->mLocation, IC_CONSTANT); pins->mDst.mType = IT_POINTER; pins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + pins->mConst.mType = IT_POINTER; pins->mConst.mVarIndex = 0; pins->mConst.mIntConst = 0; pins->mConst.mOperandSize = 2; @@ -1426,6 +1434,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); ins->mDst.mType = InterTypeOf(dec->mBase); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ins->mConst.mType = ins->mDst.mType; + if (ins->mDst.mType == IT_INT8) { if (dec->mBase->mFlags & DTF_SIGNED) @@ -1485,6 +1495,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); ins->mDst.mType = InterTypeOf(dec->mBase); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ins->mConst.mType = ins->mDst.mType; ins->mConst.mFloatConst = dec->mNumber; block->Append(ins); return ExValue(dec->mBase, ins->mDst.mTemp); @@ -1496,6 +1507,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + ins->mConst.mType = IT_POINTER; ins->mConst.mIntConst = dec->mInteger; ins->mConst.mMemory = IM_ABSOLUTE; block->Append(ins); @@ -1513,6 +1525,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); ins->mDst.mType = InterTypeOf(dec->mBase); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ins->mConst.mType = ins->mDst.mType; ins->mConst.mVarIndex = dec->mVarIndex; ins->mConst.mLinkerObject = dec->mLinkerObject; ins->mConst.mMemory = IM_PROCEDURE; @@ -1530,6 +1543,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ins->mConst.mType = IT_POINTER; ins->mConst.mVarIndex = dec->mVarIndex; ins->mConst.mLinkerObject = dec->mLinkerObject; ins->mConst.mMemory = IM_PROCEDURE; @@ -1566,6 +1580,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + ins->mConst.mType = IT_POINTER; ins->mConst.mIntConst = 0; ins->mConst.mVarIndex = dec->mVarIndex; assert(dec->mVarIndex >= 0); @@ -1599,6 +1614,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + ins->mConst.mType = IT_POINTER; ins->mConst.mIntConst = 0; ins->mConst.mVarIndex = dec->mVarIndex; assert(dec->mVarIndex >= 0); @@ -1823,6 +1839,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mType->mType == DT_TYPE_POINTER) { InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + cins->mConst.mType = IT_INT16; if (exp->mToken == TK_ASSIGN_ADD) { @@ -2002,6 +2019,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = CoerceType(proc, exp, block, vr, TheSignedIntTypeDeclaration); InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + cins->mConst.mType = IT_INT16; cins->mConst.mIntConst = stride; cins->mDst.mType = IT_INT16; cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); @@ -2042,6 +2060,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(exp->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + cins->mConst.mType = IT_INT16; cins->mConst.mIntConst = exp->mDecValue->mOffset; cins->mDst.mType = IT_INT16; cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); @@ -2090,6 +2109,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vr.mType->IsIntegerType()) { InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + cins->mConst.mType = IT_INT16; if (exp->mToken == TK_ADD) { @@ -2160,6 +2180,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + cins->mConst.mType = IT_INT16; cins->mConst.mIntConst = s; cins->mDst.mType = IT_INT16; cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); @@ -2209,6 +2230,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mType->IsIntegerType()) { InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + cins->mConst.mType = IT_INT16; if (exp->mToken == TK_ADD) { @@ -2394,10 +2416,15 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* cins->mDst.mType = ftype ? IT_FLOAT : IT_INT16; cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); + cins->mConst.mType = cins->mDst.mType; + if (vdl.mType->mType == DT_TYPE_POINTER) cins->mConst.mIntConst = exp->mToken == TK_INC ? vdl.mType->Stride() : -(vdl.mType->Stride()); else if (vdl.mType->IsNumericType()) + { cins->mConst.mIntConst = exp->mToken == TK_INC ? 1 : -1; + cins->mConst.mFloatConst = double(cins->mConst.mIntConst); + } else mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a numeric value or pointer"); @@ -2456,10 +2483,15 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* cins->mDst.mType = ftype ? IT_FLOAT : IT_INT16; cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); + cins->mConst.mType = cins->mDst.mType; + if (vdl.mType->mType == DT_TYPE_POINTER) cins->mConst.mIntConst = exp->mToken == TK_INC ? vdl.mType->Stride() : -(vdl.mType->Stride()); else if (vdl.mType->IsNumericType()) + { cins->mConst.mIntConst = exp->mToken == TK_INC ? 1 : -1; + cins->mConst.mFloatConst = double(cins->mConst.mIntConst); + } else mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a numeric value or pointer"); block->Append(cins); @@ -2838,6 +2870,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(sex->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); InterInstruction* ins = new InterInstruction(exp->mLocation, IC_STRCPY); + ins->mNumOperands = 2; + ins->mSrc[0].mType = IT_POINTER; ins->mSrc[0].mMemory = IM_INDIRECT; ins->mSrc[0].mTemp = vr.mTemp; @@ -3006,6 +3040,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); vins->mDst.mType = IT_POINTER; vins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + vins->mConst.mType = IT_POINTER; vins->mConst.mMemory = IM_LOCAL; vins->mConst.mVarIndex = nindex; vins->mConst.mOperandSize = ftype->mBase->mSize; @@ -3017,6 +3052,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(IT_POINTER); + ains->mConst.mType = IT_POINTER; ains->mConst.mVarIndex = 0; ains->mConst.mIntConst = 0; ains->mConst.mOperandSize = 2; @@ -3055,6 +3091,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* while (pex) { InterInstruction * ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains->mConst.mType = IT_POINTER; + ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); if (pdec) @@ -3285,6 +3323,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); vins->mDst.mType = IT_POINTER; vins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + vins->mConst.mType = IT_POINTER; vins->mConst.mMemory = IM_LOCAL; vins->mConst.mVarIndex = decResult->mVarIndex; block->Append(vins); @@ -3314,6 +3353,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ins->mConst.mType = IT_POINTER; ins->mConst.mOperandSize = dec->mSize; ins->mConst.mIntConst = 0; ins->mConst.mMemory = IM_GLOBAL; @@ -3332,6 +3372,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* for (int i = 0; i < refvars.Size(); i++) { InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); + vins->mConst.mType = IT_POINTER; + vins->mDst.mType = IT_POINTER; vins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); @@ -3425,6 +3467,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ains->mConst.mType = IT_POINTER; ains->mConst.mOperandSize = procType->mBase->mSize; ains->mConst.mIntConst = 0; ains->mConst.mVarIndex = inlineMapper->mResult;; @@ -3461,6 +3504,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ains->mCode = IC_CONSTANT; ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(IT_POINTER); + ains->mConst.mType = IT_POINTER; ains->mConst.mOperandSize = procType->mBase->mSize; ains->mConst.mIntConst = 0; ains->mConst.mVarIndex = inlineMapper->mResult; @@ -3475,6 +3519,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction* pins = new InterInstruction(exp->mLocation, IC_CONSTANT); pins->mDst.mType = IT_POINTER; pins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + pins->mConst.mType = IT_POINTER; pins->mConst.mVarIndex = 0; pins->mConst.mIntConst = 0; pins->mConst.mOperandSize = 2; @@ -3641,6 +3686,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ains->mConst.mType = IT_POINTER; ains->mConst.mOperandSize = procType->mBase->mSize; ains->mConst.mIntConst = 0; ains->mConst.mVarIndex = inlineMapper->mResult;; @@ -3751,6 +3797,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * zins = new InterInstruction(exp->mLocation, IC_CONSTANT); zins->mDst.mType = InterTypeOf(vl.mType); zins->mDst.mTemp = proc->AddTemporary(zins->mDst.mType); + zins->mConst.mType = zins->mDst.mType; zins->mConst.mIntConst = 0; block->Append(zins); @@ -4079,12 +4126,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* int ttemp = proc->AddTemporary(IT_BOOL); InterInstruction* tins = new InterInstruction(exp->mLocation, IC_CONSTANT); + tins->mConst.mType = IT_BOOL; tins->mConst.mIntConst = 1; tins->mDst.mType = IT_BOOL; tins->mDst.mTemp = ttemp; tblock->Append(tins); InterInstruction* fins = new InterInstruction(exp->mLocation, IC_CONSTANT); + fins->mConst.mType = IT_BOOL; fins->mConst.mIntConst = 0; fins->mDst.mType = IT_BOOL; fins->mDst.mTemp = ttemp; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 8bd9f33..dae74a9 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -25065,6 +25065,8 @@ bool NativeCodeBasicBlock::MoveZeroPageCrossBlockUp(int at, const NativeCodeInst return false; else if (mIns[i].ReferencesZeroPage(sins.mAddress)) return false; + else if (mIns[i].mType == ASMIT_JSR && mIns[i].ReferencesZeroPage(lins.mAddress)) + return false; } } @@ -40393,7 +40395,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "getchar"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41688,7 +41690,6 @@ void NativeCodeProcedure::Optimize(void) else cnt++; - } while (changed); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index a2a5f9d..92cdf6c 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -5002,6 +5002,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) mScanner->NextToken(); } + bool parentCall = false; if ((exp->mDecType->mFlags & DTF_FUNC_THIS) && mThisPointer && mThisPointer->mType == DT_ARGUMENT) { Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE); @@ -5017,13 +5018,20 @@ Expression* Parser::ParsePostfixExpression(bool lhs) } else nexp->mRight = texp; + + parentCall = true; } nexp = ResolveOverloadCall(nexp); nexp->mDecType = exp->mDecType->mBase; if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL) - nexp->mType = EX_VCALL; + { + if (parentCall) + exp->mDecType->mFlags |= DTF_STACKCALL; + else + nexp->mType = EX_VCALL; + } exp = nexp; } From 2b9ae73795d0d4e50b28ef874a27865ebab716b2 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 26 Jul 2023 19:46:07 +0200 Subject: [PATCH 052/169] Bump version number --- oscar64/InterCode.cpp | 2 ++ oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 56d7a41..d2a169b 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -7806,6 +7806,8 @@ static bool SameSingleAssignment(const GrowingInstructionPtrArray& tunified, con { return false; } + else if (!tunified[ins->mSrc[i].mTemp]) + return false; else if (tunified[ins->mSrc[i].mTemp] != tunified[cins->mSrc[i].mTemp]) return false; } diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 825eb2b..ac960d9 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.23.211"); + strcpy(strProductVersion, "1.23.212"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 65dc55b..12d7cd4 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,23,211,0 - PRODUCTVERSION 1,23,211,0 + FILEVERSION 1,23,212,0 + PRODUCTVERSION 1,23,212,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.23.211.0" + VALUE "FileVersion", "1.23.212.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.23.211.0" + VALUE "ProductVersion", "1.23.212.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index df337d0..7f9ef82 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5504,15 +5504,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{E5A90B4B-CA2A-43EC-9597-90010989AF33}" - "PackageCode" = "8:{C6265FB3-0498-45EF-827C-27788C57AFAF}" + "ProductCode" = "8:{56AFEF31-4A48-403F-A6CA-601769444F71}" + "PackageCode" = "8:{3797CD46-BC0B-40C2-93E5-B8226ACD9F91}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.23.211" + "ProductVersion" = "8:1.23.212" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 4c5a9c3b70267fa1895ec32caeadc47e31540557 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 26 Jul 2023 22:48:15 +0200 Subject: [PATCH 053/169] Fix over eager register promotion --- oscar64/NativeCodeGenerator.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index dae74a9..3d38038 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -29509,6 +29509,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc mIns.Remove(ai); mEntryRequiredRegs += CPU_REG_A; + for (int i = 0; i < mIns.Size(); i++) + mIns[i].mLive |= LIVE_CPU_REG_A; mExitRequiredRegs += CPU_REG_A; prevBlock->mExitRequiredRegs += CPU_REG_A; @@ -30370,6 +30372,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc, bool f mBranch = ASMIT_BCC; mIns[sz - 2].mMode = ASMIM_ZERO_PAGE; mIns[sz - 2].mAddress = mIns[sz - 1].mAddress; mIns[sz - 1].mMode = ASMIM_IMMEDIATE; mIns[sz - 1].mAddress = val; + mIns[sz - 2].mLive |= mIns[sz - 1].mLive & LIVE_MEM; } else if (mBranch == ASMIT_BCC && mIns[sz - 2].mAddress < 0xff) { @@ -30377,12 +30380,14 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc, bool f mBranch = ASMIT_BCS; mIns[sz - 2].mMode = ASMIM_ZERO_PAGE; mIns[sz - 2].mAddress = mIns[sz - 1].mAddress; mIns[sz - 1].mMode = ASMIM_IMMEDIATE; mIns[sz - 1].mAddress = val; + mIns[sz - 2].mLive |= mIns[sz - 1].mLive & LIVE_MEM; } else if ((mBranch == ASMIT_BEQ || mBranch == ASMIT_BNE) && !(mIns[sz - 1].mLive & LIVE_CPU_REG_C)) { int val = mIns[sz - 2].mAddress; mIns[sz - 2].mMode = ASMIM_ZERO_PAGE; mIns[sz - 2].mAddress = mIns[sz - 1].mAddress; mIns[sz - 1].mMode = ASMIM_IMMEDIATE; mIns[sz - 1].mAddress = val; + mIns[sz - 2].mLive |= mIns[sz - 1].mLive & LIVE_MEM; } } #endif @@ -31952,6 +31957,11 @@ bool NativeCodeBasicBlock::OptimizeFindLoop(NativeCodeProcedure* proc) body->mIns[fsz - 1].mMode = ASMIM_IMPLIED; mIns.Remove(0); + body->mEntryRequiredRegs += CPU_REG_Y; + body->mExitRequiredRegs += CPU_REG_Y; + mEntryRequiredRegs += CPU_REG_Y; + mExitRequiredRegs += CPU_REG_Y; + for (int i = 0; i < mIns.Size(); i++) mIns[i].mLive |= LIVE_CPU_REG_Y; for (int i = 0; i < fsz; i++) @@ -34510,7 +34520,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass if (FindImmediateStore(i, mIns[i].mAddress + 1, ains)) { mIns.Insert(i, NativeCodeInstruction(mIns[i + 0].mIns, ASMIT_LDX, ASMIM_ZERO_PAGE, mIns[i].mAddress)); - mIns[i + 0].mLive = mIns[i + 1].mLive | LIVE_CPU_REG_X; mIns[i + 1].mMode = ASMIM_ABSOLUTE_X; if (ains->mMode == ASMIM_IMMEDIATE) @@ -34548,13 +34557,13 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass } else if (mIns[i].mType == ASMIT_STA && mIns[i + 1].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[i + 1].mAddress && (mIns[i + 1].mLive & LIVE_CPU_REG_Z) == 0) { - mIns[i + 1].mLive |= LIVE_CPU_REG_A; + mIns[i + 0].mLive |= LIVE_CPU_REG_A; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; progress = true; } else if (mIns[i].mType == ASMIT_STA && mIns[i + 1].mType == ASMIT_LDA && mIns[i].SameEffectiveAddress(mIns[i + 1]) && !(mIns[i + 1].mFlags & NCIF_VOLATILE) && (mIns[i + 1].mLive & LIVE_CPU_REG_Z) == 0) { - mIns[i + 1].mLive |= LIVE_CPU_REG_A; + mIns[i + 0].mLive |= LIVE_CPU_REG_A; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; progress = true; } @@ -40395,7 +40404,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "gauge_show"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41419,6 +41428,7 @@ void NativeCodeProcedure::Optimize(void) } } #endif + if (!changed) { if (step == 5) From 312265c395ff6602f6ef73c883f0216c73344e90 Mon Sep 17 00:00:00 2001 From: Stefan Date: Thu, 27 Jul 2023 13:00:07 +0200 Subject: [PATCH 054/169] Support of more platforms See http://aminet.net/package/dev/cross/oscar64 --- oscar64/MachineTypes.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/oscar64/MachineTypes.h b/oscar64/MachineTypes.h index 7badfad..77ea5d0 100644 --- a/oscar64/MachineTypes.h +++ b/oscar64/MachineTypes.h @@ -16,10 +16,10 @@ typedef __int64 int64; typedef unsigned __int64 uint64; #define MAXPATHLEN _MAX_PATH #else -#if __APPLE__ -#include "limits.h" -#else /* __linux__ */ +#if __linux__ #include "linux/limits.h" +#else /* __APPLE__ */ +#include "limits.h" #endif typedef long long int64; @@ -105,4 +105,4 @@ inline int64 int64max(int64 a, int64 b) inline int64 int64min(int64 a, int64 b) { return a < b ? a : b; -} \ No newline at end of file +} From 02e7f15810a1f2cbf6a0d18347f517284b74c0fa Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 28 Jul 2023 18:51:29 +0200 Subject: [PATCH 055/169] Improve outer loop optimizations --- include/c64/memmap.c | 20 +++---- include/c64/memmap.h | 4 +- include/crt.c | 2 +- oscar64/Declaration.cpp | 4 +- oscar64/InterCode.cpp | 86 ++++++++++++++++++++++++++++- oscar64/InterCode.h | 2 + oscar64/NativeCodeGenerator.cpp | 97 ++++++++++++++++++++++++++++++++- oscar64/NativeCodeGenerator.h | 6 ++ 8 files changed, 201 insertions(+), 20 deletions(-) diff --git a/include/c64/memmap.c b/include/c64/memmap.c index c2c061f..fb101fc 100644 --- a/include/c64/memmap.c +++ b/include/c64/memmap.c @@ -1,11 +1,8 @@ #include "memmap.h" -volatile char PLAShadow; - __asm DoneTrampoline { - lda PLAShadow - sta $01 + stx $01 pla tax pla @@ -17,8 +14,6 @@ __asm IRQTrampoline pha txa pha - lda #$36 - sta $01 lda #>DoneTrampoline pha @@ -27,6 +22,9 @@ __asm IRQTrampoline tsx lda $0105, x pha + ldx $01 + lda #$36 + sta $01 jmp ($fffe) } @@ -35,8 +33,6 @@ __asm NMITrampoline pha txa pha - lda #$36 - sta $01 lda #>DoneTrampoline pha @@ -45,6 +41,9 @@ __asm NMITrampoline tsx lda $0105, x pha + ldx $01 + lda #$36 + sta $01 jmp ($fffa) } @@ -56,8 +55,9 @@ void mmap_trampoline(void) #pragma native(mmap_trampoline) -void mmap_set(char pla) +char mmap_set(char pla) { - PLAShadow = pla; + char ppla = *((char *)0x01); *((volatile char *)0x01) = pla; + return ppla; } diff --git a/include/c64/memmap.h b/include/c64/memmap.h index aebb768..947ffec 100644 --- a/include/c64/memmap.h +++ b/include/c64/memmap.h @@ -18,9 +18,9 @@ void mmap_trampoline(void); // Set the memory map in a way that is compatible with the IRQ -// trampoline +// trampoline, returns the previous state -inline void mmap_set(char pla); +inline char mmap_set(char pla); #pragma compile("memmap.c") diff --git a/include/crt.c b/include/crt.c index 2f30649..6f85487 100644 --- a/include/crt.c +++ b/include/crt.c @@ -160,7 +160,7 @@ wx1: jmp lx2 w0: - lda #$3f + lda #$2f sta $00 lda #$36 sta $01 diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index f271383..5617724 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1285,7 +1285,7 @@ bool Declaration::IsSame(const Declaration* dec) const return mIdent == dec->mIdent; else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) { - if (mBase->mType == DT_TYPE_STRUCT && dec->mBase->mType == DT_TYPE_STRUCT) + if (mBase->mType == DT_TYPE_STRUCT && dec->mBase->mType == DT_TYPE_STRUCT && mBase->mStripe == dec->mBase->mStripe) { if (mBase->mQualIdent == dec->mBase->mQualIdent && (mBase->mFlags & (DTF_CONST | DTF_VOLATILE)) == (dec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE))) @@ -1373,7 +1373,7 @@ bool Declaration::CanAssign(const Declaration* fromType) const { if (mBase->mType == DT_TYPE_VOID || fromType->mBase->mType == DT_TYPE_VOID) return (mBase->mFlags & DTF_CONST) || !(fromType->mBase->mFlags & DTF_CONST); - else if (mBase->IsSubType(fromType->mBase)) + else if (mBase->mStripe == fromType->mBase->mStripe && mBase->IsSubType(fromType->mBase)) return true; } else if (mBase->mType == DT_TYPE_FUNCTION && fromType->mType == DT_TYPE_FUNCTION) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index d2a169b..1a1b6cd 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -530,6 +530,18 @@ bool InterCodeBasicBlock::DestroyingMem(const InterInstruction* lins, const Inte return false; } +bool InterCodeBasicBlock::DestroyingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const +{ + for (int i = from; i < to; i++) + { + InterInstruction* ins = block->mInstructions[i]; + if (DestroyingMem(lins, ins)) + return true; + } + + return false; +} + static bool SameMem(const InterOperand& op1, const InterOperand& op2) { if (op1.mMemory != op2.mMemory || op1.mType != op2.mType || op1.mIntConst != op2.mIntConst) @@ -8036,7 +8048,7 @@ void InterCodeBasicBlock::PerformTempForwarding(const TempForwardingTable& forwa { if (mEntryBlocks[i] != mLoopPrefix) { - if (!mEntryBlocks[i]->CollectLoopBody(this, body)) + if (!mEntryBlocks[i]->CollectLoopBodyRecursive(this, body)) innerLoop = false; } } @@ -11578,6 +11590,10 @@ void InterCodeBasicBlock::BuildLoopSuffix(void) if (mFalseJump->mNumEntries > 1) { InterCodeBasicBlock* suffix = new InterCodeBasicBlock(mProc); + suffix->mEntryRequiredTemps = mFalseJump->mEntryRequiredTemps; + suffix->mExitRequiredTemps = mFalseJump->mEntryRequiredTemps; + suffix->mLocalModifiedTemps.Reset(mExitRequiredTemps.Size()); + InterInstruction* jins = new InterInstruction(mInstructions[0]->mLocation, IC_JUMP); suffix->Append(jins); suffix->Close(mFalseJump, nullptr); @@ -11590,6 +11606,10 @@ void InterCodeBasicBlock::BuildLoopSuffix(void) if (mTrueJump->mNumEntries > 1) { InterCodeBasicBlock* suffix = new InterCodeBasicBlock(mProc); + suffix->mEntryRequiredTemps = mTrueJump->mEntryRequiredTemps; + suffix->mExitRequiredTemps = mTrueJump->mEntryRequiredTemps; + suffix->mLocalModifiedTemps.Reset(mExitRequiredTemps.Size()); + InterInstruction* jins = new InterInstruction(mInstructions[0]->mLocation, IC_JUMP); suffix->Append(jins); suffix->Close(mTrueJump, nullptr); @@ -11620,6 +11640,10 @@ InterCodeBasicBlock* InterCodeBasicBlock::BuildLoopPrefix(void) if (mLoopHead) { mLoopPrefix = new InterCodeBasicBlock(mProc); + mLoopPrefix->mEntryRequiredTemps = mEntryRequiredTemps; + mLoopPrefix->mExitRequiredTemps = mEntryRequiredTemps; + mLoopPrefix->mLocalModifiedTemps.Reset(mEntryRequiredTemps.Size()); + InterInstruction* jins = new InterInstruction(mInstructions[0]->mLocation, IC_JUMP); mLoopPrefix->Append(jins); mLoopPrefix->Close(this, nullptr); @@ -11645,6 +11669,22 @@ bool InterCodeBasicBlock::CollectLoopBody(InterCodeBasicBlock* head, GrowingArra return true; } +bool InterCodeBasicBlock::CollectLoopBodyRecursive(InterCodeBasicBlock* head, GrowingArray& body) +{ + if (this == head) + return true; + + if (body.IndexOf(this) != -1) + return true; + body.Push(this); + + for (int i = 0; i < mEntryBlocks.Size(); i++) + if (!mEntryBlocks[i]->CollectLoopBodyRecursive(head, body)) + return false; + + return true; +} + void InterCodeBasicBlock::CollectLoopPath(const GrowingArray& body, GrowingArray& path) { if (body.IndexOf(this) >= 0) @@ -11872,6 +11912,17 @@ bool InterCodeBasicBlock::SingleTailLoopOptimization(const NumberSet& aliasedPar } } #endif + bool hasStore = false; + for (int j = 0; j < body.Size(); j++) + { + int sz = body[j]->mInstructions.Size(); + for (int i = 0; i < sz; i++) + { + InterInstruction* ins = body[j]->mInstructions[i]; + if (IsObservable(ins->mCode)) + hasStore = true; + } + } int i = 0; while (i < mInstructions.Size()) @@ -11880,7 +11931,8 @@ bool InterCodeBasicBlock::SingleTailLoopOptimization(const NumberSet& aliasedPar if (lins->mCode == IC_BINARY_OPERATOR || lins->mCode == IC_CONSTANT || lins->mCode == IC_UNARY_OPERATOR || lins->mCode == IC_CONVERSION_OPERATOR || lins->mCode == IC_SELECT || - lins->mCode == IC_RELATIONAL_OPERATOR) + lins->mCode == IC_LEA || + lins->mCode == IC_RELATIONAL_OPERATOR || (lins->mCode == IC_LOAD && !hasStore && !lins->mVolatile)) { #if 1 if (CanMoveInstructionBeforeBlock(i) && !IsInsModifiedInRange(i + 1, mInstructions.Size(), lins) && !tail->IsInsModified(lins) && !lins->UsesTemp(lins->mDst.mTemp)) @@ -11901,7 +11953,7 @@ bool InterCodeBasicBlock::SingleTailLoopOptimization(const NumberSet& aliasedPar } #endif } - else if (lins->mCode == IC_LOAD && lins->mSrc[0].mTemp < 0 && !tail->mExitRequiredTemps[lins->mDst.mTemp]) + else if (lins->mCode == IC_LOAD && !lins->mVolatile && lins->mSrc[0].mTemp < 0 && !tail->mExitRequiredTemps[lins->mDst.mTemp]) { if (CanMoveInstructionBeforeBlock(i)) { @@ -11963,8 +12015,36 @@ bool InterCodeBasicBlock::SingleTailLoopOptimization(const NumberSet& aliasedPar } } } + else + { + int k = 0; + while (k < body.Size() && !DestroyingMem(body[k], lins, 0, body[k]->mInstructions.Size())) + k++; + if (k == body.Size()) + { +#if 1 + if (!IsInsModifiedInRange(i + 1, mInstructions.Size(), lins) && !tail->IsInsModified(lins)) + { + int j = 1; + while (j < body.Size() && !body[j]->IsInsModified(lins)) + j++; + if (j == body.Size()) + { + mLoopPrefix->mInstructions.Insert(mLoopPrefix->mInstructions.Size() - 1, lins); + mLoopPrefix->mExitRequiredTemps += lins->mDst.mTemp; + mEntryRequiredTemps += lins->mDst.mTemp; + mInstructions.Remove(i); + i--; + + modified = true; + } + } +#endif + } + } } } + i++; } } diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index b39c3f5..e15a0f9 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -502,6 +502,7 @@ public: bool IsTempReferencedOnPath(int temp, int at) const; bool DestroyingMem(const InterInstruction* lins, const InterInstruction* sins) const; + bool DestroyingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const; bool CollidingMem(const InterInstruction* ins1, const InterInstruction* ins2) const; bool CollidingMem(const InterOperand& op, InterType type, const InterInstruction* ins) const; bool CollidingMem(const InterOperand& op1, InterType type1, const InterOperand& op2, InterType type2) const; @@ -542,6 +543,7 @@ public: bool SingleBlockLoopPointerSplit(int& spareTemps); bool SingleBlockLoopPointerToByte(int& spareTemps); bool CollectLoopBody(InterCodeBasicBlock* head, GrowingArray & body); + bool CollectLoopBodyRecursive(InterCodeBasicBlock* head, GrowingArray& body); void CollectLoopPath(const GrowingArray& body, GrowingArray& path); void InnerLoopOptimization(const NumberSet& aliasedParams); void PushMoveOutOfLoop(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 3d38038..ffb3809 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -2403,6 +2403,16 @@ void NativeCodeInstruction::Simulate(NativeRegisterDataSet& data) } } break; + + case ASMIT_CLC: + data.mRegs[CPU_REG_C].mValue = 0; + data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE; + break; + + case ASMIT_SEC: + data.mRegs[CPU_REG_C].mValue = 1; + data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE; + break; } } @@ -12978,10 +12988,26 @@ void NativeCodeBasicBlock::BuildEntryDataSet(const NativeRegisterDataSet& set) for (int i = 0; i < mIns.Size(); i++) mIns[i].Simulate(mNDataSet); + mFDataSet = mNDataSet; + if (mBranch == ASMIT_BCC) + { + mNDataSet.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE; + mNDataSet.mRegs[CPU_REG_C].mValue = 0; + mFDataSet.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE; + mFDataSet.mRegs[CPU_REG_C].mValue = 1; + } + else if (mBranch == ASMIT_BCS) + { + mNDataSet.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE; + mNDataSet.mRegs[CPU_REG_C].mValue = 1; + mFDataSet.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE; + mFDataSet.mRegs[CPU_REG_C].mValue = 0; + } + if (mTrueJump) mTrueJump->BuildEntryDataSet(mNDataSet); if (mFalseJump) - mFalseJump->BuildEntryDataSet(mNDataSet); + mFalseJump->BuildEntryDataSet(mFDataSet); } } @@ -15889,6 +15915,10 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) { mVisited = true; + int carry = -1; + if (mEntryRegisterDataSet.mRegs[CPU_REG_C].mMode == NRDM_IMMEDIATE) + carry = mEntryRegisterDataSet.mRegs[CPU_REG_C].mValue; + for (int i = 0; i < mIns.Size(); i++) { if (i + 2 < mIns.Size() && @@ -16229,6 +16259,45 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) break; } + if (carry == 0 && + mIns[i + 0].mType == ASMIT_LDA && + mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 1 && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 2]) && + mIns[i + 3].mType == ASMIT_LDA && + mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 && + mIns[i + 5].mType == ASMIT_STA && mIns[i + 3].SameEffectiveAddress(mIns[i + 5]) && + HasAsmInstructionMode(ASMIT_INC, mIns[i + 2].mMode) && + HasAsmInstructionMode(ASMIT_INC, mIns[i + 5].mMode) && + !(mIns[i + 5].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) + { + changed = true; + + NativeCodeBasicBlock* iblock = proc->AllocateBlock(); + NativeCodeBasicBlock* fblock = proc->AllocateBlock(); + + fblock->mTrueJump = mTrueJump; + fblock->mFalseJump = mFalseJump; + fblock->mBranch = mBranch; + + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 2].mType = ASMIT_INC; mIns[i + 2].mLive |= LIVE_CPU_REG_Z; + + for (int j = i + 6; j < mIns.Size(); j++) + fblock->mIns.Push(mIns[j]); + iblock->mIns.Push(mIns[i + 5]); + mIns.SetSize(i + 3); + iblock->mIns[0].mType = ASMIT_INC; + iblock->mTrueJump = fblock; + iblock->mBranch = ASMIT_JMP; + + mTrueJump = fblock; + mFalseJump = iblock; + mBranch = ASMIT_BNE; + break; + } + + if (mIns[i + 0].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_LDA && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0xff && @@ -17027,6 +17096,13 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) } } + + if (mIns[i].mType == ASMIT_CLC) + carry = 0; + else if (mIns[i].mType == ASMIT_SEC) + carry = 0; + else if (mIns[i].ChangesCarry()) + carry = -1; } #if 1 @@ -18369,6 +18445,19 @@ bool NativeCodeBasicBlock::PropagateSinglePath(void) changed = true; } } + if (mTrueJump->mNumEntries == 1 && mTrueJump->mIns.Size() > 0 && mTrueJump->mIns[0].mType == ASMIT_TAX && !mFalseJump->mEntryRequiredRegs[CPU_REG_A] && !mFalseJump->mEntryRequiredRegs[CPU_REG_X] && !(mTrueJump->mIns[0].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))) + { + int sz = mIns.Size(); + if (sz >= 2 && mIns[sz - 2].mType == ASMIT_LDA && mIns[sz - 1].mType == ASMIT_CMP && HasAsmInstructionMode(ASMIT_LDX, mIns[sz - 2].mMode) && HasAsmInstructionMode(ASMIT_CPX, mIns[sz - 1].mMode)) + { + mIns[sz - 2].mType = ASMIT_LDX; mIns[sz - 2].mLive |= LIVE_CPU_REG_X; + mIns[sz - 1].mType = ASMIT_CPX; mIns[sz - 1].mLive |= LIVE_CPU_REG_X; + mExitRequiredRegs += CPU_REG_X; + mTrueJump->mEntryRequiredRegs += CPU_REG_X; + mTrueJump->mIns[0].mType = ASMIT_NOP; + changed = true; + } + } } #endif @@ -40404,7 +40493,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "gauge_show"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "test"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41612,6 +41701,10 @@ void NativeCodeProcedure::Optimize(void) #if 1 if (step >= 7) { + ResetVisited(); + NativeRegisterDataSet data; + mEntryBlock->BuildEntryDataSet(data); + ResetVisited(); if (mEntryBlock->ExpandADCToBranch(this)) changed = true; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 6a37d13..ff5d34f 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -609,6 +609,12 @@ public: bool CheckPatchFailLoop(const NativeCodeBasicBlock* block, const NativeCodeBasicBlock* head, int reg, bool changed); + // reg : base register pair to replace + // index: index register + // at : start position in block + // yval: known y immediate value of -1 if not known + // lobj: linker object addressed + // address: offset into linker object bool CheckGlobalAddressSumYPointer(const NativeCodeBasicBlock * block, int reg, int index, int at, int yval); bool PatchGlobalAddressSumYPointer(const NativeCodeBasicBlock* block, int reg, int index, int at, int yval, LinkerObject * lobj, int address, uint32 flags = NCIF_LOWER | NCIF_UPPER); From ae21bbac09e3ed22f596de8a5b7fe9d5cdbf5805 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 28 Jul 2023 18:59:12 +0200 Subject: [PATCH 056/169] Bump version number --- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index ac960d9..b02728b 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.23.212"); + strcpy(strProductVersion, "1.23.213"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 12d7cd4..b888c26 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,23,212,0 - PRODUCTVERSION 1,23,212,0 + FILEVERSION 1,23,213,0 + PRODUCTVERSION 1,23,213,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.23.212.0" + VALUE "FileVersion", "1.23.213.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.23.212.0" + VALUE "ProductVersion", "1.23.213.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 7f9ef82..8051e99 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5504,15 +5504,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{56AFEF31-4A48-403F-A6CA-601769444F71}" - "PackageCode" = "8:{3797CD46-BC0B-40C2-93E5-B8226ACD9F91}" + "ProductCode" = "8:{69DF35C1-7D87-4EFB-B4D9-ECA259B2955E}" + "PackageCode" = "8:{B8C99499-4F97-4641-BF54-0202149091C6}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.23.212" + "ProductVersion" = "8:1.23.213" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 0b1d42b7d54a8663c972cf46a5c70ec02eb7dbba Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 29 Jul 2023 22:15:00 +0200 Subject: [PATCH 057/169] Expand global aliasing analysis --- oscar64/GlobalAnalyzer.cpp | 2 + oscar64/InterCode.cpp | 164 +++++++++++++++++++++++++++++++- oscar64/InterCode.h | 8 ++ oscar64/Linker.cpp | 4 +- oscar64/Linker.h | 2 +- oscar64/NativeCodeGenerator.cpp | 64 ++++++++++++- 6 files changed, 236 insertions(+), 8 deletions(-) diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 9a37e7f..4df17c1 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -660,6 +660,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo case EX_ASSIGNMENT: ldec = Analyze(exp->mLeft, procDec, true); rdec = Analyze(exp->mRight, procDec, false); + if (exp->mLeft->mType == EX_VARIABLE && exp->mRight->mType == EX_CALL && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT) + exp->mLeft->mDecValue->mFlags |= DTF_VAR_ALIASING; RegisterProc(rdec); return ldec; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 1a1b6cd..69ae93b 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -3095,6 +3095,11 @@ void InterInstruction::CollectLocalAddressTemps(GrowingIntArray& localTable, Gro nparams = mSrc[1].mVarIndex + 1; } } + else if (mSrc[1].mTemp >= 0) + { + localTable[mDst.mTemp] = localTable[mSrc[1].mTemp]; + paramTable[mDst.mTemp] = paramTable[mSrc[1].mTemp]; + } } else if (mCode == IC_LOAD_TEMPORARY) { @@ -9918,6 +9923,39 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& else nins = ins; } + else if (ins->mCode == IC_CALL_NATIVE && ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mLinkerObject && ins->mSrc[0].mLinkerObject->mProc && ins->mSrc[0].mLinkerObject->mProc->mGlobalsChecked) + { + InterCodeProcedure* proc = ins->mSrc[0].mLinkerObject->mProc; + + int j = 0, k = 0; + while (j < mLoadStoreInstructions.Size()) + { + InterOperand* op = nullptr; + + if (mLoadStoreInstructions[j]->mCode == IC_LOAD) + op = mLoadStoreInstructions[j]->mSrc + 0; + else if (mLoadStoreInstructions[j]->mCode == IC_STORE) + op = mLoadStoreInstructions[j]->mSrc + 1; + + bool flush = false; + if (op) + { + if (op->mTemp >= 0) + flush = proc->mStoresIndirect; + else if (op->mMemory == IM_FFRAME || op->mMemory == IM_FRAME) + flush = true; + else if (op->mMemory == IM_GLOBAL) + flush = proc->ModifiesGlobal(op->mVarIndex); + else + flush = true; + } + + if (!flush) + mLoadStoreInstructions[k++] = mLoadStoreInstructions[j]; + j++; + } + mLoadStoreInstructions.SetSize(k); + } else if (HasSideEffect(ins->mCode)) flushMem = true; @@ -11298,7 +11336,7 @@ void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVa for (int i = 0; i < mInstructions.Size(); i++) { - if (mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE) + if ((mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE) && mInstructions[i]->mSrc[0].mLinkerObject->mStackSection) lobj->mStackSection->mSections.Push(mInstructions[i]->mSrc[0].mLinkerObject->mStackSection); if (mInstructions[i]->mCode == IC_LOAD) @@ -15350,6 +15388,74 @@ void InterCodeBasicBlock::CheckValueReturn(void) } } +void InterCodeBasicBlock::CollectGlobalReferences(NumberSet& referencedGlobals, NumberSet& modifiedGlobals, bool& storesIndirect, bool& loadsIndirect, bool& globalsChecked) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* ins = mInstructions[i]; + + switch (ins->mCode) + { + case IC_LOAD: + if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_GLOBAL && ins->mSrc[0].mVarIndex >= 0) + referencedGlobals += ins->mSrc[0].mVarIndex; + else if (ins->mSrc[0].mTemp >= 0) + loadsIndirect = true; + break; + case IC_STORE: + if (ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_GLOBAL && ins->mSrc[1].mVarIndex >= 0) + { + referencedGlobals += ins->mSrc[1].mVarIndex; + modifiedGlobals += ins->mSrc[1].mVarIndex; + } + else if (ins->mSrc[1].mTemp >= 0) + storesIndirect = true; + break; + case IC_COPY: + case IC_STRCPY: + if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_GLOBAL && ins->mSrc[0].mVarIndex >= 0) + referencedGlobals += ins->mSrc[0].mVarIndex; + else if (ins->mSrc[0].mTemp >= 0) + loadsIndirect = true; + if (ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_GLOBAL && ins->mSrc[1].mVarIndex >= 0) + { + referencedGlobals += ins->mSrc[1].mVarIndex; + modifiedGlobals += ins->mSrc[1].mVarIndex; + } + else if (ins->mSrc[1].mTemp >= 0) + storesIndirect = true; + break; + case IC_CALL: + case IC_CALL_NATIVE: + if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mLinkerObject && ins->mSrc[0].mLinkerObject->mProc) + { + InterCodeProcedure* proc = ins->mSrc[0].mLinkerObject->mProc; + if (proc->mGlobalsChecked) + { + if (proc->mStoresIndirect) + storesIndirect = true; + if (proc->mLoadsIndirect) + loadsIndirect = true; + referencedGlobals |= proc->mReferencedGlobals; + modifiedGlobals |= proc->mModifiedGlobals; + } + else + globalsChecked = false; + } + else + globalsChecked = false; + break; + } + } + + if (mTrueJump) mTrueJump->CollectGlobalReferences(referencedGlobals, modifiedGlobals, storesIndirect, loadsIndirect, globalsChecked); + if (mFalseJump) mFalseJump->CollectGlobalReferences(referencedGlobals, modifiedGlobals, storesIndirect, loadsIndirect, globalsChecked); + } +} void InterCodeBasicBlock::WarnUsedUndefinedVariables(void) { @@ -15707,7 +15813,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), mCheckUnreachable(true), mReturnType(IT_NONE), mCheapInline(false), - mDeclaration(nullptr) + mDeclaration(nullptr), mGlobalsChecked(false) { mID = mModule->mProcedures.Size(); mModule->mProcedures.Push(this); @@ -16551,7 +16657,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "card_color"); mEntryBlock = mBlocks[0]; @@ -17173,6 +17279,7 @@ void InterCodeProcedure::Close(void) #if 1 ResetVisited(); + if (!mInterruptCalled && !mDynamicStack && mNativeProcedure && mEntryBlock->CheckStaticStack()) { mLinkerObject->mFlags |= LOBJF_STATIC_STACK; @@ -17379,6 +17486,18 @@ void InterCodeProcedure::Close(void) } } + if (mTempSize <= BC_REG_TMP_SAVED - BC_REG_TMP && !(mLinkerObject->mFlags & LOBJF_STATIC_STACK) && mLeafProcedure) + { + bool hasLocals = false; + + for (int i = 0; i < mLocalVars.Size(); i++) + if (mLocalVars[i] && mLocalVars[i]->mUsed) + hasLocals = true; + + if (!hasLocals) + mLinkerObject->mFlags |= LOBJF_STATIC_STACK; + } + if (!mEntryBlock->mTrueJump) { int nconst = 0, nvariables = 0, nparams = 0, ncalls = 0, nret = 0, nother = 0, nops = 0; @@ -17449,6 +17568,15 @@ void InterCodeProcedure::Close(void) if (nother == 0 && ncalls <= 1 && nret == 1 && nconst <= 1 + nparams && nops <= 1 + nparams) mCheapInline = true; } + + mGlobalsChecked = true; + mStoresIndirect = false; + mLoadsIndirect = false; + mReferencedGlobals.Reset(mModule->mGlobalVars.Size()); + mModifiedGlobals.Reset(mModule->mGlobalVars.Size()); + + ResetVisited(); + mEntryBlock->CollectGlobalReferences(mReferencedGlobals, mModifiedGlobals, mStoresIndirect, mLoadsIndirect, mGlobalsChecked); } void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc) @@ -17778,6 +17906,36 @@ void InterCodeProcedure::MergeBasicBlocks(void) } +bool InterCodeProcedure::ReferencesGlobal(int varindex) +{ + if (mGlobalsChecked) + { + if (mModule->mGlobalVars[varindex]->mAliased) + return mLoadsIndirect || mStoresIndirect; + else if (varindex < mReferencedGlobals.Size()) + return mReferencedGlobals[varindex]; + else + return false; + } + else + return true; +} + +bool InterCodeProcedure::ModifiesGlobal(int varindex) +{ + if (mGlobalsChecked) + { + if (mModule->mGlobalVars[varindex]->mAliased) + return mStoresIndirect; + else if (varindex < mModifiedGlobals.Size()) + return mModifiedGlobals[varindex]; + else + return false; + } + else + return true; +} + void InterCodeProcedure::BuildLoopPrefix(void) { ResetVisited(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index e15a0f9..75845db 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -576,6 +576,8 @@ public: void WarnUsedUndefinedVariables(void); void CheckValueReturn(void); + void CollectGlobalReferences(NumberSet& referencedGlobals, NumberSet& modifiedGlobals, bool & storesIndirect, bool & loadsIndirect, bool & globalsChecked); + }; class InterCodeProcedure @@ -614,6 +616,9 @@ public: InterType mReturnType; uint64 mCompilerOptions; + bool mLoadsIndirect, mStoresIndirect, mGlobalsChecked; + NumberSet mReferencedGlobals, mModifiedGlobals; + InterCodeProcedure(InterCodeModule * module, const Location & location, const Ident * ident, LinkerObject* linkerObject); ~InterCodeProcedure(void); @@ -631,6 +636,9 @@ public: void MapCallerSavedTemps(void); + bool ReferencesGlobal(int varindex); + bool ModifiesGlobal(int varindex); + void MapVariables(void); void ReduceTemporaries(void); void Disassemble(FILE* file); diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index c2a23cf..84eead1 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -43,12 +43,14 @@ void LinkerObject::AddReference(const LinkerReference& ref) mReferences.Push(nref); } -LinkerReference* LinkerObject::FindReference(int offset) +LinkerReference* LinkerObject::FindReference(int64 offset) { for (int i = 0; i < mReferences.Size(); i++) { if (mReferences[i]->mOffset == offset) return mReferences[i]; + else if ((mReferences[i]->mFlags & LREF_LOWBYTE) && (mReferences[i]->mFlags & LREF_HIGHBYTE) && mReferences[i]->mOffset + 1 == offset) + return mReferences[i]; } return nullptr; diff --git a/oscar64/Linker.h b/oscar64/Linker.h index ab6b3a8..ff9affa 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -202,7 +202,7 @@ public: GrowingArray mReferences; - LinkerReference* FindReference(int offset); + LinkerReference* FindReference(int64 offset); void AddReference(const LinkerReference& ref); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index ffb3809..5047cc1 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -7133,10 +7133,34 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, if (size <= msize) { - for (int i = 0; i < size; i++) + LinkerObject* slo = ins->mSrc[0].mLinkerObject; + if (slo && (slo->mFlags & LOBJF_CONST)) { - block->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + offset + i * sstride, ins->mSrc[0].mLinkerObject, flags)); - block->mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + offset + i * dstride, ins->mSrc[1].mLinkerObject, flags)); + + for (int i = 0; i < size; i++) + { + int64 si = ins->mSrc[0].mIntConst + offset + i * sstride; + + LinkerReference* lr = slo->FindReference(si); + if (lr) + { + if ((lr->mFlags & LREF_LOWBYTE) && lr->mOffset == si) + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, lr->mRefOffset, lr->mRefObject, NCIF_LOWER)); + else + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, lr->mRefOffset, lr->mRefObject, NCIF_UPPER)); + } + else + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, slo->mData[si])); + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + offset + i * dstride, ins->mSrc[1].mLinkerObject, flags)); + } + } + else + { + for (int i = 0; i < size; i++) + { + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + offset + i * sstride, ins->mSrc[0].mLinkerObject, flags)); + block->mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ABSOLUTE, ins->mSrc[1].mIntConst + offset + i * dstride, ins->mSrc[1].mLinkerObject, flags)); + } } } else @@ -7156,6 +7180,40 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, return block; } + else if ((ins->mSrc[0].mMemory == IM_GLOBAL || ins->mSrc[0].mMemory == IM_ABSOLUTE) && (ins->mSrc[1].mMemory == IM_FPARAM || ins->mSrc[1].mMemory == IM_FFRAME)) + { + LinkerObject* slo = ins->mSrc[0].mLinkerObject; + if (slo && (slo->mFlags & LOBJF_CONST)) + { + + for (int i = 0; i < size; i++) + { + int64 si = ins->mSrc[0].mIntConst + i * sstride; + + LinkerReference* lr = slo->FindReference(si); + if (lr) + { + if ((lr->mFlags & LREF_LOWBYTE) && lr->mOffset == si) + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, lr->mRefOffset, lr->mRefObject, NCIF_LOWER)); + else + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, lr->mRefOffset, lr->mRefObject, NCIF_UPPER)); + } + else + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, slo->mData[si])); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + i * dstride)); + } + } + else + { + for (int i = 0; i < size; i++) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst + i * sstride, ins->mSrc[0].mLinkerObject, flags)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[1].mVarIndex + ins->mSrc[1].mIntConst + i * dstride)); + } + } + + return this; + } } #endif From e013142cb18d646ec98aa718cdc4fcf1c12c97fe Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 30 Jul 2023 11:24:19 +0200 Subject: [PATCH 058/169] Cross block register optimizations --- oscar64/InterCode.cpp | 53 ++++++++ oscar64/InterCode.h | 1 + oscar64/NativeCodeGenerator.cpp | 229 +++++++++++++++++++++++++------- oscar64/NativeCodeGenerator.h | 2 + 4 files changed, 234 insertions(+), 51 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 69ae93b..2c4dbd7 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -6376,6 +6376,47 @@ static int64 BuildLowerBitsMask(int64 v) return v; } +void InterCodeBasicBlock::MarkIntegerRangeBoundUp(int temp, int64 value, GrowingIntegerValueRangeArray& range) +{ + range[temp].SetLimit(value, value); + + for (int i = mInstructions.Size() - 1; i >= 0; i--) + { + InterInstruction* ins(mInstructions[i]); + + if (ins->mDst.mTemp == temp) + { + if (ins->mCode == IC_BINARY_OPERATOR && ins->mSrc[1].mTemp == temp && ins->mSrc[0].mTemp < 0) + { + switch (ins->mOperator) + { + case IA_ADD: + value -= ins->mSrc[0].mIntConst; + break; + case IA_SUB: + value += ins->mSrc[0].mIntConst; + break; + default: + return; + } + } + else if (ins->mCode == IC_LOAD_TEMPORARY) + { + if (!IsTempModifiedInRange(i + 1, mInstructions.Size(), ins->mSrc[0].mTemp)) + range[ins->mSrc[0].mTemp].SetLimit(value, value); + temp = ins->mSrc[0].mTemp; + } + else + return; + } + else if (ins->mCode == IC_LOAD_TEMPORARY && ins->mSrc[0].mTemp == temp) + { + if (!IsTempModifiedInRange(i + 1, mInstructions.Size(), ins->mDst.mTemp)) + range[ins->mDst.mTemp].SetLimit(value, value); + } + } +} + void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars) { mLocalValueRange = mEntryValueRange; @@ -7328,34 +7369,46 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray case IA_CMPEQ: if (s0 < 0) { + MarkIntegerRangeBoundUp(s1, mInstructions[sz - 2]->mSrc[0].mIntConst, mTrueValueRange); +#if 0 mTrueValueRange[s1].mMinState = IntegerValueRange::S_BOUND; mTrueValueRange[s1].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst; mTrueValueRange[s1].mMaxState = IntegerValueRange::S_BOUND; mTrueValueRange[s1].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst; +#endif } else if (s1 < 0) { + MarkIntegerRangeBoundUp(s0, mInstructions[sz - 2]->mSrc[1].mIntConst, mTrueValueRange); +#if 0 mTrueValueRange[s0].mMinState = IntegerValueRange::S_BOUND; mTrueValueRange[s0].mMinValue = mInstructions[sz - 2]->mSrc[1].mIntConst; mTrueValueRange[s0].mMaxState = IntegerValueRange::S_BOUND; mTrueValueRange[s0].mMaxValue = mInstructions[sz - 2]->mSrc[1].mIntConst; +#endif } break; case IA_CMPNE: if (s0 < 0) { + MarkIntegerRangeBoundUp(s1, mInstructions[sz - 2]->mSrc[0].mIntConst, mFalseValueRange); +#if 0 mFalseValueRange[s1].mMinState = IntegerValueRange::S_BOUND; mFalseValueRange[s1].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst; mFalseValueRange[s1].mMaxState = IntegerValueRange::S_BOUND; mFalseValueRange[s1].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst; +#endif } else if (s1 < 0) { + MarkIntegerRangeBoundUp(s0, mInstructions[sz - 2]->mSrc[1].mIntConst, mFalseValueRange); +#if 0 mFalseValueRange[s0].mMinState = IntegerValueRange::S_BOUND; mFalseValueRange[s0].mMinValue = mInstructions[sz - 2]->mSrc[1].mIntConst; mFalseValueRange[s0].mMaxState = IntegerValueRange::S_BOUND; mFalseValueRange[s0].mMaxValue = mInstructions[sz - 2]->mSrc[1].mIntConst; +#endif } break; #endif diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 75845db..260e406 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -440,6 +440,7 @@ public: void UpdateLocalIntegerRangeSets(const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars); bool BuildGlobalIntegerRangeSets(bool initial, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars); void SimplifyIntegerRangeRelops(void); + void MarkIntegerRangeBoundUp(int temp, int64 value, GrowingIntegerValueRangeArray& range); bool CombineIndirectAddressing(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 5047cc1..2b8683c 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -20706,6 +20706,100 @@ bool NativeCodeBasicBlock::CanCrossBlockYShortcut(int addr) return false; } +bool NativeCodeBasicBlock::CrossBlockRegisterAlias(bool sameAX, bool sameAY) +{ + bool changed = false; + if (!mVisited) + { + mVisited = true; + + if (mNumEntries > 1) + { + sameAX = false; + sameAY = false; + } + + bool direct = false; + for (int i = 0; i < mIns.Size(); i++) + { + NativeCodeInstruction& ins(mIns[i]); + switch (ins.mType) + { + case ASMIT_TAY: + sameAY = true; + break; + case ASMIT_TAX: + sameAX = true; + break; + case ASMIT_TYA: + sameAY = true; + sameAX = false; + direct = true; + break; + case ASMIT_TXA: + sameAY = false; + sameAX = true; + direct = true; + break; + case ASMIT_CMP: + if (!(ins.mLive & LIVE_CPU_REG_A)) + { + if (sameAY && (ins.mLive & LIVE_CPU_REG_Y) && HasAsmInstructionMode(ASMIT_CPY, ins.mMode)) + { + ins.mType = ASMIT_CPY; + changed = true; + } + else if (sameAX && (ins.mLive & LIVE_CPU_REG_X) && HasAsmInstructionMode(ASMIT_CPX, ins.mMode)) + { + ins.mType = ASMIT_CPX; + changed = true; + } + } + break; + case ASMIT_CPX: + if (!direct && !(ins.mLive & LIVE_CPU_REG_X)) + { + if (sameAX && (ins.mLive & LIVE_CPU_REG_A)) + { + ins.mType = ASMIT_CMP; + changed = true; + } + } + break; + case ASMIT_CPY: + if (!direct && !(ins.mLive & LIVE_CPU_REG_Y)) + { + if (sameAY && (ins.mLive & LIVE_CPU_REG_A)) + { + ins.mType = ASMIT_CMP; + changed = true; + } + } + break; + default: + if (ins.ChangesAccu()) + { + sameAY = false; + sameAX = false; + } + if (ins.ChangesXReg()) + sameAX = false; + if (ins.ChangesYReg()) + sameAY = false; + break; + } + } + + + if (mTrueJump && mTrueJump->CrossBlockRegisterAlias(sameAX, sameAY)) + changed = true; + if (mFalseJump && mFalseJump->CrossBlockRegisterAlias(sameAX, sameAY)) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::CrossBlockYAliasProgpagation(const int* yalias, int yoffset) { bool changed = false; @@ -31540,13 +31634,23 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) { if (zxreg[ins.mAddress] >= 0) { - zxreg[ins.mAddress] += 3; - xskew++; + if (ins.mLive & LIVE_CPU_REG_X) + zxreg[ins.mAddress] = -1; + else + { + zxreg[ins.mAddress] += 3; + xskew++; + } } if (zyreg[ins.mAddress] >= 0) { - zyreg[ins.mAddress] += 3; - yskew++; + if (ins.mLive & LIVE_CPU_REG_Y) + zyreg[ins.mAddress] = -1; + else + { + zyreg[ins.mAddress] += 3; + yskew++; + } } zareg[ins.mAddress] = -1; @@ -31557,13 +31661,23 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) { if (zxreg[ins.mAddress] >= 0) { - zxreg[ins.mAddress] += 3; - xskew--; + if (ins.mLive & LIVE_CPU_REG_X) + zxreg[ins.mAddress] = -1; + else + { + zxreg[ins.mAddress] += 3; + xskew--; + } } if (zyreg[ins.mAddress] >= 0) { - zyreg[ins.mAddress] += 3; - yskew--; + if (ins.mLive & LIVE_CPU_REG_Y) + zyreg[ins.mAddress] = -1; + else + { + zyreg[ins.mAddress] += 3; + yskew--; + } } zareg[ins.mAddress] = -1; @@ -31762,47 +31876,6 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) block->mExitRequiredRegs += CPU_REG_A; } - if (block->mTrueJump && !lblocks.Contains(block->mTrueJump)) - { - block->mTrueJump = block->BuildSingleEntry(proc, block->mTrueJump); - if (areg >= 0 && block->mTrueJump->mEntryRequiredRegs[areg]) - { - if (areg < 256) - block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STA, ASMIM_ZERO_PAGE, areg)); - block->mTrueJump->mEntryRequiredRegs += CPU_REG_A; - } - if (yreg >= 0 && block->mTrueJump->mEntryRequiredRegs[yreg]) - { - block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, yreg)); - block->mTrueJump->mEntryRequiredRegs += CPU_REG_Y; - } - if (xreg >= 0 && block->mTrueJump->mEntryRequiredRegs[xreg]) - { - block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STX, ASMIM_ZERO_PAGE, xreg)); - block->mTrueJump->mEntryRequiredRegs += CPU_REG_X; - } - } - if (block->mFalseJump && !lblocks.Contains(block->mFalseJump)) - { - block->mFalseJump = block->BuildSingleEntry(proc, block->mFalseJump); - if (areg >= 0 && block->mFalseJump->mEntryRequiredRegs[areg]) - { - if (areg < 256) - block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STA, ASMIM_ZERO_PAGE, areg)); - block->mFalseJump->mEntryRequiredRegs += CPU_REG_A; - } - if (yreg >= 0 && block->mFalseJump->mEntryRequiredRegs[yreg]) - { - block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, yreg)); - block->mFalseJump->mEntryRequiredRegs += CPU_REG_Y; - } - if (xreg >= 0 && block->mFalseJump->mEntryRequiredRegs[xreg]) - { - block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STX, ASMIM_ZERO_PAGE, xreg)); - block->mFalseJump->mEntryRequiredRegs += CPU_REG_X; - } - } - for (int j = 0; j < block->mEntryBlocks.Size(); j++) { if (!lblocks.Contains(block->mEntryBlocks[j])) @@ -31831,7 +31904,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) } } - int yoffset = 0, xoffset = 0; + int yoffset = 0, xoffset = 0, xskew = 0, yskew = 0; for (int j = 0; j < block->mIns.Size(); j++) { @@ -31846,6 +31919,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) ins.mType = ASMIT_NOP; ins.mMode = ASMIM_IMPLIED; yoffset = 0; + yskew = 0; } break; case ASMIT_LDX: @@ -31855,6 +31929,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) ins.mType = ASMIT_NOP; ins.mMode = ASMIM_IMPLIED; xoffset = 0; + xskew = 0; } break; case ASMIT_INC: @@ -31862,11 +31937,13 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) { ins.mType = ASMIT_INY; ins.mMode = ASMIM_IMPLIED; + yskew += 1; } else if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == xreg) { ins.mType = ASMIT_INX; ins.mMode = ASMIM_IMPLIED; + xskew += 1; } break; case ASMIT_DEC: @@ -31874,11 +31951,13 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) { ins.mType = ASMIT_DEY; ins.mMode = ASMIM_IMPLIED; + yskew -= 1; } else if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == xreg) { ins.mType = ASMIT_DEX; ins.mMode = ASMIM_IMPLIED; + xskew -= 1; } break; @@ -31995,6 +32074,47 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) } + if (block->mTrueJump && !lblocks.Contains(block->mTrueJump)) + { + block->mTrueJump = block->BuildSingleEntry(proc, block->mTrueJump); + if (areg >= 0 && block->mTrueJump->mEntryRequiredRegs[areg]) + { + if (areg < 256) + block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STA, ASMIM_ZERO_PAGE, areg)); + block->mTrueJump->mEntryRequiredRegs += CPU_REG_A; + } + if (yreg >= 0 && block->mTrueJump->mEntryRequiredRegs[yreg]) + { + block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, yreg)); + block->mTrueJump->mEntryRequiredRegs += CPU_REG_Y; + } + if (xreg >= 0 && block->mTrueJump->mEntryRequiredRegs[xreg]) + { + block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STX, ASMIM_ZERO_PAGE, xreg)); + block->mTrueJump->mEntryRequiredRegs += CPU_REG_X; + } + } + if (block->mFalseJump && !lblocks.Contains(block->mFalseJump)) + { + block->mFalseJump = block->BuildSingleEntry(proc, block->mFalseJump); + if (areg >= 0 && block->mFalseJump->mEntryRequiredRegs[areg]) + { + if (areg < 256) + block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STA, ASMIM_ZERO_PAGE, areg)); + block->mFalseJump->mEntryRequiredRegs += CPU_REG_A; + } + if (yreg >= 0 && block->mFalseJump->mEntryRequiredRegs[yreg]) + { + block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, yreg)); + block->mFalseJump->mEntryRequiredRegs += CPU_REG_Y; + } + if (xreg >= 0 && block->mFalseJump->mEntryRequiredRegs[xreg]) + { + block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STX, ASMIM_ZERO_PAGE, xreg)); + block->mFalseJump->mEntryRequiredRegs += CPU_REG_X; + } + } + block->CheckLive(); } @@ -40551,7 +40671,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "test"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "enemies_find"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41631,6 +41751,13 @@ void NativeCodeProcedure::Optimize(void) } #endif + if (step == 7) + { + ResetVisited(); + if (mEntryBlock->CrossBlockRegisterAlias(false, false)) + changed = true; + } + if (step == 8) { ResetVisited(); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index ff5d34f..e103579 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -525,6 +525,8 @@ public: bool CrossBlockYAliasProgpagation(const int * yalias, int yoffset); + bool CrossBlockRegisterAlias(bool sameAX, bool sameAY); + bool BypassRegisterConditionBlock(void); bool FoldLoopEntry(void); From 8a283cc43b118bb4a00f5a075190532deff7ad07 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 30 Jul 2023 13:57:15 +0200 Subject: [PATCH 059/169] Fix register conflict in short index forwarding --- oscar64/NativeCodeGenerator.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 2b8683c..2a60306 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -23912,7 +23912,7 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to) mIns[i].mType = ASMIT_LDX; else if (mIns[i].mType == ASMIT_STA) mIns[i].mType = ASMIT_STX; - mIns[i].mLive |= LIVE_CPU_REG_X; + mIns[i].mLive |= LIVE_CPU_REG_X | LIVE_CPU_REG_A; } mIns[from].mType = ASMIT_NOP; mIns[from].mMode = ASMIM_IMPLIED; mIns[to].mType = ASMIT_NOP; mIns[to].mMode = ASMIM_IMPLIED; @@ -39128,6 +39128,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 4].mType == ASMIT_LDA && mIns[i + 4].mMode == ASMIM_ZERO_PAGE && mIns[i + 4].mAddress == mIns[i + 1].mAddress + 1 && mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_IMMEDIATE && mIns[i + 6].mType == ASMIT_STA && mIns[i + 6].mMode == ASMIM_ZERO_PAGE && mIns[i + 6].mAddress == mIns[i + 3].mAddress + 1 && + mIns[i + 2].mAddress != mIns[i + 3].mAddress && !(mIns[i + 6].mLive & LIVE_CPU_REG_A)) { int yval = RetrieveYValue(i); @@ -40671,7 +40672,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "enemies_find"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "robot_move"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; From 34c0df228b7cbf1c27abc25e61423fbb51347ac3 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 30 Jul 2023 14:46:32 +0200 Subject: [PATCH 060/169] Bump version number --- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index b02728b..ace2e49 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.23.213"); + strcpy(strProductVersion, "1.23.214"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index b888c26..9520ced 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,23,213,0 - PRODUCTVERSION 1,23,213,0 + FILEVERSION 1,23,214,0 + PRODUCTVERSION 1,23,214,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.23.213.0" + VALUE "FileVersion", "1.23.214.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.23.213.0" + VALUE "ProductVersion", "1.23.214.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 8051e99..154e0c6 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5504,15 +5504,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{69DF35C1-7D87-4EFB-B4D9-ECA259B2955E}" - "PackageCode" = "8:{B8C99499-4F97-4641-BF54-0202149091C6}" + "ProductCode" = "8:{39A4B196-6F41-483E-B0B5-95BC052CADFE}" + "PackageCode" = "8:{1726C6F5-01F2-4105-BF06-3712F9EFA860}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.23.213" + "ProductVersion" = "8:1.23.214" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From fa218d8dd7dd122ca44b2282743d86706efa50e1 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 31 Jul 2023 22:53:55 +0200 Subject: [PATCH 061/169] Fix adc to inx with wrong address mode --- include/c64/rasterirq.c | 5 ++- oscar64/NativeCodeGenerator.cpp | 54 ++++++++++++++++++++++++++++++--- oscar64/NativeCodeGenerator.h | 1 + 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/include/c64/rasterirq.c b/include/c64/rasterirq.c index 5ccc8c5..442dcfc 100644 --- a/include/c64/rasterirq.c +++ b/include/c64/rasterirq.c @@ -97,6 +97,9 @@ __asm irq2 tya pha + lda $01 + pha + lda #$35 sta $01 @@ -136,7 +139,7 @@ ji: ex: - lda PLAShadow + pla sta $01 pla diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 2a60306..967860c 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -16462,7 +16462,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) mIns[i + 0].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_NOP; - mIns[i + 2].mType = ASMIT_INX; mIns[i + 2].mLive |= LIVE_CPU_REG_Z | LIVE_CPU_REG_X; + mIns[i + 2].mType = ASMIT_INX; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_Z | LIVE_CPU_REG_X; mIns[i + 3].mType = ASMIT_STX; mIns[i + 3].mLive |= LIVE_CPU_REG_Z; fblock->mIns.Push(mIns[i + 4]); @@ -27126,7 +27126,7 @@ bool NativeCodeBasicBlock::MoveLDSTXOutOfRange(int at) if (mIns[j].mType == ASMIT_JSR) return false; - if (!(mIns[j].mLive & LIVE_CPU_REG_A)) + if (!(mIns[j].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))) { mIns.Insert(j + 1, NativeCodeInstruction(mIns[at + 1].mIns, ASMIT_STA, mIns[at + 1])); mIns.Insert(j + 1, NativeCodeInstruction(mIns[at].mIns, ASMIT_LDA, mIns[at])); @@ -35333,7 +35333,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 1].mType == ASMIT_AND && mIns[i + 1].mMode == ASMIM_IMMEDIATE && (mIns[i + 1].mAddress & 0x01) && !(mIns[i + 1].mLive & LIVE_CPU_REG_C)) { mIns[i + 0] = mIns[i + 1]; - mIns[i + 0].mLive |= LIVE_CPU_REG_C; + mIns[i + 0].mLive |= LIVE_CPU_REG_C | LIVE_CPU_REG_A; mIns[i + 0].mAddress = (mIns[i + 0].mAddress >> 1) & 0x7f; mIns[i + 1].mType = ASMIT_ROL; mIns[i + 1].mMode = ASMIM_IMPLIED; progress = true; @@ -35343,7 +35343,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 1].mType == ASMIT_AND && mIns[i + 1].mMode == ASMIM_IMMEDIATE && (mIns[i + 1].mAddress & 0x80) && !(mIns[i + 1].mLive & LIVE_CPU_REG_C)) { mIns[i + 0] = mIns[i + 1]; - mIns[i + 0].mLive |= LIVE_CPU_REG_C; + mIns[i + 0].mLive |= LIVE_CPU_REG_C | LIVE_CPU_REG_A; mIns[i + 0].mAddress = (mIns[i + 0].mAddress << 1) & 0xfe; mIns[i + 1].mType = ASMIT_ROR; mIns[i + 1].mMode = ASMIM_IMPLIED; progress = true; @@ -39976,6 +39976,23 @@ void NativeCodeBasicBlock::CheckVisited(void) #endif } +void NativeCodeBasicBlock::CheckAsmCode(void) +{ +#if _DEBUG + if (!mVisited) + { + mVisited = true; + + for (int j = 0; j < mIns.Size(); j++) + { + assert(HasAsmInstructionMode(mIns[j].mType, mIns[j].mMode)); + } + + if (mTrueJump) mTrueJump->CheckAsmCode(); + if (mFalseJump) mFalseJump->CheckAsmCode(); + } +#endif +} void NativeCodeBasicBlock::CheckBlocks(bool sequence) @@ -40672,7 +40689,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "robot_move"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "time_draw"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41405,6 +41422,11 @@ void NativeCodeProcedure::Optimize(void) { changed = true; +#if _DEBUG + ResetVisited(); + mEntryBlock->CheckBlocks(); +#endif + BuildDataFlowSets(); ResetVisited(); mEntryBlock->RemoveUnusedResultInstructions(); @@ -41418,6 +41440,10 @@ void NativeCodeProcedure::Optimize(void) if (mEntryBlock->AbsoluteValueForwarding(pairs)) { changed = true; +#if _DEBUG + ResetVisited(); + mEntryBlock->CheckBlocks(); +#endif BuildDataFlowSets(); ResetVisited(); @@ -41869,6 +41895,11 @@ void NativeCodeProcedure::Optimize(void) } #endif +#if _DEBUG + ResetVisited(); + mEntryBlock->CheckAsmCode(); +#endif + #if 1 if (step == 8) { @@ -41896,6 +41927,10 @@ void NativeCodeProcedure::Optimize(void) changed = true; } #endif +#if _DEBUG + ResetVisited(); + mEntryBlock->CheckAsmCode(); +#endif #if 1 if (step == 9) { @@ -41907,6 +41942,10 @@ void NativeCodeProcedure::Optimize(void) #endif RebuildEntry(); +#if _DEBUG + ResetVisited(); + mEntryBlock->CheckAsmCode(); +#endif #if 1 if (step == 2 && !changed) { @@ -41954,6 +41993,11 @@ void NativeCodeProcedure::Optimize(void) } #endif +#if _DEBUG + ResetVisited(); + mEntryBlock->CheckAsmCode(); +#endif + #if 1 if (cnt > 190) { diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index e103579..d417e8e 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -668,6 +668,7 @@ public: void CheckLive(void); void CheckBlocks(bool sequence = false); + void CheckAsmCode(void); void CheckVisited(void); }; From 19ab2b8d38bea0606daa107f108615c0cf3d3063 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 1 Aug 2023 13:46:30 +0200 Subject: [PATCH 062/169] Fix linux build --- oscar64/NativeCodeGenerator.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 967860c..5d9bbfd 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -36165,7 +36165,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass } else if ( mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && - !mIns[i + 1].ChangesZeroPage(mIns[i + 0].mAddress) && !mIns[i + 1].RequiresYReg() && + !mIns[i + 1].ChangesZeroPage(mIns[i + 0].mAddress) && !mIns[i + 1].RequiresYReg() && !mIns[i + 1].ChangesYReg() && mIns[i + 2].mType == ASMIT_LDY && mIns[i + 2].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 2].mLive & LIVE_MEM)) { mIns[i + 0].mType = ASMIT_TAY; mIns[i + 0].mMode = ASMIM_IMPLIED; @@ -39985,7 +39985,10 @@ void NativeCodeBasicBlock::CheckAsmCode(void) for (int j = 0; j < mIns.Size(); j++) { - assert(HasAsmInstructionMode(mIns[j].mType, mIns[j].mMode)); + if (mIns[j].mMode == ASMIM_IMMEDIATE_ADDRESS) + assert(HasAsmInstructionMode(mIns[j].mType, ASMIM_IMMEDIATE)); + else + assert(HasAsmInstructionMode(mIns[j].mType, mIns[j].mMode)); } if (mTrueJump) mTrueJump->CheckAsmCode(); From b1a42e5ecf194683fbd13d105d3ca58a84fcc5d6 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:50:11 +0200 Subject: [PATCH 063/169] Fix linux build --- oscar64/InterCode.cpp | 6 ++++-- oscar64/NativeCodeGenerator.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 2c4dbd7..9bd5e5f 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -3069,7 +3069,6 @@ void InterInstruction::CollectLocalAddressTemps(GrowingIntArray& localTable, Gro if (mConst.mVarIndex >= nparams) nparams = mConst.mVarIndex + 1; } - } else if (mCode == IC_LEA) { @@ -16695,6 +16694,9 @@ void InterCodeProcedure::BuildLocalAliasTable(void) GrowingIntArray localTable(-1), paramTable(-1); int nlocals = 0, nparams = 0; + localTable.SetSize(mTemporaries.Size()); + paramTable.SetSize(mTemporaries.Size()); + ResetVisited(); mEntryBlock->CollectLocalAddressTemps(localTable, paramTable, nlocals, nparams); @@ -16710,7 +16712,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "card_color"); + CheckFunc = !strcmp(mIdent->mString, "playSong"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 5d9bbfd..13641af 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -379,7 +379,7 @@ NativeCodeInstruction::NativeCodeInstruction(const InterInstruction* ins, AsmIns } if (mode == ASMIM_ZERO_PAGE) { - assert(address >= 2 && address < 256); + assert(address >= 1 && address < 256); } } From ec15336174d0c4b1dd511f12ced4559d8c17ae55 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 1 Aug 2023 22:17:55 +0200 Subject: [PATCH 064/169] Fix stack allocation with false recursion with function pointers --- oscar64/GlobalAnalyzer.cpp | 4 +++- oscar64/NativeCodeGenerator.cpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 4df17c1..d9113fe 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -297,14 +297,16 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head) for (int i = 0; i < mVariableFunctions.Size(); i++) { Declaration* vf = mVariableFunctions[i]; - CheckFastcall(vf, false); if (vf->mBase->IsSame(cf)) { + CheckFastcall(vf, false); + int n = vf->mBase->mFastCallBase + vf->mBase->mFastCallSize; if (n > nbase) nbase = n; } + } // procDec->mFlags |= DTF_DYNSTACK; } diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 13641af..9ad5473 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -3503,7 +3503,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT } changed = true; } - else if (data.mRegs[mAddress].mMode == NRDM_ZERO_PAGE) + else if (data.mRegs[mAddress].mMode == NRDM_ZERO_PAGE && (mAddress < BC_REG_FPARAMS || mAddress >= BC_REG_FPARAMS_END)) { data.mRegs[CPU_REG_A] = data.mRegs[mAddress]; mAddress = data.mRegs[CPU_REG_A].mValue; @@ -41410,7 +41410,7 @@ void NativeCodeProcedure::Optimize(void) t++; - } while (changed); + } while (changed && t < 20); #endif BuildDataFlowSets(); From f3eb6e19cf09e2af72a045958404a3d7dc9bf536 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 2 Aug 2023 16:52:45 +0200 Subject: [PATCH 065/169] Fix linux build --- include/c64/mouse.c | 10 +-- oscar64/InterCode.cpp | 10 ++- oscar64/InterCode.h | 1 + oscar64/InterCodeGenerator.cpp | 2 +- oscar64/Parser.cpp | 119 +++++++++++++++++++-------------- 5 files changed, 83 insertions(+), 59 deletions(-) diff --git a/include/c64/mouse.c b/include/c64/mouse.c index 5fcf93a..70a7078 100644 --- a/include/c64/mouse.c +++ b/include/c64/mouse.c @@ -7,20 +7,20 @@ bool mouse_lb, mouse_rb; static char mouse_px, mouse_py; static char mouse_port; -inline signed char dpos(char * old, char new) +inline signed char dpos(char * old, char mnew) { - new = (new & 0x7f) >> 1; + mnew = (mnew & 0x7f) >> 1; - char diff = (new - *old) & 0x3f; + char diff = (mnew - *old) & 0x3f; if (diff >= 0x20) { - *old = new; + *old = mnew; return diff | 0xe0; } else if (diff) { - *old = new; + *old = mnew; return diff; } diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 9bd5e5f..8b0862a 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4523,6 +4523,11 @@ void InterCodeBasicBlock::Append(InterInstruction * code) { assert(code->mDst.mType == code->mConst.mType); } + if (code->mCode == IC_CONSTANT && code->mConst.mType == IT_POINTER && code->mConst.mMemory == IM_GLOBAL && code->mConst.mVarIndex >= 0) + { + assert(code->mConst.mVarIndex < mProc->mModule->mGlobalVars.Size()); + assert(mProc->mModule->mGlobalVars[code->mConst.mVarIndex]); + } for (int i = 0; i < code->mNumOperands; i++) assert(code->mSrc[i].mType != IT_NONE); @@ -11370,10 +11375,12 @@ bool InterCodeBasicBlock::CheckStaticStack(void) return true; } -void ApplyStaticStack(InterOperand & iop, const GrowingVariableArray& localVars) +void InterCodeBasicBlock::ApplyStaticStack(InterOperand & iop, const GrowingVariableArray& localVars) { if (iop.mMemory == IM_LOCAL) { + assert(localVars[iop.mVarIndex]->mIndex < mProc->mModule->mGlobalVars.Size()); + iop.mMemory = IM_GLOBAL; iop.mLinkerObject = localVars[iop.mVarIndex]->mLinkerObject; iop.mVarIndex = localVars[iop.mVarIndex]->mIndex; @@ -11419,6 +11426,7 @@ void PromoteStaticStackParam(InterOperand& iop, LinkerObject* paramlobj) iop.mMemory = IM_GLOBAL; iop.mIntConst += offset; iop.mLinkerObject = paramlobj; + iop.mVarIndex = -1; paramlobj->EnsureSpace(int(iop.mIntConst), iop.mOperandSize); } } diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 260e406..1049569 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -569,6 +569,7 @@ public: bool DropUnreachable(void); bool CheckStaticStack(void); + void ApplyStaticStack(InterOperand& iop, const GrowingVariableArray& localVars); void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars); void PromoteStaticStackParams(LinkerObject* paramlobj); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 7414ced..0c09be3 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1288,7 +1288,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I pcins->mConst.mVarIndex = ccdec->mVarIndex; pcins->mConst.mIntConst = 0; pcins->mConst.mOperandSize = 2; - pcins->mConst.mMemory = IM_GLOBAL; + pcins->mConst.mMemory = IM_PROCEDURE; pcins->mConst.mLinkerObject = ccdec->mLinkerObject; block->Append(pcins); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 92cdf6c..9565772 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -4717,6 +4717,8 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) dist += 1; else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_FUNCTION && ptype->mBase->IsSame(etype)) dist += 0; + else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_POINTER && etype->mBase->mType == DT_TYPE_VOID) + dist += 0; else if (ptype->IsSubType(etype)) dist += 256; else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->IsSame(etype)) @@ -5233,31 +5235,40 @@ Expression* Parser::ParsePrefixExpression(bool lhs) if (mScanner->mToken == TK_OPEN_PARENTHESIS || dec->mDefaultConstructor) { - Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); - vdec->mVarIndex = mLocalIndex++; - vdec->mBase = nexp->mDecType; - vdec->mSize = 2; - - Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); - vexp->mDecType = vdec->mBase; - vexp->mDecValue = vdec; - - Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); - iexp->mToken = TK_ASSIGN; - iexp->mLeft = vexp; - iexp->mRight = nexp; - iexp->mDecType = nexp->mDecType; - Declaration* mdec = dec->mDefaultConstructor; - Expression* pexp = vexp; + bool plist = false; if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) { if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) { - pexp = ParseListExpression(false); - + plist = true; mdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+")); + } + } + + if (mdec) + { + Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + vdec->mVarIndex = mLocalIndex++; + vdec->mBase = nexp->mDecType; + vdec->mSize = 2; + + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = vdec->mBase; + vexp->mDecValue = vdec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + iexp->mToken = TK_ASSIGN; + iexp->mLeft = vexp; + iexp->mRight = nexp; + iexp->mDecType = nexp->mDecType; + + Expression* pexp = vexp; + + if (plist) + { + pexp = ParseListExpression(false); ConsumeToken(TK_CLOSE_PARENTHESIS); @@ -5266,41 +5277,45 @@ Expression* Parser::ParsePrefixExpression(bool lhs) lexp->mRight = pexp; pexp = lexp; } + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + + dexp = ResolveOverloadCall(dexp); + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = vexp; + sexp->mDecType = vexp->mDecType; + + Expression* coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); + coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); + coexp->mLeft->mDecType = TheBoolTypeDeclaration; + coexp->mLeft->mToken = TK_EQUAL; + coexp->mLeft->mLeft = vexp; + coexp->mLeft->mRight = nuexp; + coexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + coexp->mRight->mLeft = vexp; + coexp->mRight->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + coexp->mRight->mRight->mLeft = dexp; + coexp->mRight->mRight->mRight = vexp; + coexp->mDecType = vexp->mDecType; + + nexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + nexp->mLeft = iexp; + nexp->mRight = coexp; + nexp->mDecType = coexp->mDecType; + } + else if (plist) + { + mErrors->Error(mScanner->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor", dec->mIdent); } - - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; - - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; - - dexp = ResolveOverloadCall(dexp); - - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - - sexp->mLeft = dexp; - sexp->mRight = vexp; - sexp->mDecType = vexp->mDecType; - - Expression * coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); - coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); - coexp->mLeft->mDecType = TheBoolTypeDeclaration; - coexp->mLeft->mToken = TK_EQUAL; - coexp->mLeft->mLeft = vexp; - coexp->mLeft->mRight = nuexp; - coexp->mRight = new Expression(mScanner->mLocation, EX_LIST); - coexp->mRight->mLeft = vexp; - coexp->mRight->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); - coexp->mRight->mRight->mLeft = dexp; - coexp->mRight->mRight->mRight = vexp; - coexp->mDecType = vexp->mDecType; - - nexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - nexp->mLeft = iexp; - nexp->mRight = coexp; - nexp->mDecType = coexp->mDecType; } } } From eac12e4559ef0ca1409dd97e7661dd872bbc0afa Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 2 Aug 2023 22:29:10 +0200 Subject: [PATCH 066/169] Fix cpp compare of two derived pointers --- oscar64/InterCodeGenerator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 0c09be3..6c85e03 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -2665,6 +2665,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { if (vl.mType->mBase->mType == DT_TYPE_VOID || vr.mType->mBase->mType == DT_TYPE_VOID) ; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && (vl.mType->mBase->IsSubType(vr.mType->mBase) || vr.mType->mBase->IsSubType(vl.mType->mBase))) + ; else if (!vl.mType->mBase->IsConstSame(vr.mType->mBase)) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible pointer types"); } From 58ab6818ed0ed3d590fc08cbca4f39155af6a727 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 3 Aug 2023 13:34:23 +0200 Subject: [PATCH 067/169] Add alignment for functions --- include/conio.c | 31 +++++++++++++++++++++++++++++++ include/conio.h | 4 ++++ oscar64/InterCodeGenerator.cpp | 19 ++++++++++++++++--- oscar64/Parser.cpp | 16 +++++++++++++++- 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/include/conio.c b/include/conio.c index afc8e1a..6b4b008 100644 --- a/include/conio.c +++ b/include/conio.c @@ -32,6 +32,12 @@ __asm bsinit jsr 0xff81 sta 0xff01 } +__asm dswap +{ + sta 0xff00 + jsr 0xff5f + sta 0xff01 +} #pragma code(code) #elif defined(__PLUS4__) #pragma code(lowcode) @@ -94,6 +100,31 @@ __asm bsinit #define bsinit 0xff81 #endif +#if defined(__C128__) +void dispmode40col(void) +{ + if (*(volatile char *)0xd7 >= 128) + { + __asm + { + jsr dswap + } + } +} + +void dispmode80col(void) +{ + if (*(volatile char *)0xd7 < 128) + { + __asm + { + jsr dswap + } + } +} +#endif + + void iocharmap(IOCharMap chmap) { giocharmap = chmap; diff --git a/include/conio.h b/include/conio.h index 28a72b4..f1749b3 100644 --- a/include/conio.h +++ b/include/conio.h @@ -18,6 +18,10 @@ extern IOCharMap giocharmap; void iocharmap(IOCharMap chmap); +#if defined(__C128__) +void dispmode40col(void); +void dispmode80col(void); +#endif int kbhit(void); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 6c85e03..3b61f44 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -473,7 +473,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex Declaration* dec = exp->mDecValue; - dec->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_NATIVE_CODE); + dec->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_NATIVE_CODE, dec->mAlignment); uint8* d = dec->mLinkerObject->AddSpace(osize); @@ -600,7 +600,20 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex } else if (aexp->mType == DT_ARGUMENT || aexp->mType == DT_VARIABLE) { - if (refvars) + if (aexp->mFlags & DTF_GLOBAL) + { + InitGlobalVariable(mod, aexp); + + LinkerReference ref; + ref.mObject = dec->mLinkerObject; + ref.mOffset = offset; + ref.mFlags = LREF_LOWBYTE; + ref.mRefObject = aexp->mLinkerObject; + ref.mRefOffset = 0; + ref.mRefObject->mFlags |= LOBJF_RELEVANT; + dec->mLinkerObject->AddReference(ref); + } + else if (refvars) { int j = 0; while (j < refvars->Size() && (*refvars)[j] != aexp) @@ -4635,7 +4648,7 @@ void InterCodeGenerator::TranslateLogic(Declaration* procType, InterCodeProcedur InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod, Expression* exp, Declaration * dec) { - InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mQualIdent, mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_BYTE_CODE)); + 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, "main")) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 9565772..aaeef30 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -7322,7 +7322,8 @@ Expression* Parser::ParseAssembler(void) if ((ilast->mLeft->mDecValue->mType == DT_CONST_INTEGER && ilast->mLeft->mDecValue->mInteger < 256) || (ilast->mLeft->mDecValue->mType == DT_VARIABLE_REF && !(ilast->mLeft->mDecValue->mBase->mFlags & DTF_GLOBAL)) || (ilast->mLeft->mDecValue->mType == DT_VARIABLE && !(ilast->mLeft->mDecValue->mFlags & DTF_GLOBAL)) || - ilast->mLeft->mDecValue->mType == DT_ARGUMENT) + (ilast->mLeft->mDecValue->mType == DT_VARIABLE && (ilast->mLeft->mDecValue->mFlags & DTF_ZEROPAGE)) || + ilast->mLeft->mDecValue->mType == DT_ARGUMENT) { if (ilast->mAsmInsMode == ASMIM_ABSOLUTE && HasAsmInstructionMode(ilast->mAsmInsType, ASMIM_ZERO_PAGE)) ilast->mAsmInsMode = ASMIM_ZERO_PAGE; @@ -8072,6 +8073,19 @@ void Parser::ParsePragma(void) else mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer number for alignment expected"); } + else if (dec && dec->mType == DT_CONST_FUNCTION) + { + mScanner->NextToken(); + ConsumeToken(TK_COMMA); + + Expression* exp = ParseRExpression(); + if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) + { + dec->mAlignment = int(exp->mDecValue->mInteger); + } + else + mErrors->Error(mScanner->mLocation, EERR_PRAGMA_PARAMETER, "Integer number for alignment expected"); + } else { mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Variable not found"); From 1931f25475f5132347a8072565316b66b58c6f50 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 5 Aug 2023 21:52:44 +0200 Subject: [PATCH 068/169] Add struct member initializer --- oscar64/Parser.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index aaeef30..0a69b3d 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1548,7 +1548,7 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) while (bdec->mType == DT_TYPE_ARRAY) bdec = bdec->mBase; - if (bdec->mType == DT_TYPE_STRUCT && bdec->mDefaultConstructor) + if (bdec->mType == DT_TYPE_STRUCT && bdec->mDefaultConstructor || dec->mValue) { Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); qexp->mLeft = thisexp; @@ -1556,7 +1556,17 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) Expression* dexp; - if (dec->mSize == bdec->mSize) + if (dec->mValue) + { + qexp->mDecType = bdec; + + dexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + dexp->mToken = TK_ASSIGN; + dexp->mDecType = bdec; + dexp->mLeft = qexp; + dexp->mRight = dec->mValue; + } + else if (dec->mSize == bdec->mSize) { qexp->mDecType = bdec; @@ -1825,6 +1835,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis) if (bdec->mCopyAssignment) simpleAssignment = false; } + if (dec->mValue) + simpleConstructor = false; } dec = dec->mNext; } From 8161ff88a864e6788996eaeea695459720201599 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 6 Aug 2023 11:51:11 +0200 Subject: [PATCH 069/169] Fix crash on infinite macro expansion --- oscar64/Errors.cpp | 2 +- oscar64/Errors.h | 5 ++++- oscar64/Scanner.cpp | 6 ++++++ oscar64/Scanner.h | 2 ++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/oscar64/Errors.cpp b/oscar64/Errors.cpp index ff29cf5..5522e47 100644 --- a/oscar64/Errors.cpp +++ b/oscar64/Errors.cpp @@ -35,7 +35,7 @@ void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char else fprintf(stderr, "%s(%d, %d) : %s %d: %s\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg); - if (mErrorCount > 10) + if (mErrorCount > 10 || eid >= EFATAL_GENERIC) exit(20); } diff --git a/oscar64/Errors.h b/oscar64/Errors.h index dcf4a97..967cf6c 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -36,7 +36,6 @@ enum ErrorID EERR_RUNTIME_CODE, EERR_UNIMPLEMENTED, EERR_COMMAND_LINE, - EERR_OUT_OF_MEMORY, EERR_OBJECT_NOT_FOUND, EERR_SYNTAX, EERR_EXECUTION_FAILED, @@ -86,6 +85,10 @@ enum ErrorID ERRR_INVALID_NUMBER, EERR_INVALID_PREPROCESSOR, + + EFATAL_GENERIC = 4000, + EFATAL_OUT_OF_MEMORY, + EFATAL_MACRO_EXPANSION_DEPTH, }; class Errors diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 535736b..c1541d6 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -318,6 +318,7 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor) mAssemblerMode = false; mPreprocessorMode = false; mMacroExpansion = nullptr; + mMacroExpansionDepth = 0; mDefines = new MacroDict(); mDefineArguments = nullptr; @@ -817,6 +818,9 @@ void Scanner::NextToken(void) ex->mChar = mTokenChar; mMacroExpansion = ex; + mMacroExpansionDepth++; + if (mMacroExpansionDepth > 1024) + mErrors->Error(mLocation, EFATAL_MACRO_EXPANSION_DEPTH, "Maximum macro expansion depth exceeded", mTokenIdent); mLine = def->mString; mOffset = 0; NextChar(); @@ -1812,6 +1816,8 @@ bool Scanner::NextChar(void) delete mMacroExpansion; mMacroExpansion = mac; + mMacroExpansionDepth--; + return true; } else if (mPreprocessor->NextLine()) diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 51d8b0a..2c61d7d 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -259,6 +259,8 @@ protected: MacroDict* mDefinedArguments; } * mMacroExpansion; + int mMacroExpansionDepth; + MacroDict* mDefines, * mDefineArguments; Token mUngetToken; From 1407d9d94886afee06cfe7037b6e7925340be037 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 6 Aug 2023 15:21:11 +0200 Subject: [PATCH 070/169] Add function default parameters --- oscar64/Parser.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++ oscar64/Parser.h | 1 + 2 files changed, 51 insertions(+) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 0a69b3d..8688095 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -913,6 +913,11 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) adec->mSize = adec->mBase->mSize; + if ((mCompilerOptions & COPT_CPLUSPLUS) && ConsumeTokenIf(TK_ASSIGN)) + { + adec->mValue = ParseExpression(false); + } + vi += adec->mSize; if (pdec) pdec->mNext = adec; @@ -4754,6 +4759,12 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) return NOOVERLOAD; } + while (pdec && pdec->mValue) + { + dist += 1024; + pdec = pdec->mNext; + } + if (pdec) return NOOVERLOAD; @@ -4795,6 +4806,43 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) return exp; } +void Parser::CompleteFunctionDefaultParams(Expression* exp) +{ + Declaration* fdec = exp->mLeft->mDecValue; + Expression* lexp = exp; + + Declaration* pdec = fdec->mBase->mParams; + Expression* pexp = lexp->mRight; + while (pdec) + { + if (pexp) + { + if (pexp->mType == EX_LIST) + { + lexp = pexp; + pexp = pexp->mRight; + } + else + pexp = nullptr; + } + else if (pdec->mValue) + { + if (lexp->mRight) + { + Expression* nexp = new Expression(exp->mLocation, EX_LIST); + nexp->mLeft = lexp->mRight; + nexp->mRight = pdec->mValue; + lexp->mRight = nexp; + lexp = nexp; + } + else + lexp->mRight = pdec->mValue; + } + + pdec = pdec->mNext; + } +} + Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) { if (exp->mType == EX_CALL && exp->mLeft->mDecValue) @@ -4850,6 +4898,8 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) exp->mRight = pbest; } } + + CompleteFunctionDefaultParams(exp); } return exp; diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 66f153c..608a1c0 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -90,6 +90,7 @@ protected: int OverloadDistance(Declaration* pdec, Expression* pexp); Expression * ResolveOverloadCall(Expression* exp, Expression * exp2 = nullptr); Expression* CoerceExpression(Expression* exp, Declaration* type); + void CompleteFunctionDefaultParams(Expression* exp); Expression* ParseSimpleExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs); From 0d95a748136eae9a52bdba3d2746a01b35faf7d3 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 7 Aug 2023 15:50:01 +0200 Subject: [PATCH 071/169] Add cartridge bank lookup for lables in asm file --- oscar64/Disassembler.cpp | 22 ++++++++++---------- oscar64/Disassembler.h | 2 +- oscar64/InterCode.cpp | 44 ++++++++++++++++++++++++++-------------- oscar64/Linker.cpp | 18 ++++++++++++++++ oscar64/Linker.h | 1 + 5 files changed, 60 insertions(+), 27 deletions(-) diff --git a/oscar64/Disassembler.cpp b/oscar64/Disassembler.cpp index 7f76623..173fa35 100644 --- a/oscar64/Disassembler.cpp +++ b/oscar64/Disassembler.cpp @@ -718,29 +718,29 @@ void NativeCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int ba break; case ASMIM_ZERO_PAGE: addr = memory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s %s %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], TempName(addr, tbuffer, proc, linker), AddrName(addr, abuffer, proc, linker)); + fprintf(file, "%04x : %02x %02x __ %s %s %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], TempName(addr, tbuffer, proc, linker), AddrName(bank, addr, abuffer, proc, linker)); break; case ASMIM_ZERO_PAGE_X: addr = memory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s %s,x %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], TempName(addr, tbuffer, proc, linker), AddrName(addr, abuffer, proc, linker)); + fprintf(file, "%04x : %02x %02x __ %s %s,x %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], TempName(addr, tbuffer, proc, linker), AddrName(bank, addr, abuffer, proc, linker)); break; case ASMIM_ZERO_PAGE_Y: addr = memory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s %s,y %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], TempName(addr, tbuffer, proc, linker), AddrName(addr, abuffer, proc, linker)); + fprintf(file, "%04x : %02x %02x __ %s %s,y %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], TempName(addr, tbuffer, proc, linker), AddrName(bank, addr, abuffer, proc, linker)); break; case ASMIM_ABSOLUTE: addr = memory[ip] + 256 * memory[ip + 1]; - fprintf(file, "%04x : %02x %02x %02x %s $%04x %s\n", iip, memory[iip], memory[iip + 1], memory[iip + 2], AsmInstructionNames[d.mType], addr, AddrName(addr, abuffer, proc, linker)); + fprintf(file, "%04x : %02x %02x %02x %s $%04x %s\n", iip, memory[iip], memory[iip + 1], memory[iip + 2], AsmInstructionNames[d.mType], addr, AddrName(bank, addr, abuffer, proc, linker)); ip += 2; break; case ASMIM_ABSOLUTE_X: addr = memory[ip] + 256 * memory[ip + 1]; - fprintf(file, "%04x : %02x %02x %02x %s $%04x,x %s\n", iip, memory[iip], memory[iip + 1], memory[iip + 2], AsmInstructionNames[d.mType], addr, AddrName(addr, abuffer, proc, linker)); + fprintf(file, "%04x : %02x %02x %02x %s $%04x,x %s\n", iip, memory[iip], memory[iip + 1], memory[iip + 2], AsmInstructionNames[d.mType], addr, AddrName(bank, addr, abuffer, proc, linker)); ip += 2; break; case ASMIM_ABSOLUTE_Y: addr = memory[ip] + 256 * memory[ip + 1]; - fprintf(file, "%04x : %02x %02x %02x %s $%04x,y %s\n", iip, memory[iip], memory[iip + 1], memory[iip + 2], AsmInstructionNames[d.mType], addr, AddrName(addr, abuffer, proc, linker)); + fprintf(file, "%04x : %02x %02x %02x %s $%04x,y %s\n", iip, memory[iip], memory[iip + 1], memory[iip + 2], AsmInstructionNames[d.mType], addr, AddrName(bank, addr, abuffer, proc, linker)); ip += 2; break; case ASMIM_INDIRECT: @@ -750,11 +750,11 @@ void NativeCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int ba break; case ASMIM_INDIRECT_X: addr = memory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s (%s,x) %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], TempName(addr, tbuffer, proc, linker), AddrName(addr, abuffer, proc, linker)); + fprintf(file, "%04x : %02x %02x __ %s (%s,x) %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], TempName(addr, tbuffer, proc, linker), AddrName(bank, addr, abuffer, proc, linker)); break; case ASMIM_INDIRECT_Y: addr = memory[ip++]; - fprintf(file, "%04x : %02x %02x __ %s (%s),y %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], TempName(addr, tbuffer, proc, linker), AddrName(addr, abuffer, proc, linker)); + fprintf(file, "%04x : %02x %02x __ %s (%s),y %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], TempName(addr, tbuffer, proc, linker), AddrName(bank, addr, abuffer, proc, linker)); break; case ASMIM_RELATIVE: addr = memory[ip++]; @@ -762,14 +762,14 @@ void NativeCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int ba addr = addr + ip - 256; else addr = addr + ip; - fprintf(file, "%04x : %02x %02x __ %s $%04x %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], addr, AddrName(addr, abuffer, proc, linker)); + fprintf(file, "%04x : %02x %02x __ %s $%04x %s\n", iip, memory[iip], memory[iip + 1], AsmInstructionNames[d.mType], addr, AddrName(bank, addr, abuffer, proc, linker)); break; } } } -const char* NativeCodeDisassembler::AddrName(int addr, char* buffer, InterCodeProcedure* proc, Linker* linker) +const char* NativeCodeDisassembler::AddrName(int bank, int addr, char* buffer, InterCodeProcedure* proc, Linker* linker) { if (linker) { @@ -794,7 +794,7 @@ const char* NativeCodeDisassembler::AddrName(int addr, char* buffer, InterCodePr if (proc && proc->mLinkerObject && addr >= proc->mLinkerObject->mAddress && addr < proc->mLinkerObject->mAddress + proc->mLinkerObject->mSize) obj = proc->mLinkerObject; else - obj = linker->FindObjectByAddr(addr); + obj = linker->FindObjectByAddr(bank, addr); if (obj && obj->mIdent) { diff --git a/oscar64/Disassembler.h b/oscar64/Disassembler.h index 68a764e..846a25e 100644 --- a/oscar64/Disassembler.h +++ b/oscar64/Disassembler.h @@ -31,7 +31,7 @@ public: void DumpMemory(FILE* file, const uint8* memory, int bank, int start, int size, InterCodeProcedure* proc, const Ident* ident, Linker* linker, LinkerObject * lobj); protected: const char* TempName(uint8 tmp, char* buffer, InterCodeProcedure* proc, Linker* linker); - const char* AddrName(int addr, char* buffer, InterCodeProcedure* proc, Linker* linker); + const char* AddrName(int bank, int addr, char* buffer, InterCodeProcedure* proc, Linker* linker); }; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 8b0862a..31222ad 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -3170,7 +3170,7 @@ void InterInstruction::FilterStaticVarsUsage(const GrowingVariableArray& staticV } else if (mSrc[0].mMemory == IM_GLOBAL) { - if (!providedVars[mSrc[0].mVarIndex]) + if (mSrc[0].mVarIndex >= 0 && !providedVars[mSrc[0].mVarIndex]) requiredVars += mSrc[0].mVarIndex; } } @@ -3186,10 +3186,13 @@ void InterInstruction::FilterStaticVarsUsage(const GrowingVariableArray& staticV } else if (mSrc[1].mMemory == IM_GLOBAL) { - if (mSrc[1].mIntConst == 0 && mSrc[1].mOperandSize == staticVars[mSrc[1].mVarIndex]->mSize) - providedVars += mSrc[1].mVarIndex; - else if (!providedVars[mSrc[1].mVarIndex]) - requiredVars += mSrc[1].mVarIndex; + if (mSrc[1].mVarIndex >= 0) + { + if (mSrc[1].mIntConst == 0 && mSrc[1].mOperandSize == staticVars[mSrc[1].mVarIndex]->mSize) + providedVars += mSrc[1].mVarIndex; + else if (!providedVars[mSrc[1].mVarIndex]) + requiredVars += mSrc[1].mVarIndex; + } } } else if (mCode == IC_COPY || mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE || mCode == IC_STRCPY || mCode == IC_DISPATCH) @@ -3696,7 +3699,8 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(InterCodeBasicBlock* } else if (mSrc[0].mMemory == IM_GLOBAL) { - requiredVars += mSrc[0].mVarIndex; + if (mSrc[0].mVarIndex >= 0) + requiredVars += mSrc[0].mVarIndex; } int k = 0; @@ -3709,7 +3713,7 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(InterCodeBasicBlock* } else if (mCode == IC_STORE) { - if (mSrc[1].mMemory == IM_GLOBAL) + if (mSrc[1].mMemory == IM_GLOBAL && mSrc[1].mVarIndex >= 0) { if (requiredVars[mSrc[1].mVarIndex]) { @@ -17973,10 +17977,15 @@ bool InterCodeProcedure::ReferencesGlobal(int varindex) { if (mGlobalsChecked) { - if (mModule->mGlobalVars[varindex]->mAliased) - return mLoadsIndirect || mStoresIndirect; - else if (varindex < mReferencedGlobals.Size()) - return mReferencedGlobals[varindex]; + if (varindex >= 0) + { + if (mModule->mGlobalVars[varindex]->mAliased) + return mLoadsIndirect || mStoresIndirect; + else if (varindex < mReferencedGlobals.Size()) + return mReferencedGlobals[varindex]; + else + return false; + } else return false; } @@ -17988,10 +17997,15 @@ bool InterCodeProcedure::ModifiesGlobal(int varindex) { if (mGlobalsChecked) { - if (mModule->mGlobalVars[varindex]->mAliased) - return mStoresIndirect; - else if (varindex < mModifiedGlobals.Size()) - return mModifiedGlobals[varindex]; + if (varindex >= 0) + { + if (mModule->mGlobalVars[varindex]->mAliased) + return mStoresIndirect; + else if (varindex < mModifiedGlobals.Size()) + return mModifiedGlobals[varindex]; + else + return false; + } else return false; } diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index 84eead1..8713b36 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -241,6 +241,24 @@ LinkerObject* Linker::FindObjectByAddr(int addr) return nullptr; } +LinkerObject* Linker::FindObjectByAddr(int bank, int addr) +{ + for (int i = 0; i < mObjects.Size(); i++) + { + LinkerObject* lobj = mObjects[i]; + if (lobj->mFlags & LOBJF_PLACED) + { + if (lobj->mRegion && ((1ULL << bank) & lobj->mRegion->mCartridgeBanks)) + { + if (addr >= lobj->mAddress && addr < lobj->mAddress + lobj->mSize) + return lobj; + } + } + } + + return FindObjectByAddr(addr); +} + LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, LinkerSection * section, LinkerObjectType type, int alignment) { LinkerObject* obj = new LinkerObject; diff --git a/oscar64/Linker.h b/oscar64/Linker.h index ff9affa..a230e3f 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -237,6 +237,7 @@ public: LinkerRegion* FindRegionOfSection(LinkerSection* section); LinkerObject* FindObjectByAddr(int addr); + LinkerObject* FindObjectByAddr(int bank, int addr); bool IsSectionPlaced(LinkerSection* section); From 0f31a4e8c6c6eacbad84e6a7fbef686a6a99cb4e Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 7 Aug 2023 16:06:34 +0200 Subject: [PATCH 072/169] Add error for overlapping data sections --- oscar64/Errors.h | 1 + oscar64/Linker.cpp | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 967cf6c..1813cfc 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -83,6 +83,7 @@ enum ErrorID ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, + EERR_OVERLAPPING_DATA_SECTIONS, EERR_INVALID_PREPROCESSOR, diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index 8713b36..f5f1e94 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -612,6 +612,29 @@ void Linker::Link(void) } } } + + for (int i = 0; i < mObjects.Size(); i++) + { + LinkerObject* oi = mObjects[i]; + + if (oi->mSection->mType == LST_DATA && (oi->mFlags & LOBJF_PLACED) && oi->mRegion) + { + for (int j = i + 1; j < mObjects.Size(); j++) + { + LinkerObject* oj = mObjects[j]; + + if (oj->mSection->mType == LST_DATA && (oj->mFlags & LOBJF_PLACED) && oj->mRegion) + { + if (oj->mAddress < oi->mAddress + oi->mSize && oi->mAddress < oj->mAddress + oj->mSize && (oj->mRegion->mCartridgeBanks & oi->mRegion->mCartridgeBanks)) + { + mErrors->Error(oi->mLocation, EERR_OVERLAPPING_DATA_SECTIONS, "Overlapping data section", oi->mIdent); + mErrors->Error(oj->mLocation, EERR_OVERLAPPING_DATA_SECTIONS, "Overlapping data section", oj->mIdent); + } + } + } + } + } + } } From c46870ec1011d3b491d6560c1d262b8115c1cdd6 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 7 Aug 2023 17:50:17 +0200 Subject: [PATCH 073/169] bump version number --- README.md | 1 + oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 6 +++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b3f41e7..a020a79 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ Supported Features: * new, delete, new[] and delete[] * virtual member functions * string and iostream classes +* default parameters for class members and functions ## Installation and Usage diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index ace2e49..c006cc7 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.23.214"); + strcpy(strProductVersion, "1.23.215"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 9520ced..bc8b980 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,23,214,0 - PRODUCTVERSION 1,23,214,0 + FILEVERSION 1,23,215,0 + PRODUCTVERSION 1,23,215,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.23.214.0" + VALUE "FileVersion", "1.23.215.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.23.214.0" + VALUE "ProductVersion", "1.23.215.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 154e0c6..963e16f 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5504,15 +5504,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{39A4B196-6F41-483E-B0B5-95BC052CADFE}" - "PackageCode" = "8:{1726C6F5-01F2-4105-BF06-3712F9EFA860}" + "ProductCode" = "8:{98D62EE4-5445-436D-BF7B-4353AD7BFEA3}" + "PackageCode" = "8:{90AEC745-AEF0-410C-9324-C5E13121720B}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.23.214" + "ProductVersion" = "8:1.23.215" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From b7630450f17a05ba678355ef82c00ee3597c4bc5 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 8 Aug 2023 14:19:08 +0200 Subject: [PATCH 074/169] Improve C++ compliance --- oscar64/Declaration.h | 2 + oscar64/Emulator.cpp | 6 + oscar64/Errors.h | 1 + oscar64/InterCode.cpp | 16 ++- oscar64/InterCodeGenerator.cpp | 3 + oscar64/Parser.cpp | 252 +++++++++++++++++++++++++++++++-- oscar64/Parser.h | 3 + oscar64/Scanner.cpp | 65 +++++++++ oscar64/Scanner.h | 27 +++- 9 files changed, 358 insertions(+), 17 deletions(-) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 89075ca..2788596 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -51,6 +51,8 @@ enum DecType DT_NAMESPACE, DT_BASECLASS, + DT_TEMPLATE, + DT_VTABLE }; diff --git a/oscar64/Emulator.cpp b/oscar64/Emulator.cpp index c7f1bdf..7bc4421 100644 --- a/oscar64/Emulator.cpp +++ b/oscar64/Emulator.cpp @@ -545,6 +545,12 @@ int Emulator::Emulate(int startIP, int trace) mIP = mMemory[0x101 + mRegS] + 256 * mMemory[0x102 + mRegS] + 1; mRegS += 2; } + else if (mIP == 0xff81) + { + printf("------------------ CLEAR ---------------\n"); + mIP = mMemory[0x101 + mRegS] + 256 * mMemory[0x102 + mRegS] + 1; + mRegS += 2; + } uint8 opcode = mMemory[mIP]; AsmInsData d = DecInsData[opcode]; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 1813cfc..157de78 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -80,6 +80,7 @@ enum ErrorID EERR_INVALID_OPERATOR, EERR_MISSING_TEMP, EERR_NON_STATIC_MEMBER, + EERR_TEMPLATE_PARAMS, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 31222ad..06b6ed9 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -13420,6 +13420,18 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa sins->mSrc[0].mFinal = false; assert(nins->mSrc[0].mTemp >= 0); + // Propagate all loads to move temps + + for (int t = j + 1; t < mInstructions.Size(); t++) + { + InterInstruction* ti = mInstructions[t]; + if (ti->mCode == IC_LOAD && SameMem(ti->mSrc[0], ins->mSrc[0])) + { + ti->mCode = IC_LOAD_TEMPORARY; + ti->mSrc[0].mTemp = ins->mDst.mTemp; + } + } + // Move store behind loop tailBlock->mInstructions.Insert(0, sins); mInstructions.Remove(j); @@ -16724,7 +16736,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "playSong"); + CheckFunc = !strcmp(mIdent->mString, "MenuItem::+MenuItem"); mEntryBlock = mBlocks[0]; @@ -16899,6 +16911,8 @@ void InterCodeProcedure::Close(void) TempForwarding(); RemoveUnusedInstructions(); + DisassembleDebug("pre single block loop opt"); + ResetVisited(); mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet, mModule->mGlobalVars); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 3b61f44..7663feb 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -4111,6 +4111,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = Dereference(proc, exp, block, vr); return CoerceType(proc, exp, block, vr, exp->mDecType); } + else if (exp->mDecType->mType == DT_TYPE_VOID) + { + } else { vr = Dereference(proc, exp, block, vr); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 8688095..e424e98 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -284,6 +284,15 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (dec->mScope->Insert(mdec->mIdent, mdec)) mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + if (dec->mConst) + { + Declaration* cmdec = mdec->Clone(); + cmdec->mBase = mdec->mBase->ToConstType(); + + dec->mConst->mScope->Insert(cmdec->mIdent, cmdec); + dec->mConst->mSize = dec->mSize; + } + if (mlast) mlast->mNext = mdec; else @@ -442,6 +451,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) { Declaration* dec = nullptr; + const Ident* pident = nullptr; switch (mScanner->mToken) { @@ -551,6 +561,7 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) break; case TK_IDENT: + pident = mScanner->mTokenIdent; dec = mScope->Lookup(mScanner->mTokenIdent); if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS) dec = mScope->mParent->Lookup(mScanner->mTokenIdent); @@ -560,6 +571,7 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) { if (ExpectToken(TK_IDENT)) { + pident = mScanner->mTokenIdent; dec = dec->mScope->Lookup(mScanner->mTokenIdent); mScanner->NextToken(); } @@ -594,15 +606,9 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) } } else if (!dec) - { - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", mScanner->mTokenIdent); - mScanner->NextToken(); - } + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); else - { - mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", mScanner->mTokenIdent); - mScanner->NextToken(); - } + mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); break; case TK_ENUM: @@ -3424,6 +3430,21 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (mScanner->mToken == TK_OPEN_BRACE) { + // + // Take parameter names from new declaration + // + Declaration* npdec = ctdec->mParams, * ppdec = cdec->mBase->mParams; + while (npdec && ppdec) + { + if (npdec->mIdent) + { + ppdec->mIdent = npdec->mIdent; + ppdec->mQualIdent = npdec->mQualIdent; + } + npdec = npdec->mNext; + ppdec = ppdec->mNext; + } + if (cdec->mFlags & DTF_DEFINED) mErrors->Error(cdec->mLocation, EERR_DUPLICATE_DEFINITION, "Function already has a body"); @@ -4001,7 +4022,7 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) texp->mLeft = vexp; texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = pdec->mBase; + texp->mDecType->mBase = dec->mBase; texp->mDecType->mSize = 2; Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); @@ -4014,12 +4035,13 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) Expression* aexp; - if (dec->mBase->mCopyConstructor && !(dec->mValue->mType == EX_CALL && dec->mValue->mDecType->mType == DT_TYPE_STRUCT)) + Declaration* fcons = dec->mBase->mScope->Lookup(dec->mBase->mIdent->PreMangle("+")); + + if (fcons && !(dec->mValue->mType == EX_CALL && dec->mValue->mDecType->mType == DT_TYPE_STRUCT)) { - Declaration* mdec = dec->mBase->mCopyConstructor; Expression* cexp = new Expression(dec->mLocation, EX_CONSTANT); - cexp->mDecValue = mdec; + cexp->mDecValue = fcons; cexp->mDecType = cexp->mDecValue->mBase; aexp = new Expression(mScanner->mLocation, EX_CALL); @@ -4027,6 +4049,8 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) aexp->mRight = new Expression(dec->mLocation, EX_LIST); aexp->mRight->mLeft = texp; aexp->mRight->mRight = dec->mValue; + + ResolveOverloadCall(aexp); } else { @@ -4710,6 +4734,8 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) dist += 4; else if (ptype->IsSame(ex->mDecType)) ; + else if (CanCoerceExpression(ex, ptype)) + dist += 512; else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_TYPE_STRUCT && etype->mType == DT_TYPE_STRUCT) { int ncast = 0; @@ -4771,12 +4797,52 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) return dist; } +bool Parser::CanCoerceExpression(Expression* exp, Declaration* type) +{ + Declaration* tdec = exp->mDecType; + while (tdec->mType == DT_TYPE_REFERENCE) + tdec = tdec->mBase; + while (type->mType == DT_TYPE_REFERENCE) + type = type->mBase; + + if (tdec->mType == DT_TYPE_STRUCT) + { + Declaration* fexp = tdec->mScope->Lookup(Ident::Unique("(cast)")); + if (fexp) + { + while (fexp && !fexp->mBase->mBase->IsSame(type)) + fexp = fexp->mNext; + if (fexp) + return true; + } + } + + if (type->mType == DT_TYPE_STRUCT) + { + if (!type->IsConstSame(tdec)) + { + Declaration* fcons = type->mScope->Lookup(type->mIdent->PreMangle("+")); + if (fcons) + { + while (fcons && !(fcons->mBase->mParams && fcons->mBase->mParams->mNext && !fcons->mBase->mParams->mNext->mNext && fcons->mBase->mParams->mNext->mBase->CanAssign(tdec))) + fcons = fcons->mNext; + + if (fcons) + return true; + } + } + } + + return false; +} + Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) { Declaration* tdec = exp->mDecType; while (tdec->mType == DT_TYPE_REFERENCE) tdec = tdec->mBase; - + while (type->mType == DT_TYPE_REFERENCE) + type = type->mBase; if (tdec->mType == DT_TYPE_STRUCT) { @@ -4802,6 +4868,78 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) } } } + + if (type->mType == DT_TYPE_STRUCT) + { + if (!type->IsConstSame(tdec)) + { + Declaration* fcons = type->mScope->Lookup(type->mIdent->PreMangle("+")); + if (fcons) + { + while (fcons && !(fcons->mBase->mParams && fcons->mBase->mParams->mNext && !fcons->mBase->mParams->mNext->mNext && fcons->mBase->mParams->mNext->mBase->CanAssign(tdec))) + fcons = fcons->mNext; + + if (fcons) + { + Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + + vdec->mBase = type->ToMutableType(); + vdec->mVarIndex = mLocalIndex++; + vdec->mSize = type->mSize; + vdec->mFlags |= DTF_DEFINED; + + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = vdec->mBase; + vexp->mDecValue = vdec; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = fcons; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + + fexp->mRight = exp; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = vdec->mBase; + texp->mDecType->mSize = 2; + + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = fexp->mRight; + fexp->mRight = lexp; + + Expression* dexp = nullptr; + if (type->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = type->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + return nexp; + } + } + } + } return exp; } @@ -4817,13 +4955,19 @@ void Parser::CompleteFunctionDefaultParams(Expression* exp) { if (pexp) { + Expression* exp = pexp; + if (pexp->mType == EX_LIST) { + pexp->mLeft = CoerceExpression(pexp->mLeft, pdec->mBase); lexp = pexp; pexp = pexp->mRight; } else + { + lexp->mRight = CoerceExpression(lexp->mRight, pdec->mBase); pexp = nullptr; + } } else if (pdec->mValue) { @@ -4887,9 +5031,14 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) } if (ibest == NOOVERLOAD) - mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call"); + { +#if _DEBUG + int d = OverloadDistance(exp->mLeft->mDecValue->mBase, exp->mRight); +#endif + mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call", exp->mLeft->mDecValue->mQualIdent); + } else if (nbest > 1) - mErrors->Error(exp->mLocation, ERRO_AMBIGUOUS_FUNCTION_CALL, "Ambiguous function call"); + mErrors->Error(exp->mLocation, ERRO_AMBIGUOUS_FUNCTION_CALL, "Ambiguous function call", exp->mLeft->mDecValue->mQualIdent); else { exp->mLeft->mDecValue = dbest; @@ -6831,6 +6980,69 @@ Expression* Parser::ParseSwitchStatement(void) return sexp; } +void Parser::ParseTemplate(void) +{ + ConsumeToken(TK_LESS_THAN); + Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); + Declaration* ppdec = nullptr; + + for (;;) + { + Declaration* pdec = nullptr; + + if (ConsumeTokenIf(TK_CLASS)) + { + if (mScanner->mToken == TK_IDENT) + { + Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + pdec->mIdent = mScanner->mTokenIdent; + pdec->mBase = TheVoidTypeDeclaration; + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + } + else if (ConsumeTokenIf(TK_INT)) + { + if (mScanner->mToken == TK_IDENT) + { + Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + pdec->mIdent = mScanner->mTokenIdent; + pdec->mBase = TheSignedIntTypeDeclaration; + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + } + else + mErrors->Error(mScanner->mLocation, EERR_TEMPLATE_PARAMS, "'class' or 'int' expected as template parameter"); + + if (pdec) + { + if (ppdec) + ppdec->mNext = pdec; + else + tdec->mParams = pdec; + ppdec = pdec; + } + + if (!ConsumeTokenIf(TK_COMMA)) + break; + } + + ConsumeToken(TK_GREATER_THAN); + + if (mScanner->mToken == TK_CLASS) + { + // Class template + + } + else + { + // Function template + + } +} Expression* Parser::ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset) @@ -7541,6 +7753,11 @@ void Parser::ParsePragma(void) } ConsumeToken(TK_CLOSE_PARENTHESIS); } + else if (!strcmp(mScanner->mTokenIdent->mString, "once")) + { + mScanner->MarkSourceOnce(); + mScanner->NextToken(); + } else if (!strcmp(mScanner->mTokenIdent->mString, "compile")) { mScanner->NextToken(); @@ -8453,6 +8670,11 @@ void Parser::Parse(void) } else if (mScanner->mToken == TK_SEMICOLON) mScanner->NextToken(); + else if (mScanner->mToken == TK_TEMPLATE) + { + mScanner->NextToken(); + ParseTemplate(); + } else if (mScanner->mToken == TK_NAMESPACE) { mScanner->NextToken(); diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 608a1c0..81fa74b 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -90,8 +90,11 @@ protected: int OverloadDistance(Declaration* pdec, Expression* pexp); Expression * ResolveOverloadCall(Expression* exp, Expression * exp2 = nullptr); Expression* CoerceExpression(Expression* exp, Declaration* type); + bool CanCoerceExpression(Expression* exp, Declaration* type); void CompleteFunctionDefaultParams(Expression* exp); + void ParseTemplate(void); + Expression* ParseSimpleExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs); Expression* ParsePostfixExpression(bool lhs); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index c1541d6..07f60f4 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -162,6 +162,7 @@ const char* TokenNames[] = "'delete'", "'virtual'", "'operator'", + "'template'", }; @@ -306,6 +307,25 @@ Macro* MacroDict::Lookup(const Ident* ident) } +TokenSequence::TokenSequence(Scanner* scanner) + : mNext(nullptr), mLocation(scanner->mLocation), mToken(scanner->mToken), + mTokenIdent(scanner->mTokenIdent), mTokenChar(scanner->mTokenChar), + mTokenInteger(scanner->mTokenInteger), mTokenNumber(scanner->mTokenNumber), + mTokenString(nullptr) +{ + if (mToken == TK_STRING) + { + int ssize = strlen(scanner->mTokenString); + char * str = new char[ssize + 1]; + strcpy_s(str, ssize + 1, scanner->mTokenString); + mTokenString = str; + } +} + +TokenSequence::~TokenSequence(void) +{ + delete[] mTokenString; +} Scanner::Scanner(Errors* errors, Preprocessor* preprocessor) : mErrors(errors), mPreprocessor(preprocessor) @@ -324,6 +344,9 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor) mDefineArguments = nullptr; mToken = TK_NONE; mUngetToken = TK_NONE; + mReplay = nullptr; + + mOnceDict = new MacroDict(); NextChar(); @@ -336,6 +359,18 @@ Scanner::~Scanner(void) } +TokenSequence* Scanner::Record(void) +{ + return new TokenSequence(this); +} + +const TokenSequence* Scanner::Replay(const TokenSequence* replay) +{ + const TokenSequence* seq = mReplay; + mReplay = replay; + return seq; +} + const char* Scanner::TokenName(Token token) const { return TokenNames[token]; @@ -412,8 +447,32 @@ void Scanner::AddMacro(const Ident* ident, const char* value) mDefines->Insert(macro); } +void Scanner::MarkSourceOnce(void) +{ + const Ident* fident = Ident::Unique(mPreprocessor->mSource->mFileName); + + Macro* macro = new Macro(fident, nullptr); + mOnceDict->Insert(macro); +} + void Scanner::NextToken(void) { + if (mReplay) + { + mLocation = mReplay->mLocation; + mToken = mReplay->mToken; + + mTokenIdent = mReplay->mTokenIdent; + mTokenChar = mReplay->mTokenChar; + mTokenNumber = mReplay->mTokenNumber; + mTokenInteger = mReplay->mTokenInteger; + if (mReplay->mTokenString) + strcpy_s(mTokenString, mReplay->mTokenString); + + mReplay = mReplay->mNext; + return; + } + for (;;) { NextRawToken(); @@ -503,6 +562,8 @@ void Scanner::NextToken(void) { if (!mPreprocessor->OpenSource("Including", mTokenString, true)) mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Could not open source file", mTokenString); + else if (mOnceDict->Lookup(Ident::Unique(mPreprocessor->mSource->mFileName))) + mPreprocessor->CloseSource(); } else if (mToken == TK_LESS_THAN) { @@ -510,6 +571,8 @@ void Scanner::NextToken(void) StringToken('>', 'a'); if (!mPreprocessor->OpenSource("Including", mTokenString, false)) mErrors->Error(mLocation, EERR_FILE_NOT_FOUND, "Could not open source file", mTokenString); + else if (mOnceDict->Lookup(Ident::Unique(mPreprocessor->mSource->mFileName))) + mPreprocessor->CloseSource(); } } else if (mToken == TK_PREP_DEFINE) @@ -1426,6 +1489,8 @@ void Scanner::NextRawToken(void) mToken = TK_DELETE; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "virtual")) mToken = TK_VIRTUAL; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "template")) + mToken = TK_TEMPLATE; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 2c61d7d..3d1691f 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -161,6 +161,7 @@ enum Token TK_DELETE, TK_VIRTUAL, TK_OPERATOR, + TK_TEMPLATE, NUM_TOKENS }; @@ -204,6 +205,24 @@ protected: MacroDict * mParent; }; +class Scanner; + +struct TokenSequence +{ + TokenSequence * mNext; + Location mLocation; + Token mToken; + + const Ident * mTokenIdent; + char mTokenChar; + const char * mTokenString; + double mTokenNumber; + int64 mTokenInteger; + + TokenSequence(Scanner* scanner); + ~TokenSequence(void); +}; + class Scanner { public: @@ -214,6 +233,9 @@ public: void NextToken(void); + TokenSequence* Record(void); + const TokenSequence* Replay(const TokenSequence * sequence); + void Warning(const char * error); void Error(const char * error); @@ -247,6 +269,7 @@ public: uint64 mCompilerOptions; void AddMacro(const Ident* ident, const char* value); + void MarkSourceOnce(void); protected: void NextRawToken(void); @@ -261,10 +284,12 @@ protected: int mMacroExpansionDepth; - MacroDict* mDefines, * mDefineArguments; + MacroDict* mDefines, * mDefineArguments, * mOnceDict; Token mUngetToken; + const TokenSequence* mReplay; + void StringToken(char terminator, char mode); void CharToken(char mode); bool NextChar(void); From 07969d1fa66c0426bb38d025cb2a71234fc71f62 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 8 Aug 2023 17:33:47 +0200 Subject: [PATCH 075/169] Fix type coercion from empty string pointer to 0 --- include/opp/string.cpp | 86 ++++++++++++++++++++-------------- oscar64/InterCode.cpp | 2 +- oscar64/InterCodeGenerator.cpp | 5 ++ 3 files changed, 58 insertions(+), 35 deletions(-) diff --git a/include/opp/string.cpp b/include/opp/string.cpp index 4973fda..1b86951 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -33,12 +33,17 @@ string::string(const string & s) string::string(const char * s) { - char l = sstrlen(s); - if (l) - { - cstr = malloc(char(l + 2)); - cstr[0] = l; - smemcpy(cstr + 1, s, l + 1); + if (s) + { + char l = sstrlen(s); + if (l) + { + cstr = malloc(char(l + 2)); + cstr[0] = l; + smemcpy(cstr + 1, s, l + 1); + } + else + cstr = nullptr; } else cstr = nullptr; @@ -102,12 +107,17 @@ string & string::operator=(const string & s) string & string::operator=(const char * s) { free(cstr); - char l = sstrlen(s); - if (l) + if (s) { - cstr = malloc(char(l + 2)); - cstr[0] = l; - smemcpy(cstr + 1, s, l + 1); + char l = sstrlen(s); + if (l) + { + cstr = malloc(char(l + 2)); + cstr[0] = l; + smemcpy(cstr + 1, s, l + 1); + } + else + cstr = nullptr; } else cstr = nullptr; @@ -141,24 +151,27 @@ string & string::operator+=(const string & s) string & string::operator+=(const char * s) { - char sl = sstrlen(s); - if (sl) + if (s) { - if (cstr) + char sl = sstrlen(s); + if (sl) { - char l = sl + cstr[0]; - char * c = malloc(char(l + 2)); - c[0] = l; - smemcpy(c + 1, cstr + 1, cstr[0]); - smemcpy(c + 1 + cstr[0], s, sl + 1); - free(cstr); - cstr = c; - } - else - { - cstr = malloc(char(sl + 2)); - cstr[0] = sl; - smemcpy(cstr + 1, s, sl + 1); + if (cstr) + { + char l = sl + cstr[0]; + char * c = malloc(char(l + 2)); + c[0] = l; + smemcpy(c + 1, cstr + 1, cstr[0]); + smemcpy(c + 1 + cstr[0], s, sl + 1); + free(cstr); + cstr = c; + } + else + { + cstr = malloc(char(sl + 2)); + cstr[0] = sl; + smemcpy(cstr + 1, s, sl + 1); + } } } return *this; @@ -226,14 +239,19 @@ string string::operator+(const char * s) const { if (cstr) { - char sl = sstrlen(s); - if (sl) + if (s) { - char l = cstr[0] + sl; - char * p = malloc(char(l + 2)); - smemcpy(p + 1, cstr + 1, cstr[0]); - smemcpy(p + 1 + cstr[0], s, sl); - return string(l, p); + char sl = sstrlen(s); + if (sl) + { + char l = cstr[0] + sl; + char * p = malloc(char(l + 2)); + smemcpy(p + 1, cstr + 1, cstr[0]); + smemcpy(p + 1 + cstr[0], s, sl); + return string(l, p); + } + else + return *this; } else return *this; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 06b6ed9..df97f20 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16736,7 +16736,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "MenuItem::+MenuItem"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 7663feb..0612f0e 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -150,6 +150,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p v.mTemp = cins->mDst.mTemp; v.mType = type; } + else if (type->mType == DT_TYPE_POINTER && v.mType->mType == DT_TYPE_ARRAY) + { + v.mType = type; + return v; + } else if (v.mType->mSize < type->mSize) { if (v.mType->mSize == 1 && type->mSize == 2) From fef6bc29bc7a20ea3e74432277d5efbf5a2df407 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 11 Aug 2023 07:41:27 +0200 Subject: [PATCH 076/169] Add templates --- autotest/autotest.bat | 9 + autotest/opp_array.cpp | 23 ++ autotest/opp_vector.cpp | 27 +++ autotest/opp_vector_string.cpp | 35 +++ include/opp/array.h | 127 +++++++++++ include/opp/string.cpp | 27 +-- include/opp/vector.h | 175 ++++++++++++++ oscar64/CompilationUnits.cpp | 1 + oscar64/CompilationUnits.h | 2 +- oscar64/Compiler.cpp | 4 + oscar64/Compiler.h | 1 + oscar64/Declaration.cpp | 109 ++++++++- oscar64/Declaration.h | 12 +- oscar64/Errors.h | 1 + oscar64/InterCode.cpp | 16 +- oscar64/InterCodeGenerator.cpp | 11 +- oscar64/NativeCodeGenerator.cpp | 110 ++++++++- oscar64/NativeCodeGenerator.h | 1 + oscar64/Parser.cpp | 389 ++++++++++++++++++++++++++++---- oscar64/Parser.h | 8 +- oscar64/Scanner.cpp | 30 ++- oscar64/Scanner.h | 7 +- 22 files changed, 1041 insertions(+), 84 deletions(-) create mode 100644 autotest/opp_array.cpp create mode 100644 autotest/opp_vector.cpp create mode 100644 autotest/opp_vector_string.cpp create mode 100644 include/opp/array.h create mode 100644 include/opp/vector.h diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 38ae467..9d5a926 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -3,6 +3,15 @@ rem @echo off @call :test opp_string.cpp @if %errorlevel% neq 0 goto :error +@call :test opp_array.cpp +@if %errorlevel% neq 0 goto :error + +@call :test opp_vector.cpp +@if %errorlevel% neq 0 goto :error + +@call :test opp_vector_string.cpp +@if %errorlevel% neq 0 goto :error + @call :test opp_streamtest.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/opp_array.cpp b/autotest/opp_array.cpp new file mode 100644 index 0000000..cf105c0 --- /dev/null +++ b/autotest/opp_array.cpp @@ -0,0 +1,23 @@ +#include +#include + +int main(void) +{ + array a10; + array a20; + + for(int i=0; i<10; i++) + a10[i] = i; + for(int i=0; i<20; i++) + a20[i] = i; + + int s = 0; + for(int i=0; i<10; i++) + s += a10[i]; + for(int i=10; i<20; i++) + s -= a20[i]; + + assert(s == -100); + + return 0; +} diff --git a/autotest/opp_vector.cpp b/autotest/opp_vector.cpp new file mode 100644 index 0000000..91ecca3 --- /dev/null +++ b/autotest/opp_vector.cpp @@ -0,0 +1,27 @@ +#include +#include + +int main(void) +{ + vector a; + + for(int i=0; i<10; i++) + a.push_back(i); + + int s = 0; + for(int i=0; i +#include +#include +#include +#include + +string join(const vector & vs) +{ + string sj; + for(int i=0; i vs; + string a; + + for(int i=0; i<10; i++) + { + vs.push_back(a); + a += "x"; + } + + int s = 0; + for(int i=0; i<10; i++) + s += vs[i].size(); + + assert(s == 45); + + assert(join(vs).size() == 45); + + return 0; +} diff --git a/include/opp/array.h b/include/opp/array.h new file mode 100644 index 0000000..0956811 --- /dev/null +++ b/include/opp/array.h @@ -0,0 +1,127 @@ +#ifndef OPP_ARRAY_H +#define OPP_ARRAY_H + + +template +class array +{ +protected: + T _data[n]; +public: + int size(void) const + { + return n; + } + + int max_size(void) const + { + return n; + } + + bool empty(void) const + { + return n == 0; + } + + const T & at(int at) const + { + return _data[at]; + } + + T & at(int at) + { + return _data[at]; + } + + T & operator[] (int at) + { + return _data[at]; + } + + const T & operator[] (int at) const + { + return _data[at]; + } + + T * begin(void) + { + return _data; + } + + const T * begin(void) const + { + return _data; + } + + const T * cbegin(void) const + { + return _data; + } + + T * end(void) + { + return _data + n; + } + + const T * end(void) const + { + return _data + n; + } + + const T * cend(void) const + { + return _data + n; + } + + T & back(void) + { + return _data[n - 1]; + } + + const T & back(void) const + { + return _data[n - 1]; + } + + T & front(void) + { + return _data[0]; + } + + const T & front(void) const + { + return _data[0]; + } + + T * data(void) + { + return _data; + } + + const T * data(void) const + { + return _data; + } + + void fill(const T & t) + { + for(int i=0; i & a) + { + for(int i=0; i +class vector +{ +protected: + T * _data; + int _size, _capacity; +public: + vector(void) : _data(nullptr), _size(0), _capacity(0) {} + vector(int n) : _data(new T[n]), _size(n), _capacity(n) {} + ~vector(void) + { + delete[] _data; + } + + int size(void) const + { + return _size; + } + + int max_size(void) const + { + return 32767; + } + + bool empty(void) const + { + return _size == 0; + } + + int capacity(void) const + { + return _capacity; + } + + void resize(int n); + + void reserve(int n); + + void shrink_to_fit(void); + + T & at(int at) + { + return _data[at]; + } + + const T & at(int at) const + { + return _data[at]; + } + + T & operator[](int at) + { + return _data[at]; + } + + const T & operator[](int at) const + { + return _data[at]; + } + + T & front(void) + { + return _data[0]; + } + + const T & front(void) const + { + return _data[0]; + } + + T & back(void) + { + return _data[_size - 1]; + } + + const T & back(void) const + { + return _data[_size - 1]; + } + + T * data(void) + { + return _data; + } + + const T * at(void) const + { + return _data; + } + + void push_back(const T & t); + + void pop_back(void) + { + _size--; + } + + void insert(int at, const T & t); + + void erase(int at, int n = 1); +}; + + +template +void vector::reserve(int n) +{ + if (n > _capacity) + { + _capacity = n; + T * d = new T[_capacity]; + for(int i=0; i<_size; i++) + d[i] = _data[i]; + delete[] _data; + _data = d; + } +} + +template +void vector::resize(int n) +{ + if (n < _size) + _size = n; + else if (n < _capacity) + _size = n; + else + { + reserve(n); + _size = n; + } +} + +template +void vector::shrink_to_fit(void) +{ + if (_size < _capacity) + { + _capacity = _size; + T * d = new T[_capacity]; + for(int i=0; i<_size; i++) + d[i] = _data[i]; + delete[] _data; + _data = d; + } +} + +template +void vector::push_back(const T & t) +{ + if (_size == _capacity) + reserve(_size + 1 + (_size >> 1)); + _data[_size++] = t; +} + +template +void vector::insert(int at, const T & t) +{ + if (_size == _capacity) + reserve(_size + 1 + (_size >> 1)); + for(int i=_size; i>at; i--) + _data[i] = _data[i - 1]; + _data[at] = t; +} + +template +void vector::erase(int at, int n) +{ + _size -= n; + for(int i=at; i<_size; i++) + _data[i] = _data[i + n]; +} + +#endif diff --git a/oscar64/CompilationUnits.cpp b/oscar64/CompilationUnits.cpp index 948964b..9db05f7 100644 --- a/oscar64/CompilationUnits.cpp +++ b/oscar64/CompilationUnits.cpp @@ -15,6 +15,7 @@ CompilationUnits::CompilationUnits(Errors * errors) mScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); mRuntimeScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); mVTableScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); + mTemplateScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); mStartup = nullptr; for (int i = 0; i < 256; i++) diff --git a/oscar64/CompilationUnits.h b/oscar64/CompilationUnits.h index a68acbb..47d829d 100644 --- a/oscar64/CompilationUnits.h +++ b/oscar64/CompilationUnits.h @@ -19,7 +19,7 @@ public: CompilationUnits(Errors * errors); ~CompilationUnits(void); - DeclarationScope* mScope, * mVTableScope; + DeclarationScope* mScope, * mVTableScope, * mTemplateScope; CompilationUnit* mCompilationUnits, * mPendingUnits; Declaration* mStartup; diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 06b66e2..08e9b58 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -240,6 +240,10 @@ static void FillVTableTree(Declaration* vdec) cvdec = cvdec->mNext; } } +void Compiler::CompleteTemplateExpansion(void) +{ +} + void Compiler::BuildVTables(void) { // Connect vdecs with parents diff --git a/oscar64/Compiler.h b/oscar64/Compiler.h index b14571f..67964b7 100644 --- a/oscar64/Compiler.h +++ b/oscar64/Compiler.h @@ -52,6 +52,7 @@ public: void CompileProcedure(InterCodeProcedure* proc); void BuildVTables(void); + void CompleteTemplateExpansion(void); bool WriteDbjFile(const char* filename); }; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 5617724..a075e27 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -800,7 +800,7 @@ Declaration::Declaration(const Location& loc, DecType type) mVTable(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), - mCompilerOptions(0), mUseCount(0) + mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr) {} Declaration::~Declaration(void) @@ -811,7 +811,12 @@ Declaration::~Declaration(void) int Declaration::Stride(void) const { - return mStride > 0 ? mStride : mBase->mSize; + if (mStride > 0) + return mStride; + else if (mBase) + return mBase->mSize; + else + return 1; } Declaration* Declaration::BuildConstPointer(const Location& loc) @@ -862,6 +867,104 @@ Declaration* Declaration::Last(void) return p; } +const Ident* Declaration::MangleIdent(void) +{ + if (!mMangleIdent) + { + if (mType == DT_CONST_INTEGER) + { + char buffer[20]; + sprintf_s(buffer, "%d", (int)mInteger); + mMangleIdent = Ident::Unique(buffer); + } + else if (mType == DT_TYPE_INTEGER) + { + char buffer[20]; + sprintf_s(buffer, "%c%d", (mFlags & DTF_SIGNED) ? 'i' : 'u', mSize * 8); + mMangleIdent = Ident::Unique(buffer); + } + else if (mType == DT_TYPE_FLOAT) + { + mMangleIdent = Ident::Unique("float"); + } + else if (mType == DT_TYPE_REFERENCE) + { + mMangleIdent = mBase->MangleIdent()->PreMangle("&"); + } + else if (mType == DT_TYPE_POINTER) + { + mMangleIdent = mBase->MangleIdent()->PreMangle("*"); + } + else if (mType == DT_TYPE_STRUCT) + { + mMangleIdent = mQualIdent->PreMangle("struct "); + } + else if (mType == DT_TYPE_ENUM) + { + mMangleIdent = mQualIdent->PreMangle("enum "); + } + else if (mType == DT_TEMPLATE) + { + mMangleIdent = Ident::Unique("<"); + + Declaration* dec = mParams; + while (dec) + { + mMangleIdent = mMangleIdent->Mangle(dec->mBase->MangleIdent()->mString); + dec = dec->mNext; + if (dec) + mMangleIdent = mMangleIdent->Mangle(","); + } + mMangleIdent = mMangleIdent->Mangle(">"); + } + else + mMangleIdent = mQualIdent; + + if (mFlags & DTF_CONST) + mMangleIdent = mMangleIdent->PreMangle("const "); + } + + return mMangleIdent; +} + +Declaration* Declaration::TemplateExpand(Declaration* tdec) +{ + if (mType == DT_ARGUMENT) + { + Declaration* edec = this->Clone(); + edec->mBase = mBase->TemplateExpand(tdec); + if (mNext) + edec->mNext = mNext->TemplateExpand(tdec); + return edec; + } + else if (mType == DT_CONST_FUNCTION) + { + Declaration* edec = this->Clone(); + edec->mBase = mBase->TemplateExpand(tdec); + return edec; + } + else if (mType == DT_TYPE_FUNCTION) + { + Declaration* edec = this->Clone(); + edec->mBase = mBase->TemplateExpand(tdec); + if (edec->mParams) + edec->mParams = mParams->TemplateExpand(tdec); + return edec; + } + else if (mType == DT_TYPE_TEMPLATE || mType == DT_CONST_TEMPLATE) + { + return tdec->mScope->Lookup(mIdent); + } + else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY || mType == DT_TYPE_REFERENCE) + { + Declaration* edec = this->Clone(); + edec->mBase = mBase->TemplateExpand(tdec); + return edec; + } + else + return this; +} + Declaration* Declaration::Clone(void) { Declaration* ndec = new Declaration(mLocation, mType); @@ -1221,7 +1324,7 @@ bool Declaration::IsConstSame(const Declaration* dec) const bool Declaration::IsSameParams(const Declaration* dec) const { - if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION) + if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION || mType == DT_TEMPLATE && dec->mType == DT_TEMPLATE) { Declaration* ld = mParams, * rd = dec->mParams; while (ld && rd) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 2788596..07d107b 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -8,6 +8,7 @@ class LinkerObject; class LinkerSection; +class Parser; enum DecType { @@ -25,6 +26,7 @@ enum DecType DT_TYPE_FUNCTION, DT_TYPE_ASSEMBLER, DT_TYPE_AUTO, + DT_TYPE_TEMPLATE, DT_TYPE_CONST, DT_TYPE_VOLATILE, @@ -39,6 +41,7 @@ enum DecType DT_CONST_REFERENCE, DT_CONST_ASSEMBLER, DT_CONST_CONSTRUCTOR, + DT_CONST_TEMPLATE, DT_VARIABLE, DT_ARGUMENT, @@ -115,6 +118,7 @@ enum ScopeLevel SLEVEL_GLOBAL, SLEVEL_STATIC, SLEVEL_NAMESPACE, + SLEVEL_TEMPLATE, SLEVEL_CLASS, SLEVEL_FUNCTION, SLEVEL_LOCAL, @@ -254,11 +258,13 @@ public: int64 mInteger, mMinValue, mMaxValue; double mNumber; uint64 mFlags, mCompilerOptions; - const Ident * mIdent, * mQualIdent; + const Ident * mIdent, * mQualIdent, * mMangleIdent; LinkerSection * mSection; const uint8 * mData; LinkerObject * mLinkerObject; int mUseCount; + TokenSequence * mTokens; + Parser * mParser; GrowingArray mCallers, mCalled; @@ -290,6 +296,10 @@ public: Declaration* BuildConstPointer(const Location& loc); Declaration* BuildConstReference(const Location& loc); + Declaration* TemplateExpand(Declaration* tdec); + + const Ident* MangleIdent(void); + int Stride(void) const; }; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 157de78..23b5678 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -81,6 +81,7 @@ enum ErrorID EERR_MISSING_TEMP, EERR_NON_STATIC_MEMBER, EERR_TEMPLATE_PARAMS, + EERR_FUNCTION_TEMPLATE, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index df97f20..6811f5f 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -14790,7 +14790,7 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 1]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal && mInstructions[i + 1]->mSrc[0].mTemp < 0 && mInstructions[i + 0]->mDst.mIntConst >= 0 && mInstructions[i + 0]->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND && mInstructions[i + 0]->mSrc[1].mRange.mMaxValue + mInstructions[i + 0]->mSrc[0].mIntConst < 32767 && - (IsSignedRelational(mInstructions[i + 1]->mOperator) || mInstructions[i + 0]->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND && mInstructions[i + 0]->mSrc[1].mRange.mMinValue >= 0) && + (IsSignedRelational(mInstructions[i + 1]->mOperator) || mInstructions[i + 0]->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND && mInstructions[i + 0]->mSrc[1].mRange.mMinValue >= 0) && mInstructions[i + 1]->mSrc[0].mIntConst - mInstructions[i + 0]->mSrc[0].mIntConst >= (IsSignedRelational(mInstructions[i + 1]->mOperator) ? 0 : -32768) && mInstructions[i + 1]->mSrc[0].mIntConst - mInstructions[i + 0]->mSrc[0].mIntConst <= 32767) { @@ -14812,6 +14812,18 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 0]->mSrc[1].mFinal = false; changed = true; } + else if ( + mInstructions[i + 0]->mCode == IC_LEA && + mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && + mInstructions[i + 2]->mCode == IC_LOAD && + mInstructions[i + 2]->mSrc[0].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 2]->mSrc[0].mFinal && + CanSwapInstructions(mInstructions[i + 1], mInstructions[i + 2])) + { + InterInstruction* ins = mInstructions[i + 2]; + mInstructions[i + 2] = mInstructions[i + 1]; + mInstructions[i + 1] = ins; + changed = true; + } else if ( mInstructions[i + 0]->mCode == IC_STORE && mInstructions[i + 1]->mCode == IC_STORE && SameMemSegment(mInstructions[i + 1]->mSrc[1], mInstructions[i + 0]->mSrc[1]) && @@ -16736,7 +16748,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "join"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 0612f0e..cf1c62f 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -40,7 +40,7 @@ static inline InterType InterTypeOf(const Declaration* dec) InterCodeGenerator::ExValue InterCodeGenerator::ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v) { - if (v.mType->mType == DT_TYPE_REFERENCE) + if (v.mType && v.mType->mType == DT_TYPE_REFERENCE) { v.mType = v.mType->mBase; v.mReference++; @@ -1020,7 +1020,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro { if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION) vr = Dereference(proc, texp, block, vr, 1); - else if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) + else if (pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE && vr.mType->mType != DT_TYPE_REFERENCE)) vr = Dereference(proc, texp, block, vr, 1); else vr = Dereference(proc, texp, block, vr); @@ -2029,7 +2029,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = Dereference(proc, exp, block, vr); if (vl.mType->mType != DT_TYPE_ARRAY && vl.mType->mType != DT_TYPE_POINTER) + { mErrors->Error(exp->mLocation, EERR_INVALID_INDEX, "Invalid type for indexing"); + return ExValue(TheConstVoidTypeDeclaration, -1); + } if (!vr.mType->IsIntegerType()) mErrors->Error(exp->mLocation, EERR_INVALID_INDEX, "Index operand is not integral number"); @@ -3235,7 +3238,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(texp->mLocation, EWARN_NUMERIC_0_USED_AS_NULLPTR, "Numeric 0 used for nullptr"); vr = CoerceType(proc, texp, block, vr, pdec->mBase); } - else if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) + else if (pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE && vr.mType->mType != DT_TYPE_REFERENCE)) vr = Dereference(proc, texp, block, vr, 1); else vr = Dereference(proc, texp, block, vr); @@ -4659,7 +4662,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, "main")) + if (proc->mIdent && !strcmp(proc->mIdent->mString, "join")) exp->Dump(0); #endif #if 0 diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 9ad5473..9fdf5f6 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -16298,7 +16298,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) fblock->mFalseJump = mFalseJump; fblock->mBranch = mBranch; - mIns[i + 0].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 3].mType = ASMIT_INC; mIns[i + 3].mLive |= LIVE_CPU_REG_Z; @@ -25274,6 +25274,8 @@ bool NativeCodeBasicBlock::MoveZeroPageCrossBlockUp(int at, const NativeCodeInst return false; if (mIns[i].ReferencesZeroPage(sins.mAddress)) return false; + if (mIns[i].mMode == ASMIM_INDIRECT_Y && (mIns[i].mAddress + 1 == lins.mAddress || mIns[i].mAddress == lins.mAddress)) + return false; } at = mIns.Size(); @@ -27108,6 +27110,58 @@ bool NativeCodeBasicBlock::ReverseLoadCommutativeOpUp(int aload, int aop) return false; } +bool NativeCodeBasicBlock::MoveTYADCStoreDown(int at) +{ + // [at + 0] TYA + // [at + 1] CLC + // [at + 2] ADC # + // [at + 3] STA + + int offset = mIns[at + 2].mAddress; + int addr = mIns[at + 3].mAddress; + + for (int i = at + 4; i < mIns.Size(); i++) + { + NativeCodeInstruction& ins(mIns[i]); + + if (mIns[i].mType == ASMIT_INY) + offset--; + else if (mIns[i].mType == ASMIT_DEY) + offset++; + else if (mIns[i].ChangesYReg()) + return false; + else if (mIns[i].ReferencesZeroPage(addr)) + return false; + else if (!(mIns[i].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_Z))) + { + if (offset < -2 || offset > 2) + return false; + while (offset < 0) + { + mIns.Insert(i, NativeCodeInstruction(mIns[at].mIns, ASMIT_DEY)); + offset++; + i++; + } + while (offset > 0) + { + mIns.Insert(i, NativeCodeInstruction(mIns[at].mIns, ASMIT_INY)); + offset--; + i++; + } + mIns.Insert(i, NativeCodeInstruction(mIns[at].mIns, ASMIT_STY, ASMIM_ZERO_PAGE, addr)); + while (i > at) + { + mIns[i].mLive |= LIVE_CPU_REG_Y; + i--; + } + mIns.Remove(at, 4); + return true; + } + } + + return false; +} + bool NativeCodeBasicBlock::MoveLDSTXOutOfRange(int at) { int j = at + 2; @@ -28678,15 +28732,19 @@ bool NativeCodeBasicBlock::OptimizeSingleEntryLoop(NativeCodeProcedure* proc) i++; } - int aimm = -1; + bool aimm = false; + NativeCodeInstruction ains; if (!pblock->mExitRequiredRegs[CPU_REG_A] || !pblock->mExitRequiredRegs[CPU_REG_X]) { for (int i = 0; i < mIns.Size(); i++) { - if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_IMMEDIATE) - aimm = mIns[i].mAddress; - else if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE && aimm >= 0) + if (mIns[i].mType == ASMIT_LDA && (mIns[i].mMode == ASMIM_IMMEDIATE || mIns[i].mMode == ASMIM_IMMEDIATE_ADDRESS)) + { + aimm = true; + ains = mIns[i]; + } + else if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE && aimm) { int reg = mIns[i].mAddress; if (!ReferencedOnPath(this, 0, i, reg) && !ChangedOnPath(this, i + 1, mIns.Size(), reg)) @@ -28698,12 +28756,12 @@ bool NativeCodeBasicBlock::OptimizeSingleEntryLoop(NativeCodeProcedure* proc) { if (!pblock->mExitRequiredRegs[CPU_REG_A]) { - pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_LDA, ASMIM_IMMEDIATE, aimm)); + pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_LDA, ains)); pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); } else if (!pblock->mExitRequiredRegs[CPU_REG_X]) { - pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_LDX, ASMIM_IMMEDIATE, aimm)); + pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_LDX, ains)); pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_STX, ASMIM_ZERO_PAGE, reg)); } @@ -28724,7 +28782,7 @@ bool NativeCodeBasicBlock::OptimizeSingleEntryLoop(NativeCodeProcedure* proc) } } else if (mIns[i].ChangesAccu()) - aimm = -1; + aimm = false; } } } @@ -33760,6 +33818,20 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #endif +#if 1 + for (int i = 0; i + 4 < mIns.Size(); i++) + { + if (mIns[i + 0].mType == ASMIT_TYA && mIns[i + 1].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) + { + if (MoveTYADCStoreDown(i)) + changed = true; + } + } + CheckLive(); +#endif + #if 1 // move load - store abs up to initial store // @@ -38380,6 +38452,26 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } #endif +#if 1 + else if ( + mIns[i + 0].mType == ASMIT_TYA && + mIns[i + 1].mType == ASMIT_TAX && + mIns[i + 2].mType == ASMIT_CLC && + mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress <= 2 && + mIns[i + 4].mType == ASMIT_TAY && !(mIns[i + 4].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) + { + mIns[i + 0].mLive |= LIVE_CPU_REG_Y; + mIns[i + 1].mLive |= LIVE_CPU_REG_Y; + mIns[i + 2].mType = ASMIT_INY; mIns[i + 2].mLive |= LIVE_CPU_REG_Y; + mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED; + if (mIns[i + 3].mAddress > 1) + mIns[i + 4].mType = ASMIT_INY; + else + mIns[i + 4].mType = ASMIT_NOP; + + progress = true; + } +#endif #if 0 else if ( mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && @@ -40692,7 +40784,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "time_draw"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index d417e8e..044061b 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -410,6 +410,7 @@ public: bool MoveLoadAddZPStoreUp(int at); bool MoveLoadShiftRotateUp(int at); bool MoveLoadShiftStoreUp(int at); + bool MoveTYADCStoreDown(int at); bool MoveLDSTXOutOfRange(int at); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index e424e98..f7df66e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -8,6 +8,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn { mGlobals = new DeclarationScope(compilationUnits->mScope, SLEVEL_STATIC); mScope = mGlobals; + mTemplateScope = nullptr; mCodeSection = compilationUnits->mSectionCode; mDataSection = compilationUnits->mSectionData; @@ -28,6 +29,20 @@ Parser::~Parser(void) } +Parser* Parser::Clone(void) +{ + Parser* p = new Parser(mErrors, new Scanner(mErrors, mScanner->mPreprocessor), mCompilationUnits); + + p->mGlobals = mGlobals; + p->mScope = mScope; + p->mCompilerOptions = mCompilerOptions; + p->mCodeSection = mCodeSection; + p->mDataSection = mDataSection; + p->mBSSection = mBSSection; + + return p; +} + Declaration* Parser::FindBaseMemberFunction(Declaration* dec, Declaration* mdec) { const Ident* ident = mdec->mIdent; @@ -117,7 +132,15 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) structName = mScanner->mTokenIdent; mScanner->NextToken(); Declaration* edec = mScope->Lookup(structName); - if (edec && mScanner->mToken != TK_OPEN_BRACE && mScanner->mToken != TK_COLON) + if (edec && edec->mType == DT_TEMPLATE) + { + mTemplateScope->Insert(structName, dec); + + dec->mIdent = structName; + dec->mQualIdent = mScope->Mangle(structName->Mangle(mTemplateScope->mName->mString)); + dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, dec->mQualIdent); + } + else if (edec && mScanner->mToken != TK_OPEN_BRACE && mScanner->mToken != TK_COLON) { dec = edec; } @@ -562,53 +585,65 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) case TK_IDENT: pident = mScanner->mTokenIdent; - dec = mScope->Lookup(mScanner->mTokenIdent); - if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS) - dec = mScope->mParent->Lookup(mScanner->mTokenIdent); + if (mTemplateScope) + dec = mTemplateScope->Lookup(mScanner->mTokenIdent); - mScanner->NextToken(); - while (qualified && dec && dec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON)) + if (!dec) { - if (ExpectToken(TK_IDENT)) - { - pident = mScanner->mTokenIdent; - dec = dec->mScope->Lookup(mScanner->mTokenIdent); - mScanner->NextToken(); - } - } + dec = mScope->Lookup(mScanner->mTokenIdent); + if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS) + dec = mScope->mParent->Lookup(mScanner->mTokenIdent); - if (dec && dec->mType <= DT_TYPE_FUNCTION) - { - if (dec->IsSimpleType() && (flags & ~dec->mFlags)) + mScanner->NextToken(); + + if (dec && dec->mType == DT_TEMPLATE) + dec = ParseTemplateExpansion(dec, nullptr); + + while (qualified && dec && dec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON)) { - Declaration* ndec = new Declaration(dec->mLocation, dec->mType); - ndec->mFlags = dec->mFlags | flags; - ndec->mSize = dec->mSize; - ndec->mBase = dec->mBase; - dec = ndec; + if (ExpectToken(TK_IDENT)) + { + pident = mScanner->mTokenIdent; + dec = dec->mScope->Lookup(mScanner->mTokenIdent); + mScanner->NextToken(); + } } - else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) + + if (dec && dec->mType <= DT_TYPE_FUNCTION) { - if ((flags & ~dec->mFlags) == DTF_CONST) - dec = dec->ToConstType(); - else + if (dec->IsSimpleType() && (flags & ~dec->mFlags)) { Declaration* ndec = new Declaration(dec->mLocation, dec->mType); ndec->mFlags = dec->mFlags | flags; ndec->mSize = dec->mSize; ndec->mBase = dec->mBase; - ndec->mScope = dec->mScope; - ndec->mParams = dec->mParams; - ndec->mIdent = dec->mIdent; - ndec->mQualIdent = dec->mQualIdent; dec = ndec; } + else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) + { + if ((flags & ~dec->mFlags) == DTF_CONST) + dec = dec->ToConstType(); + else + { + Declaration* ndec = new Declaration(dec->mLocation, dec->mType); + ndec->mFlags = dec->mFlags | flags; + ndec->mSize = dec->mSize; + ndec->mBase = dec->mBase; + ndec->mScope = dec->mScope; + ndec->mParams = dec->mParams; + ndec->mIdent = dec->mIdent; + ndec->mQualIdent = dec->mQualIdent; + dec = ndec; + } + } } + else if (!dec) + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); + else + mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); } - else if (!dec) - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); else - mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); + mScanner->NextToken(); break; case TK_ENUM: @@ -804,10 +839,26 @@ Declaration* Parser::ParsePostfixDeclaration(void) { dec = new Declaration(mScanner->mLocation, DT_VARIABLE); dec->mIdent = mScanner->mTokenIdent; - dec->mQualIdent = mScope->Mangle(dec->mIdent); dec->mSection = mBSSection; dec->mBase = nullptr; mScanner->NextToken(); + + if (mScanner->mToken == TK_LESS_THAN && mTemplateScope) + { + Declaration* tdec = mScope->Lookup(dec->mIdent); + if (tdec && tdec->mType == DT_TEMPLATE) + { + // for now just skip over template stuff + while (!ConsumeTokenIf(TK_GREATER_THAN)) + mScanner->NextToken(); + + if (mTemplateScope->mName) + dec->mIdent = dec->mIdent->Mangle(mTemplateScope->mName->mString); + } + } + + dec->mQualIdent = mScope->Mangle(dec->mIdent); + if (mScanner->mToken == TK_OPEN_PARENTHESIS && mScope->mLevel >= SLEVEL_FUNCTION) { // Can't be a function declaration in local context, so it must be an object @@ -2964,6 +3015,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) cexp->mToken = pex->mToken; pex->mType = EX_INITIALIZATION; + pex->mToken = TK_ASSIGN; pex->mLeft = vexp; pex->mRight = cexp; pex->mDecValue = nullptr; @@ -2990,6 +3042,38 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) rexp = ConcatExpression(rexp, dexp); } } + else if (pdec->mBase->mType == DT_TYPE_REFERENCE && pex->mType == EX_CONSTANT) + { + // A simple constant is passed by const ref + if (pex->mDecValue->mType == DT_CONST_INTEGER || pex->mDecValue->mType == DT_CONST_FLOAT || pex->mDecValue->mType == DT_CONST_POINTER) + { + int nindex = mLocalIndex++; + + Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); + + vdec->mVarIndex = nindex; + vdec->mBase = pdec->mBase->mBase; + vdec->mSize = pdec->mBase->mBase->mSize; + + Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE); + vexp->mDecType = pdec->mBase->mBase; + vexp->mDecValue = vdec; + + Expression* cexp = new Expression(pex->mLocation, pex->mType); + cexp->mDecType = pex->mDecType; + cexp->mDecValue = pex->mDecValue; + cexp->mLeft = pex->mLeft; + cexp->mRight = pex->mRight; + cexp->mToken = pex->mToken; + + pex->mType = EX_INITIALIZATION; + pex->mToken = TK_ASSIGN; + pex->mLeft = vexp; + pex->mRight = cexp; + pex->mDecValue = nullptr; + pex->mDecType = vdec->mBase; + } + } pdec = pdec->mNext; } @@ -4108,7 +4192,15 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) Declaration* Parser::ParseQualIdent(void) { - Declaration* dec = mScope->Lookup(mScanner->mTokenIdent); + Declaration* dec = nullptr; + if (mTemplateScope) + { + dec = mTemplateScope->Lookup(mScanner->mTokenIdent); + } + + if (!dec) + dec = mScope->Lookup(mScanner->mTokenIdent); + if (dec) { mScanner->NextToken(); @@ -4371,6 +4463,9 @@ Expression* Parser::ParseSimpleExpression(bool lhs) dec = ParseQualIdent(); if (dec) { + if (dec->mType == DT_TEMPLATE) + dec = ParseTemplateExpansion(dec, nullptr); + if (dec->mType == DT_CONST_INTEGER || dec->mType == DT_CONST_FLOAT || dec->mType == DT_CONST_FUNCTION || dec->mType == DT_CONST_ASSEMBLER || dec->mType == DT_LABEL || dec->mType == DT_LABEL_REF) { exp = new Expression(mScanner->mLocation, EX_CONSTANT); @@ -6980,10 +7075,153 @@ Expression* Parser::ParseSwitchStatement(void) return sexp; } -void Parser::ParseTemplate(void) +Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* expd) +{ + + Declaration * tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); + tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + + if (expd) + { + tdec->mParams = expd->mParams; + Declaration* dec = tdec->mParams; + while (dec) + { + tdec->mScope->Insert(dec->mIdent, dec->mBase); + dec = dec->mNext; + } + } + else + { + ConsumeToken(TK_LESS_THAN); + + Declaration* ppdec = nullptr; + Declaration* pdec = tmpld->mParams; + while (pdec) + { + Declaration* epdec = pdec->Clone(); + Expression* exp = ParseShiftExpression(false); + + if (epdec->mType == DT_TYPE_TEMPLATE) + { + if (exp->mType == EX_TYPE) + epdec->mBase = exp->mDecType; + else + mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Type parameter expected", pdec->mIdent); + } + else + { + if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) + epdec->mBase = exp->mDecValue; + else + mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Const integer parameter expected", pdec->mIdent); + } + + tdec->mScope->Insert(epdec->mIdent, epdec->mBase); + epdec->mFlags |= DTF_DEFINED; + + if (ppdec) + ppdec->mNext = epdec; + else + tdec->mParams = epdec; + ppdec = epdec; + + pdec = pdec->mNext; + if (pdec) + ConsumeToken(TK_COMMA); + } + + ConsumeToken(TK_GREATER_THAN); + } + + Declaration* etdec = tmpld->mNext; + while (etdec && !etdec->IsSameParams(tdec)) + etdec = etdec->mNext; + if (etdec) + { + return etdec->mBase; + } + else + { + Parser* p = tmpld->mParser; + + p->mScanner->Replay(tmpld->mTokens); + + tdec->mScope->mName = tdec->MangleIdent(); + + p->mTemplateScope = tdec->mScope; + tdec->mBase = p->ParseDeclaration(nullptr, true, false); + p->mTemplateScope = nullptr; + + tdec->mNext = tmpld->mNext; + tmpld->mNext = tdec; + + if (tdec->mBase->mType == DT_ANON) + { + tdec->mBase = tdec->mBase->mBase; + mCompilationUnits->mTemplateScope->Insert(tmpld->mQualIdent, tmpld); + + tdec->mBase->mScope->Iterate([=](const Ident* ident, Declaration* mdec) + { + if (mdec->mType == DT_CONST_FUNCTION) + { + while (mdec) + { + if (!(mdec->mFlags & DTF_DEFINED)) + { + Declaration* mpdec = mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); + if (mpdec && mpdec->mType == DT_TEMPLATE) + { + p->ParseTemplateExpansion(mpdec, tdec); + } + } + + mdec = mdec->mNext; + } + } + }); + } + + return tdec->mBase; + } +} + +void Parser::CompleteTemplateExpansion(Declaration* tmpld) +{ + tmpld = tmpld->mNext; + while (tmpld) + { + if (tmpld->mBase->mType == DT_TYPE_STRUCT) + { + // now expand the templated members + + tmpld->mBase->mScope->Iterate([=](const Ident* ident, Declaration* mdec) + { + if (mdec->mType == DT_CONST_FUNCTION) + { + while (mdec) + { + Declaration* mpdec = mScope->Lookup(mdec->mQualIdent); + if (mpdec && mpdec->mType == DT_TEMPLATE) + { + ParseTemplateExpansion(mpdec, tmpld); + } + + mdec = mdec->mNext; + } + } + }); + } + } +} + + +void Parser::ParseTemplateDeclaration(void) { ConsumeToken(TK_LESS_THAN); Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); + tdec->mParser = this->Clone(); + tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); Declaration* ppdec = nullptr; for (;;) @@ -6994,9 +7232,8 @@ void Parser::ParseTemplate(void) { if (mScanner->mToken == TK_IDENT) { - Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + pdec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); pdec->mIdent = mScanner->mTokenIdent; - pdec->mBase = TheVoidTypeDeclaration; mScanner->NextToken(); } else @@ -7006,9 +7243,8 @@ void Parser::ParseTemplate(void) { if (mScanner->mToken == TK_IDENT) { - Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + pdec = new Declaration(mScanner->mLocation, DT_CONST_TEMPLATE); pdec->mIdent = mScanner->mTokenIdent; - pdec->mBase = TheSignedIntTypeDeclaration; mScanner->NextToken(); } else @@ -7019,6 +7255,9 @@ void Parser::ParseTemplate(void) if (pdec) { + tdec->mScope->Insert(pdec->mIdent, pdec); + pdec->mFlags |= DTF_DEFINED; + if (ppdec) ppdec->mNext = pdec; else @@ -7032,16 +7271,86 @@ void Parser::ParseTemplate(void) ConsumeToken(TK_GREATER_THAN); + mScanner->BeginRecord(); if (mScanner->mToken == TK_CLASS) { // Class template + Declaration* bdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT); + tdec->mBase = bdec; + mScanner->NextToken(); + if (mScanner->mToken == TK_IDENT) + { + bdec->mIdent = mScanner->mTokenIdent; + bdec->mQualIdent = mScope->Mangle(bdec->mIdent); + + while (mScanner->mToken != TK_SEMICOLON && mScanner->mToken != TK_OPEN_BRACE) + mScanner->NextToken(); + + if (ConsumeTokenIf(TK_OPEN_BRACE)) + { + int qdepth = 1; + while (qdepth) + { + if (ConsumeTokenIf(TK_OPEN_BRACE)) + qdepth++; + else if (ConsumeTokenIf(TK_CLOSE_BRACE)) + qdepth--; + else + mScanner->NextToken(); + } + } + } + else + mErrors->Error(bdec->mLocation, EERR_FUNCTION_TEMPLATE, "Class template expected"); } else { // Function template + mTemplateScope = tdec->mScope; + Declaration* bdec = ParseBaseTypeDeclaration(0, false); + Declaration* adec = ParsePostfixDeclaration(); + + adec = ReverseDeclaration(adec, bdec); + + mTemplateScope = nullptr; + + if (adec->mBase->mType == DT_TYPE_FUNCTION) + { + adec->mType = DT_CONST_FUNCTION; + adec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + adec->mFlags |= DTF_NATIVE; + + tdec->mBase = adec; + + if (ConsumeTokenIf(TK_OPEN_BRACE)) + { + int qdepth = 1; + while (qdepth) + { + if (ConsumeTokenIf(TK_OPEN_BRACE)) + qdepth++; + else if (ConsumeTokenIf(TK_CLOSE_BRACE)) + qdepth--; + else + mScanner->NextToken(); + } + } + } + else + mErrors->Error(bdec->mLocation, EERR_FUNCTION_TEMPLATE, "Function template expected"); } + + tdec->mTokens = mScanner->CompleteRecord(); + + tdec->mIdent = tdec->mBase->mIdent; + tdec->mQualIdent = tdec->mBase->mQualIdent; + tdec->mScope->mName = tdec->mQualIdent; + + mScope->Insert(tdec->mQualIdent, tdec); } @@ -8673,7 +8982,7 @@ void Parser::Parse(void) else if (mScanner->mToken == TK_TEMPLATE) { mScanner->NextToken(); - ParseTemplate(); + ParseTemplateDeclaration(); } else if (mScanner->mToken == TK_NAMESPACE) { diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 81fa74b..710f1b0 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -10,7 +10,9 @@ public: Parser(Errors * errors, Scanner* scanner, CompilationUnits * compilationUnits); ~Parser(void); - DeclarationScope * mGlobals, * mScope; + Parser* Clone(void); + + DeclarationScope * mGlobals, * mScope, * mTemplateScope; int mLocalIndex; CompilationUnits * mCompilationUnits; Declaration * mThisPointer, * mReturnType; @@ -93,7 +95,9 @@ protected: bool CanCoerceExpression(Expression* exp, Declaration* type); void CompleteFunctionDefaultParams(Expression* exp); - void ParseTemplate(void); + void ParseTemplateDeclaration(void); + Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); + void CompleteTemplateExpansion(Declaration* tmpld); Expression* ParseSimpleExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 07f60f4..88e63f8 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -309,7 +309,7 @@ Macro* MacroDict::Lookup(const Ident* ident) TokenSequence::TokenSequence(Scanner* scanner) : mNext(nullptr), mLocation(scanner->mLocation), mToken(scanner->mToken), - mTokenIdent(scanner->mTokenIdent), mTokenChar(scanner->mTokenChar), + mTokenIdent(scanner->mTokenIdent), mTokenInteger(scanner->mTokenInteger), mTokenNumber(scanner->mTokenNumber), mTokenString(nullptr) { @@ -345,6 +345,7 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor) mToken = TK_NONE; mUngetToken = TK_NONE; mReplay = nullptr; + mRecord = mRecordLast = nullptr; mOnceDict = new MacroDict(); @@ -359,15 +360,23 @@ Scanner::~Scanner(void) } -TokenSequence* Scanner::Record(void) +void Scanner::BeginRecord(void) { - return new TokenSequence(this); + mRecord = mRecordLast = new TokenSequence(this); +} + +TokenSequence* Scanner::CompleteRecord(void) +{ + TokenSequence* seq = mRecord; + mRecord = mRecordLast = nullptr; + return seq; } const TokenSequence* Scanner::Replay(const TokenSequence* replay) { const TokenSequence* seq = mReplay; mReplay = replay; + NextToken(); return seq; } @@ -463,16 +472,27 @@ void Scanner::NextToken(void) mToken = mReplay->mToken; mTokenIdent = mReplay->mTokenIdent; - mTokenChar = mReplay->mTokenChar; mTokenNumber = mReplay->mTokenNumber; mTokenInteger = mReplay->mTokenInteger; if (mReplay->mTokenString) strcpy_s(mTokenString, mReplay->mTokenString); mReplay = mReplay->mNext; - return; } + else + { + NextPreToken(); + if (mRecord) + { + mRecordLast->mNext = new TokenSequence(this); + mRecordLast = mRecordLast->mNext; + } + } +} + +void Scanner::NextPreToken(void) +{ for (;;) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 3d1691f..984fcf3 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -214,7 +214,6 @@ struct TokenSequence Token mToken; const Ident * mTokenIdent; - char mTokenChar; const char * mTokenString; double mTokenNumber; int64 mTokenInteger; @@ -233,7 +232,9 @@ public: void NextToken(void); - TokenSequence* Record(void); + void BeginRecord(void); + TokenSequence* CompleteRecord(void); + const TokenSequence* Replay(const TokenSequence * sequence); void Warning(const char * error); @@ -272,6 +273,7 @@ public: void MarkSourceOnce(void); protected: void NextRawToken(void); + void NextPreToken(void); struct MacroExpansion { @@ -289,6 +291,7 @@ protected: Token mUngetToken; const TokenSequence* mReplay; + TokenSequence* mRecord, * mRecordLast; void StringToken(char terminator, char mode); void CharToken(char mode); From 5b7334bb17589c528747aea161a6d02c8b6f8570 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 11 Aug 2023 19:04:13 +0200 Subject: [PATCH 077/169] Add placement new and destructor call --- oscar64/Parser.cpp | 421 +++++++++++++++++++++++++-------------------- oscar64/Parser.h | 2 + 2 files changed, 232 insertions(+), 191 deletions(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index f7df66e..df5f7c1 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -4648,18 +4648,31 @@ Expression* Parser::ParseQualify(Expression* exp) { Expression* nexp = new Expression(mScanner->mLocation, EX_QUALIFY); nexp->mLeft = exp; - if (mScanner->mToken == TK_IDENT) + + int moffset = 0; + uint64 mflags = 0; + Declaration* mdec = nullptr; + const Ident* ident = nullptr; + + if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_BINARY_NOT) { - int moffset; - uint64 mflags; - Declaration* mdec = MemberLookup(dtype, mScanner->mTokenIdent, moffset, mflags); + mScanner->NextToken(); + if (mScanner->mToken == TK_IDENT) + ident = mScanner->mTokenIdent->PreMangle("~"); + } + else if (mScanner->mToken == TK_IDENT) + ident = mScanner->mTokenIdent; + + if (ident) + { + mdec = MemberLookup(dtype, ident, moffset, mflags); if (mdec) { if (mflags & DTF_PROTECTED) - { + { if (!mThisPointer || mThisPointer->mBase->IsConstSame(dtype)) - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", mScanner->mTokenIdent); + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", ident); } mScanner->NextToken(); @@ -4730,10 +4743,10 @@ Expression* Parser::ParseQualify(Expression* exp) mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not found", mScanner->mTokenIdent); mScanner->NextToken(); } - } else mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Struct member identifier expected"); + } else mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Struct expected"); @@ -5414,6 +5427,215 @@ Expression* Parser::ParsePostfixExpression(bool lhs) } +Expression* Parser::ParseNewOperator(void) +{ + Expression* nexp; + + nexp = new Expression(mScanner->mLocation, EX_PREFIX); + nexp->mToken = TK_NEW; + mScanner->NextToken(); + + bool placement = false; + + // Check for placement new + if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) + { + nexp->mType = EX_TYPECAST; + nexp->mLeft = ParseExpression(false); + + ConsumeToken(TK_CLOSE_PARENTHESIS); + placement = true; + } + + Declaration* dec = ParseBaseTypeDeclaration(0, true); + + Declaration* sconst = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + sconst->mBase = TheUnsignedIntTypeDeclaration; + sconst->mInteger = dec->mSize; + + Expression* sexp = new Expression(mScanner->mLocation, EX_CONSTANT); + sexp->mDecValue = sconst; + sexp->mDecType = TheUnsignedIntTypeDeclaration; + + Declaration* nudec = new Declaration(mScanner->mLocation, DT_CONST_ADDRESS); + nudec->mBase = TheVoidPointerTypeDeclaration; + nudec->mInteger = 0; + Expression* nuexp = new Expression(mScanner->mLocation, EX_CONSTANT); + nuexp->mDecValue = nudec; + nuexp->mDecType = nudec->mBase; + + if (ConsumeTokenIf(TK_OPEN_BRACKET)) + { + Expression* mexp = new Expression(mScanner->mLocation, EX_BINARY); + mexp->mToken = TK_MUL; + mexp->mLeft = sexp; + mexp->mRight = ParseExpression(false); + mexp->mDecType = TheUnsignedIntTypeDeclaration; + ConsumeToken(TK_CLOSE_BRACKET); + + if (!placement) + nexp->mLeft = mexp; + + nexp->mDecType = dec->BuildPointer(mScanner->mLocation); + + if (dec->mVectorConstructor) + { + Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + vdec->mVarIndex = mLocalIndex++; + vdec->mBase = nexp->mDecType; + vdec->mSize = 2; + + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = vdec->mBase; + vexp->mDecValue = vdec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + iexp->mToken = TK_ASSIGN; + iexp->mLeft = vexp; + iexp->mRight = nexp; + iexp->mDecType = nexp->mDecType; + + Expression* csexp = new Expression(mScanner->mLocation, EX_TYPECAST); + csexp->mLeft = vexp; + csexp->mDecType = nexp->mDecType->BuildPointer(mScanner->mLocation); + + Declaration* mdec = dec->mVectorConstructor; + + Expression* pexp = new Expression(mScanner->mLocation, EX_LIST); + pexp->mLeft = vexp; + pexp->mRight = new Expression(mScanner->mLocation, EX_INDEX); + pexp->mRight->mLeft = csexp; + pexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + pexp->mRight->mRight->mDecType = TheSignedIntTypeDeclaration; + pexp->mRight->mRight->mDecValue = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + pexp->mRight->mRight->mDecValue->mBase = TheSignedIntTypeDeclaration; + pexp->mRight->mRight->mDecValue->mInteger = -1; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + + Expression* coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); + coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); + coexp->mLeft->mDecType = TheBoolTypeDeclaration; + coexp->mLeft->mToken = TK_EQUAL; + coexp->mLeft->mLeft = vexp; + coexp->mLeft->mRight = nuexp; + coexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + coexp->mRight->mLeft = vexp; + coexp->mRight->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + coexp->mRight->mRight->mLeft = dexp; + coexp->mRight->mRight->mRight = vexp; + coexp->mDecType = vexp->mDecType; + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + sexp->mLeft = iexp; + sexp->mRight = coexp; + sexp->mDecType = coexp->mDecType; + + nexp = sexp; + } + } + else + { + if (!placement) + nexp->mLeft = sexp; + + nexp->mDecType = dec->BuildPointer(mScanner->mLocation); + + if (mScanner->mToken == TK_OPEN_PARENTHESIS || dec->mDefaultConstructor) + { + Declaration* mdec = dec->mDefaultConstructor; + + bool plist = false; + if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) + { + if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) + { + plist = true; + mdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+")); + } + } + + if (mdec) + { + Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + vdec->mVarIndex = mLocalIndex++; + vdec->mBase = nexp->mDecType; + vdec->mSize = 2; + + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = vdec->mBase; + vexp->mDecValue = vdec; + + Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + iexp->mToken = TK_ASSIGN; + iexp->mLeft = vexp; + iexp->mRight = nexp; + iexp->mDecType = nexp->mDecType; + + Expression* pexp = vexp; + + if (plist) + { + pexp = ParseListExpression(false); + + ConsumeToken(TK_CLOSE_PARENTHESIS); + + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = vexp; + lexp->mRight = pexp; + pexp = lexp; + } + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = mdec; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = pexp; + + dexp = ResolveOverloadCall(dexp); + + Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + + sexp->mLeft = dexp; + sexp->mRight = vexp; + sexp->mDecType = vexp->mDecType; + + Expression* coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); + coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); + coexp->mLeft->mDecType = TheBoolTypeDeclaration; + coexp->mLeft->mToken = TK_EQUAL; + coexp->mLeft->mLeft = vexp; + coexp->mLeft->mRight = nuexp; + coexp->mRight = new Expression(mScanner->mLocation, EX_LIST); + coexp->mRight->mLeft = vexp; + coexp->mRight->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); + coexp->mRight->mRight->mLeft = dexp; + coexp->mRight->mRight->mRight = vexp; + coexp->mDecType = vexp->mDecType; + + nexp = new Expression(mScanner->mLocation, EX_SEQUENCE); + nexp->mLeft = iexp; + nexp->mRight = coexp; + nexp->mDecType = coexp->mDecType; + } + else if (plist) + { + mErrors->Error(mScanner->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor", dec->mIdent); + } + } + } + + return nexp; +} + Expression* Parser::ParsePrefixExpression(bool lhs) { if (mScanner->mToken == TK_SUB || mScanner->mToken == TK_BINARY_NOT || mScanner->mToken == TK_LOGICAL_NOT || @@ -5440,190 +5662,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) } else if (mScanner->mToken == TK_NEW) { - nexp = new Expression(mScanner->mLocation, EX_PREFIX); - nexp->mToken = TK_NEW; - mScanner->NextToken(); - Declaration * dec = ParseBaseTypeDeclaration(0, true); - - Declaration* sconst = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); - sconst->mBase = TheUnsignedIntTypeDeclaration; - sconst->mInteger = dec->mSize; - - Expression* sexp = new Expression(mScanner->mLocation, EX_CONSTANT); - sexp->mDecValue = sconst; - sexp->mDecType = TheUnsignedIntTypeDeclaration; - - Declaration* nudec = new Declaration(mScanner->mLocation, DT_CONST_ADDRESS); - nudec->mBase = TheVoidPointerTypeDeclaration; - nudec->mInteger = 0; - Expression* nuexp = new Expression(mScanner->mLocation, EX_CONSTANT); - nuexp->mDecValue = nudec; - nuexp->mDecType = nudec->mBase; - - if (ConsumeTokenIf(TK_OPEN_BRACKET)) - { - Expression* mexp = new Expression(mScanner->mLocation, EX_BINARY); - mexp->mToken = TK_MUL; - mexp->mLeft = sexp; - mexp->mRight = ParseExpression(false); - mexp->mDecType = TheUnsignedIntTypeDeclaration; - ConsumeToken(TK_CLOSE_BRACKET); - - nexp->mLeft = mexp; - nexp->mDecType = dec->BuildPointer(mScanner->mLocation); - - if (dec->mVectorConstructor) - { - Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); - vdec->mVarIndex = mLocalIndex++; - vdec->mBase = nexp->mDecType; - vdec->mSize = 2; - - Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); - vexp->mDecType = vdec->mBase; - vexp->mDecValue = vdec; - - Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); - iexp->mToken = TK_ASSIGN; - iexp->mLeft = vexp; - iexp->mRight = nexp; - iexp->mDecType = nexp->mDecType; - - Expression* csexp = new Expression(mScanner->mLocation, EX_TYPECAST); - csexp->mLeft = vexp; - csexp->mDecType = nexp->mDecType->BuildPointer(mScanner->mLocation); - - Declaration* mdec = dec->mVectorConstructor; - - Expression* pexp = new Expression(mScanner->mLocation, EX_LIST); - pexp->mLeft = vexp; - pexp->mRight = new Expression(mScanner->mLocation, EX_INDEX); - pexp->mRight->mLeft = csexp; - pexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); - pexp->mRight->mRight->mDecType = TheSignedIntTypeDeclaration; - pexp->mRight->mRight->mDecValue = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); - pexp->mRight->mRight->mDecValue->mBase = TheSignedIntTypeDeclaration; - pexp->mRight->mRight->mDecValue->mInteger = -1; - - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; - - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; - - Expression* coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); - coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); - coexp->mLeft->mDecType = TheBoolTypeDeclaration; - coexp->mLeft->mToken = TK_EQUAL; - coexp->mLeft->mLeft = vexp; - coexp->mLeft->mRight = nuexp; - coexp->mRight = new Expression(mScanner->mLocation, EX_LIST); - coexp->mRight->mLeft = vexp; - coexp->mRight->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); - coexp->mRight->mRight->mLeft = dexp; - coexp->mRight->mRight->mRight = vexp; - coexp->mDecType = vexp->mDecType; - - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - sexp->mLeft = iexp; - sexp->mRight = coexp; - sexp->mDecType = coexp->mDecType; - - nexp = sexp; - } - } - else - { - nexp->mLeft = sexp; - nexp->mDecType = dec->BuildPointer(mScanner->mLocation); - - if (mScanner->mToken == TK_OPEN_PARENTHESIS || dec->mDefaultConstructor) - { - Declaration* mdec = dec->mDefaultConstructor; - - bool plist = false; - if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) - { - if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) - { - plist = true; - mdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+")); - } - } - - if (mdec) - { - Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); - vdec->mVarIndex = mLocalIndex++; - vdec->mBase = nexp->mDecType; - vdec->mSize = 2; - - Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); - vexp->mDecType = vdec->mBase; - vexp->mDecValue = vdec; - - Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); - iexp->mToken = TK_ASSIGN; - iexp->mLeft = vexp; - iexp->mRight = nexp; - iexp->mDecType = nexp->mDecType; - - Expression* pexp = vexp; - - if (plist) - { - pexp = ParseListExpression(false); - - ConsumeToken(TK_CLOSE_PARENTHESIS); - - Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); - lexp->mLeft = vexp; - lexp->mRight = pexp; - pexp = lexp; - } - - Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); - cexp->mDecValue = mdec; - cexp->mDecType = cexp->mDecValue->mBase; - - Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); - dexp->mLeft = cexp; - dexp->mRight = pexp; - - dexp = ResolveOverloadCall(dexp); - - Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - - sexp->mLeft = dexp; - sexp->mRight = vexp; - sexp->mDecType = vexp->mDecType; - - Expression* coexp = nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); - coexp->mLeft = new Expression(mScanner->mLocation, EX_RELATIONAL); - coexp->mLeft->mDecType = TheBoolTypeDeclaration; - coexp->mLeft->mToken = TK_EQUAL; - coexp->mLeft->mLeft = vexp; - coexp->mLeft->mRight = nuexp; - coexp->mRight = new Expression(mScanner->mLocation, EX_LIST); - coexp->mRight->mLeft = vexp; - coexp->mRight->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE); - coexp->mRight->mRight->mLeft = dexp; - coexp->mRight->mRight->mRight = vexp; - coexp->mDecType = vexp->mDecType; - - nexp = new Expression(mScanner->mLocation, EX_SEQUENCE); - nexp->mLeft = iexp; - nexp->mRight = coexp; - nexp->mDecType = coexp->mDecType; - } - else if (plist) - { - mErrors->Error(mScanner->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor", dec->mIdent); - } - } - } + nexp = ParseNewOperator(); } else if (mScanner->mToken == TK_DELETE) { diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 710f1b0..6abdd96 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -99,6 +99,8 @@ protected: Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); void CompleteTemplateExpansion(Declaration* tmpld); + Expression* ParseNewOperator(void); + Expression* ParseSimpleExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs); Expression* ParsePostfixExpression(bool lhs); From cb5451b9b9b5a24de65c22c3c704f5bb31947627 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 12 Aug 2023 15:25:30 +0200 Subject: [PATCH 078/169] Automatic function template expansion --- oscar64/Declaration.cpp | 170 ++++++++++++++++++++++++++++++++++------ oscar64/Declaration.h | 7 +- oscar64/Parser.cpp | 60 ++++++++++---- oscar64/Parser.h | 1 + 4 files changed, 197 insertions(+), 41 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index a075e27..23b8254 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -10,6 +10,19 @@ DeclarationScope::DeclarationScope(DeclarationScope* parent, ScopeLevel level, c mHash = nullptr; } +void DeclarationScope::Clear(void) +{ + mHashFill = 0; + if (mHash) + { + for (int i = 0; i < mHashSize; i++) + { + mHash[i].mDec = nullptr; + mHash[i].mIdent = nullptr; + } + } +} + DeclarationScope::~DeclarationScope(void) { delete[] mHash; @@ -797,7 +810,7 @@ Declaration::Declaration(const Location& loc, DecType type) mConst(nullptr), mMutable(nullptr), mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), - mVTable(nullptr), + mVTable(nullptr), mTemplate(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr) @@ -920,6 +933,11 @@ const Ident* Declaration::MangleIdent(void) else mMangleIdent = mQualIdent; + if (mTemplate) + { + + } + if (mFlags & DTF_CONST) mMangleIdent = mMangleIdent->PreMangle("const "); } @@ -927,44 +945,146 @@ const Ident* Declaration::MangleIdent(void) return mMangleIdent; } -Declaration* Declaration::TemplateExpand(Declaration* tdec) +bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) { - if (mType == DT_ARGUMENT) + Declaration* pdec = tdec->mBase->mParams; + + while (pexp) { - Declaration* edec = this->Clone(); - edec->mBase = mBase->TemplateExpand(tdec); - if (mNext) - edec->mNext = mNext->TemplateExpand(tdec); - return edec; + Expression* ex = pexp; + if (pexp->mType == EX_LIST) + { + ex = pexp->mLeft; + pexp = pexp->mRight; + } + else + pexp = nullptr; + + if (pdec) + { + if (!ResolveTemplate(ex->mDecType, pdec->mBase)) + return false; + + pdec = pdec->mNext; + } + else + return false; } - else if (mType == DT_CONST_FUNCTION) + + Declaration* ppdec = nullptr; + Declaration* ptdec = tdec->mTemplate->mParams; + while (ptdec) { - Declaration* edec = this->Clone(); - edec->mBase = mBase->TemplateExpand(tdec); - return edec; + Declaration* pdec = mScope->Lookup(ptdec->mIdent); + if (!pdec) + return false; + + Declaration * epdec = ptdec->Clone(); + epdec->mBase = pdec; + epdec->mFlags |= DTF_DEFINED; + + if (ppdec) + ppdec->mNext = epdec; + else + mParams = epdec; + ppdec = epdec; + ptdec = ptdec->mNext; } - else if (mType == DT_TYPE_FUNCTION) + + mScope->Clear(); + + return true; +} + +bool Declaration::CanResolveTemplate(Expression* pexp, Declaration* tdec) +{ + Declaration* pdec = tdec->mBase->mParams; + + while (pexp) { - Declaration* edec = this->Clone(); - edec->mBase = mBase->TemplateExpand(tdec); - if (edec->mParams) - edec->mParams = mParams->TemplateExpand(tdec); - return edec; + Expression* ex = pexp; + if (pexp->mType == EX_LIST) + { + ex = pexp->mLeft; + pexp = pexp->mRight; + } + else + pexp = nullptr; + + if (pdec) + { + if (!ResolveTemplate(ex->mDecType, pdec->mBase)) + return false; + + pdec = pdec->mNext; + } + else + return false; } - else if (mType == DT_TYPE_TEMPLATE || mType == DT_CONST_TEMPLATE) + + return true; +} + +bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) +{ + if (tdec->IsSame(fdec)) + return true; + else if (tdec->mType == DT_TYPE_FUNCTION) { - return tdec->mScope->Lookup(mIdent); + if (fdec->mType == DT_TYPE_FUNCTION) + { + if (fdec->mBase) + { + if (!tdec->mBase || !ResolveTemplate(fdec->mBase, tdec->mBase)) + return false; + } + else if (tdec->mBase) + return false; + + Declaration* fpdec = fdec->mParams; + Declaration* tpdec = tdec->mParams; + while (fpdec && tpdec) + { + if (!ResolveTemplate(fpdec->mBase, tpdec->mBase)) + return false; + fpdec = fpdec->mNext; + tpdec = tpdec->mNext; + } + if (fpdec || tpdec) + return false; + } + else + return false; + + return true; } - else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY || mType == DT_TYPE_REFERENCE) + else if (tdec->mType == DT_TYPE_REFERENCE) { - Declaration* edec = this->Clone(); - edec->mBase = mBase->TemplateExpand(tdec); - return edec; + if (fdec->mType == DT_TYPE_REFERENCE) + return ResolveTemplate(fdec->mBase, tdec->mBase); + else + return ResolveTemplate(fdec, tdec->mBase); + } + else if (tdec->mType == DT_TYPE_POINTER) + { + if (fdec->mType == DT_TYPE_POINTER) + return ResolveTemplate(fdec->mBase, tdec->mBase); + else + return false; + } + else if (tdec->mType == DT_TYPE_TEMPLATE) + { + Declaration* pdec = mScope->Insert(tdec->mIdent, fdec); + if (pdec && !pdec->IsSame(fdec)) + return false; + + return true; } else - return this; + return tdec->CanAssign(fdec); } + Declaration* Declaration::Clone(void) { Declaration* ndec = new Declaration(mLocation, mType); diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 07d107b..a18439b 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -136,6 +136,7 @@ public: Declaration* Lookup(const Ident* ident, ScopeLevel limit = SLEVEL_GLOBAL); void End(const Location & loc); + void Clear(void); void UseScope(DeclarationScope* scope); @@ -250,7 +251,7 @@ public: Declaration * mBase, * mParams, * mNext, * mPrev, * mConst, * mMutable; Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; - Declaration * mVTable, * mClass; + Declaration * mVTable, * mClass, * mTemplate; Expression* mValue; DeclarationScope* mScope; @@ -296,7 +297,9 @@ public: Declaration* BuildConstPointer(const Location& loc); Declaration* BuildConstReference(const Location& loc); - Declaration* TemplateExpand(Declaration* tdec); + bool CanResolveTemplate(Expression* pexp, Declaration* tdec); + bool ResolveTemplate(Declaration* fdec, Declaration * tdec); + bool ResolveTemplate(Expression* pexp, Declaration* tdec); const Ident* MangleIdent(void); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index df5f7c1..d6ff328 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -132,7 +132,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) structName = mScanner->mTokenIdent; mScanner->NextToken(); Declaration* edec = mScope->Lookup(structName); - if (edec && edec->mType == DT_TEMPLATE) + if (edec && edec->mTemplate) { mTemplateScope->Insert(structName, dec); @@ -596,8 +596,8 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) mScanner->NextToken(); - if (dec && dec->mType == DT_TEMPLATE) - dec = ParseTemplateExpansion(dec, nullptr); + if (dec && dec->mTemplate) + dec = ParseTemplateExpansion(dec->mTemplate, nullptr); while (qualified && dec && dec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON)) { @@ -846,7 +846,7 @@ Declaration* Parser::ParsePostfixDeclaration(void) if (mScanner->mToken == TK_LESS_THAN && mTemplateScope) { Declaration* tdec = mScope->Lookup(dec->mIdent); - if (tdec && tdec->mType == DT_TEMPLATE) + if (tdec && tdec->mTemplate) { // for now just skip over template stuff while (!ConsumeTokenIf(TK_GREATER_THAN)) @@ -3730,7 +3730,11 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ndec->mIdent == ndec->mQualIdent) { Declaration* ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec); - if (ldec && ldec != pdec) + if (ldec && ldec->mTemplate && mTemplateScope) + { + ndec->mQualIdent = ndec->mQualIdent->Mangle(mTemplateScope->mName->mString); + } + else if (ldec && ldec != pdec) mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); } else if (!pdec) @@ -4463,8 +4467,8 @@ Expression* Parser::ParseSimpleExpression(bool lhs) dec = ParseQualIdent(); if (dec) { - if (dec->mType == DT_TEMPLATE) - dec = ParseTemplateExpansion(dec, nullptr); + if (dec->mTemplate && mScanner->mToken == TK_LESS_THAN) + dec = ParseTemplateExpansion(dec->mTemplate, nullptr); if (dec->mType == DT_CONST_INTEGER || dec->mType == DT_CONST_FLOAT || dec->mType == DT_CONST_FUNCTION || dec->mType == DT_CONST_ASSEMBLER || dec->mType == DT_LABEL || dec->mType == DT_LABEL_REF) { @@ -4758,7 +4762,17 @@ static const int NOOVERLOAD = 0x7fffffff; int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) { - Declaration* pdec = fdec->mParams; + if (fdec->mTemplate) + { + Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); + tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + if (tdec->CanResolveTemplate(pexp, fdec)) + return 16; + else + return NOOVERLOAD; + } + + Declaration* pdec = fdec->mBase->mParams; int dist = 0; @@ -4884,7 +4898,7 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) pdec = pdec->mNext; } - else if (fdec->mFlags & DTF_VARIADIC) + else if (fdec->mBase->mFlags & DTF_VARIADIC) { dist += 1024; break; @@ -5052,6 +5066,20 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) return exp; } +void Parser::ExpandFunctionCallTemplate(Expression* exp) +{ + if (exp->mLeft->mDecValue->mTemplate) + { + Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); + tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + if (tdec->ResolveTemplate(exp->mRight, exp->mLeft->mDecValue)) + { + exp->mLeft->mDecValue = ParseTemplateExpansion(exp->mLeft->mDecValue->mTemplate, tdec); + exp->mLeft->mDecType = exp->mLeft->mDecValue->mBase; + } + } +} + void Parser::CompleteFunctionDefaultParams(Expression* exp) { Declaration* fdec = exp->mLeft->mDecValue; @@ -5110,7 +5138,7 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) while (fdec) { - int d = OverloadDistance(fdec->mBase, exp->mRight); + int d = OverloadDistance(fdec, exp->mRight); if (d < ibest) { dbest = fdec; @@ -5125,7 +5153,7 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) while (fdec2) { - int d = OverloadDistance(fdec2->mBase, exp2->mRight); + int d = OverloadDistance(fdec2, exp2->mRight); if (d < ibest) { dbest = fdec2; @@ -5156,6 +5184,7 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) } } + ExpandFunctionCallTemplate(exp); CompleteFunctionDefaultParams(exp); } @@ -7209,9 +7238,9 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp if (!(mdec->mFlags & DTF_DEFINED)) { Declaration* mpdec = mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); - if (mpdec && mpdec->mType == DT_TEMPLATE) + if (mpdec && mpdec->mTemplate) { - p->ParseTemplateExpansion(mpdec, tdec); + p->ParseTemplateExpansion(mpdec->mTemplate, tdec); } } @@ -7316,6 +7345,7 @@ void Parser::ParseTemplateDeclaration(void) // Class template Declaration* bdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT); tdec->mBase = bdec; + bdec->mTemplate = tdec; mScanner->NextToken(); if (mScanner->mToken == TK_IDENT) @@ -7364,6 +7394,7 @@ void Parser::ParseTemplateDeclaration(void) adec->mFlags |= DTF_NATIVE; tdec->mBase = adec; + adec->mTemplate = tdec; if (ConsumeTokenIf(TK_OPEN_BRACE)) { @@ -7389,7 +7420,8 @@ void Parser::ParseTemplateDeclaration(void) tdec->mQualIdent = tdec->mBase->mQualIdent; tdec->mScope->mName = tdec->mQualIdent; - mScope->Insert(tdec->mQualIdent, tdec); + mScope->Insert(tdec->mQualIdent, tdec->mBase); + mCompilationUnits->mScope->Insert(tdec->mQualIdent, tdec->mBase); } diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 6abdd96..892c52b 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -94,6 +94,7 @@ protected: Expression* CoerceExpression(Expression* exp, Declaration* type); bool CanCoerceExpression(Expression* exp, Declaration* type); void CompleteFunctionDefaultParams(Expression* exp); + void ExpandFunctionCallTemplate(Expression* exp); void ParseTemplateDeclaration(void); Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); From 9d6691cf919ba0475dac91a859875f19a3f0b462 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 12 Aug 2023 18:19:46 +0200 Subject: [PATCH 079/169] Copy constructor and destruct for scalar types --- include/opp/vector.h | 42 ++++++++++++++++----- oscar64/Parser.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 118 insertions(+), 12 deletions(-) diff --git a/include/opp/vector.h b/include/opp/vector.h index 4227ca1..d20f405 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -1,6 +1,8 @@ #ifndef OPP_VECTOR_H #define OPP_VECTOR_H +#include + template class vector { @@ -9,10 +11,16 @@ protected: int _size, _capacity; public: vector(void) : _data(nullptr), _size(0), _capacity(0) {} - vector(int n) : _data(new T[n]), _size(n), _capacity(n) {} + vector(int n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n) + { + for(int i=0; i::reserve(int n) if (n > _capacity) { _capacity = n; - T * d = new T[_capacity]; + T * d = (T *)malloc(_capacity * sizeof(T)); for(int i=0; i<_size; i++) - d[i] = _data[i]; - delete[] _data; + { + new (d + i)T(_data[i]); + _data[i].~T(); + } + free(_data); _data = d; } } @@ -122,9 +133,17 @@ template void vector::resize(int n) { if (n < _size) + { + for(int i=n; i<_size; i++) + _data[i].~T(); _size = n; + } else if (n < _capacity) + { + for(int i=_size; i::shrink_to_fit(void) if (_size < _capacity) { _capacity = _size; - T * d = new T[_capacity]; + T * d = (T *)malloc(_capacity * sizeof(T)); for(int i=0; i<_size; i++) - d[i] = _data[i]; - delete[] _data; + { + new (d + i)T(_data[i]); + _data[i].~T(); + } + free(_data); _data = d; } } @@ -151,7 +173,7 @@ void vector::push_back(const T & t) { if (_size == _capacity) reserve(_size + 1 + (_size >> 1)); - _data[_size++] = t; + new (_data + _size++)T(t); } template @@ -159,6 +181,7 @@ void vector::insert(int at, const T & t) { if (_size == _capacity) reserve(_size + 1 + (_size >> 1)); + new (_data + _size)T; for(int i=_size; i>at; i--) _data[i] = _data[i - 1]; _data[at] = t; @@ -170,6 +193,7 @@ void vector::erase(int at, int n) _size -= n; for(int i=at; i<_size; i++) _data[i] = _data[i + n]; + _data[_size].~T(); } #endif diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index d6ff328..c3e50f9 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3301,7 +3301,15 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex mScanner->NextToken(); if (mScanner->mToken == TK_IDENT) { - if (mScanner->mTokenIdent != pthis->mBase->mIdent) + const Ident* ident = mScanner->mTokenIdent; + if (mTemplateScope) + { + Declaration* dec = mTemplateScope->Lookup(ident); + if (dec) + ident = dec->mIdent; + } + + if (ident != pthis->mBase->mIdent) mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Wrong class name for destructor", pthis->mBase->mIdent); mScanner->NextToken(); } @@ -4662,7 +4670,19 @@ Expression* Parser::ParseQualify(Expression* exp) { mScanner->NextToken(); if (mScanner->mToken == TK_IDENT) - ident = mScanner->mTokenIdent->PreMangle("~"); + { + ident = mScanner->mTokenIdent; + if (mTemplateScope) + { + Declaration* dec = mTemplateScope->Lookup(ident); + if (dec) + ident = dec->mIdent; + } + + ident = ident->PreMangle("~"); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); } else if (mScanner->mToken == TK_IDENT) ident = mScanner->mTokenIdent; @@ -4752,6 +4772,40 @@ Expression* Parser::ParseQualify(Expression* exp) mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Struct member identifier expected"); } + else if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_BINARY_NOT) + { + mScanner->NextToken(); + if (mScanner->mToken == TK_IDENT) + { + const Ident * ident = mScanner->mTokenIdent; + if (mTemplateScope) + { + Declaration* dec = mTemplateScope->Lookup(ident); + if (dec == dtype) + { + mScanner->NextToken(); + ConsumeToken(TK_OPEN_PARENTHESIS); + ConsumeToken(TK_CLOSE_PARENTHESIS); + + exp = new Expression(mScanner->mLocation, EX_VOID); + exp->mDecType = TheConstVoidTypeDeclaration; + } + } + else if (ident == dtype->mIdent) + { + mScanner->NextToken(); + ConsumeToken(TK_OPEN_PARENTHESIS); + ConsumeToken(TK_CLOSE_PARENTHESIS); + + exp = new Expression(mScanner->mLocation, EX_VOID); + exp->mDecType = TheConstVoidTypeDeclaration; + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Destructor identifier expected"); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + } else mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Struct expected"); @@ -5586,7 +5640,10 @@ Expression* Parser::ParseNewOperator(void) if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) { plist = true; - mdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+")); + if (dec->mType == DT_TYPE_STRUCT) + mdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+")); + else + mdec = nullptr; } } @@ -5654,6 +5711,31 @@ Expression* Parser::ParseNewOperator(void) nexp->mLeft = iexp; nexp->mRight = coexp; nexp->mDecType = coexp->mDecType; + } + else if (plist && !mdec) + { + Expression * pexp = ParseListExpression(false); + ConsumeToken(TK_CLOSE_PARENTHESIS); + + if (pexp && pexp->mType != EX_LIST) + { + Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX); + dexp->mToken = TK_MUL; + dexp->mLeft = nexp; + dexp->mDecType = nexp->mDecType->mBase; + + Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + iexp->mToken = TK_ASSIGN; + iexp->mLeft = dexp; + iexp->mRight = pexp; + iexp->mDecType = nexp->mDecType; + + nexp = iexp; + } + else + mErrors->Error(mScanner->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor", dec->mIdent); + + } else if (plist) { From 61f8b68c2fec39e05e7cef11a87162d45d07587a Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 13 Aug 2023 11:00:02 +0200 Subject: [PATCH 080/169] Fix duplicate member cons/destructor if class included from multiple cpp --- include/opp/move.h | 11 ++++ oscar64/Compiler.cpp | 3 ++ oscar64/Declaration.cpp | 68 +++++++++++++++++++++++ oscar64/Declaration.h | 9 ++++ oscar64/Errors.h | 1 + oscar64/GlobalAnalyzer.cpp | 2 +- oscar64/InterCodeGenerator.cpp | 6 +++ oscar64/Parser.cpp | 99 +++++++++++++++++++++++++++------- 8 files changed, 178 insertions(+), 21 deletions(-) create mode 100644 include/opp/move.h diff --git a/include/opp/move.h b/include/opp/move.h new file mode 100644 index 0000000..bdf4950 --- /dev/null +++ b/include/opp/move.h @@ -0,0 +1,11 @@ +#ifndef OPP_MOVE_H +#define OPP_MOVE_H + + +template +void move(T & dst, T & src) +{ + dst = src; +} + +#endif diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 08e9b58..7bf5ee2 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -1346,6 +1346,9 @@ bool Compiler::WriteDbjFile(const char* filename) case DT_TYPE_REFERENCE: fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"ref\", eid: %d}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize, types.IndexOrPush(dec->mBase)); break; + case DT_TYPE_RVALUEREF: + fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"rref\", eid: %d}", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize, types.IndexOrPush(dec->mBase)); + break; case DT_TYPE_ENUM: { fprintf(file, "\t\t{\"name\": \"%s\", \"typeid\": %d, \"size\": %d, \"type\": \"enum\",\"members\": [\n", dec->mQualIdent ? dec->mQualIdent->mString : "", i, dec->mSize); diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 23b8254..c957ea4 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -328,6 +328,37 @@ bool Expression::HasSideEffects(void) const } } +bool Expression::IsRValue(void) const +{ + if (mDecType->mType == DT_TYPE_RVALUEREF) + return true; + else if (mDecType->mType == DT_TYPE_REFERENCE) + return false; + else if (mType == EX_VARIABLE) + { + if (mDecValue->mFlags & DTF_TEMPORARY) + return true; + else + return false; + } + else if (mType == EX_QUALIFY || mType == EX_INDEX || mType == EX_ASSIGNMENT || mType == EX_CONSTANT || mType == EX_PREFIX && mToken == TK_MUL) + return false; + else + return true; +} + +bool Expression::IsLValue(void) const +{ + if (mDecType->mFlags & DTF_CONST) + return false; + else 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::IsSame(const Expression* exp) const { if (!exp || mType != exp->mType) @@ -868,6 +899,32 @@ Declaration* Declaration::BuildReference(const Location& loc) return pdec; } +Declaration* Declaration::BuildRValueRef(const Location& loc) +{ + Declaration* pdec = new Declaration(loc, DT_TYPE_RVALUEREF); + pdec->mBase = this; + pdec->mFlags = DTF_DEFINED; + pdec->mSize = 2; + return pdec; +} + +Declaration* Declaration::BuildConstRValueRef(const Location& loc) +{ + Declaration* pdec = new Declaration(loc, DT_TYPE_RVALUEREF); + pdec->mBase = this; + pdec->mFlags = DTF_DEFINED | DTF_CONST; + pdec->mSize = 2; + return pdec; +} + +DecType Declaration::ValueType(void) const +{ + if (mType == DT_TYPE_REFERENCE || mType == DT_TYPE_RVALUEREF) + return mBase->mType; + else + return mType; +} + Declaration* Declaration::Last(void) { mPrev = nullptr; @@ -904,6 +961,10 @@ const Ident* Declaration::MangleIdent(void) { mMangleIdent = mBase->MangleIdent()->PreMangle("&"); } + else if (mType == DT_TYPE_RVALUEREF) + { + mMangleIdent = mBase->MangleIdent()->PreMangle("&&"); + } else if (mType == DT_TYPE_POINTER) { mMangleIdent = mBase->MangleIdent()->PreMangle("*"); @@ -1065,6 +1126,13 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) else return ResolveTemplate(fdec, tdec->mBase); } + else if (tdec->mType == DT_TYPE_RVALUEREF) + { + if (fdec->mType == DT_TYPE_RVALUEREF) + return ResolveTemplate(fdec->mBase, tdec->mBase); + else + return ResolveTemplate(fdec, tdec->mBase); + } else if (tdec->mType == DT_TYPE_POINTER) { if (fdec->mType == DT_TYPE_POINTER) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index a18439b..1f1a9b0 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -20,6 +20,7 @@ enum DecType DT_TYPE_ENUM, DT_TYPE_POINTER, DT_TYPE_REFERENCE, + DT_TYPE_RVALUEREF, DT_TYPE_ARRAY, DT_TYPE_STRUCT, DT_TYPE_UNION, @@ -90,6 +91,8 @@ static const uint64 DTF_DYNSTACK = (1ULL << 25); static const uint64 DTF_PRIVATE = (1ULL << 26); 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_FUNC_VARIABLE = (1ULL << 32); static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33); @@ -235,6 +238,8 @@ public: bool HasSideEffects(void) const; bool IsSame(const Expression* exp) const; + bool IsRValue(void) const; + bool IsLValue(void) const; void Dump(int ident) const; }; @@ -296,6 +301,10 @@ public: Declaration* BuildReference(const Location& loc); Declaration* BuildConstPointer(const Location& loc); Declaration* BuildConstReference(const Location& loc); + Declaration* BuildRValueRef(const Location& loc); + Declaration* BuildConstRValueRef(const Location& loc); + + DecType ValueType(void) const; bool CanResolveTemplate(Expression* pexp, Declaration* tdec); bool ResolveTemplate(Declaration* fdec, Declaration * tdec); diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 23b5678..95c32f1 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -30,6 +30,7 @@ enum ErrorID EWARN_NULL_POINTER_DEREFERENCED, EWARN_DESTRUCTOR_MISMATCH, EWARN_NUMERIC_0_USED_AS_NULLPTR, + EWARN_FLOAT_TO_INT, EERR_GENERIC = 3000, EERR_FILE_NOT_FOUND, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index d9113fe..479330f 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -802,7 +802,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo RegisterCall(procDec, pdec->mBase->mCopyConstructor); } - if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT && !(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE)) + if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT && !(pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF))) ldec->mBase->mFlags |= DTF_STACKCALL; if (pdec) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index cf1c62f..a7fda9a 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -140,6 +140,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p } else if (v.mType->mType == DT_TYPE_FLOAT && type->IsIntegerType()) { + mErrors->Error(exp->mLocation, EWARN_FLOAT_TO_INT, "Float to int conversion, potential loss of precision"); + InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); cins->mOperator = IA_FLOAT2INT; cins->mSrc[0].mType = IT_FLOAT; @@ -155,6 +157,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p v.mType = type; return v; } + else if (type->mType == DT_TYPE_POINTER && v.mType->IsNumericType() && (mCompilerOptions & COPT_CPLUSPLUS)) + { + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign numeric value to pointer"); + } else if (v.mType->mSize < type->mSize) { if (v.mType->mSize == 1 && type->mSize == 2) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index c3e50f9..cde99e8 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -825,6 +825,34 @@ Declaration* Parser::ParsePostfixDeclaration(void) ndec->mBase = dec; return ndec; } + else if (mScanner->mToken == TK_LOGICAL_AND && (mCompilerOptions & COPT_CPLUSPLUS)) + { + mScanner->NextToken(); + + Declaration* ndec = new Declaration(mScanner->mLocation, DT_TYPE_RVALUEREF); + ndec->mSize = 2; + ndec->mFlags |= DTF_DEFINED; + + for (;;) + { + if (mScanner->mToken == TK_CONST) + { + ndec->mFlags |= DTF_CONST; + mScanner->NextToken(); + } + else if (mScanner->mToken == TK_VOLATILE) + { + ndec->mFlags |= DTF_VOLATILE; + mScanner->NextToken(); + } + else + break; + } + + Declaration* dec = ParsePostfixDeclaration(); + ndec->mBase = dec; + return ndec; + } else if (mScanner->mToken == TK_OPEN_PARENTHESIS) { mScanner->NextToken(); @@ -1543,6 +1571,11 @@ Expression* Parser::BuildMemberInitializer(Expression* vexp) void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) { + if (cfunc->mFlags & DTF_COMPLETED) + return; + + cfunc->mFlags |= DTF_COMPLETED; + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); pthisexp->mDecType = pthis; pthisexp->mDecValue = cfunc->mBase->mParams; @@ -2688,6 +2721,10 @@ void Parser::AppendMemberDestructor(Declaration* pthis) { if (pthis->mBase->mDestructor->mFlags & DTF_DEFINED) { + if (pthis->mBase->mDestructor->mFlags & DTF_COMPLETED) + return; + pthis->mBase->mDestructor->mFlags |= DTF_COMPLETED; + Expression* pthisexp = new Expression(pthis->mLocation, EX_VARIABLE); pthisexp->mDecType = pthis; pthisexp->mDecValue = pthis->mBase->mDestructor->mBase->mParams; @@ -2870,7 +2907,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) { Expression* lexp = nullptr, * rexp = nullptr; - if (exp->mType == EX_PREFIX && exp->mToken == TK_BINARY_AND && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE) + if (exp->mType == EX_PREFIX && exp->mToken == TK_BINARY_AND && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE && exp->mLeft->mDecType->mType != DT_TYPE_RVALUEREF) { lexp = AddFunctionCallRefReturned(exp->mLeft); @@ -2921,7 +2958,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) rexp = ConcatExpression(rexp, dexp); } } - else if (exp->mType == EX_QUALIFY && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE) + else if (exp->mType == EX_QUALIFY && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE && exp->mLeft->mDecType->mType != DT_TYPE_RVALUEREF) { lexp = AddFunctionCallRefReturned(exp->mLeft); @@ -2990,7 +3027,8 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) rexp = ConcatExpression(rexp, AddFunctionCallRefReturned(pex)); - if (pdec->mBase->mType == DT_TYPE_REFERENCE && pex->mDecType->mType != DT_TYPE_REFERENCE && pex->mType == EX_CALL) + if ((pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) && + (pex->mDecType->mType != DT_TYPE_REFERENCE && pex->mDecType->mType != DT_TYPE_RVALUEREF) && pex->mType == EX_CALL) { // Returning a value object for pass as reference // add a temporary variable @@ -3042,7 +3080,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) rexp = ConcatExpression(rexp, dexp); } } - else if (pdec->mBase->mType == DT_TYPE_REFERENCE && pex->mType == EX_CONSTANT) + else if ((pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) && pex->mType == EX_CONSTANT) { // A simple constant is passed by const ref if (pex->mDecValue->mType == DT_CONST_INTEGER || pex->mDecValue->mType == DT_CONST_FLOAT || pex->mDecValue->mType == DT_CONST_POINTER) @@ -4653,7 +4691,7 @@ Expression* Parser::ParseQualify(Expression* exp) { Declaration* dtype = exp->mDecType; - if (dtype->mType == DT_TYPE_REFERENCE) + if (dtype->mType == DT_TYPE_REFERENCE || dtype->mType == DT_TYPE_RVALUEREF) dtype = dtype->mBase; if (dtype->mType == DT_TYPE_STRUCT || dtype->mType == DT_TYPE_UNION) @@ -4940,10 +4978,16 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) dist += 0; else if (ptype->IsSubType(etype)) dist += 256; - else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->IsSame(etype)) + else if (ptype->mType == DT_TYPE_RVALUEREF && ptype->mBase->IsSameMutable(etype) && ex->IsRValue()) { - if (ex->mType == EX_VARIABLE) - dist += 1; + dist += 1; + } + else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->IsSameMutable(etype)) + { + if (ex->IsLValue()) + dist += 2; + else if (ptype->mBase->mFlags & DTF_CONST) + dist += 4; else return NOOVERLOAD; } @@ -4976,9 +5020,9 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) bool Parser::CanCoerceExpression(Expression* exp, Declaration* type) { Declaration* tdec = exp->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; - while (type->mType == DT_TYPE_REFERENCE) + while (type->mType == DT_TYPE_REFERENCE || type->mType == DT_TYPE_RVALUEREF) type = type->mBase; if (tdec->mType == DT_TYPE_STRUCT) @@ -5015,9 +5059,9 @@ bool Parser::CanCoerceExpression(Expression* exp, Declaration* type) Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) { Declaration* tdec = exp->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; - while (type->mType == DT_TYPE_REFERENCE) + while (type->mType == DT_TYPE_REFERENCE || type->mType == DT_TYPE_RVALUEREF) type = type->mBase; if (tdec->mType == DT_TYPE_STRUCT) @@ -5223,7 +5267,7 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) if (ibest == NOOVERLOAD) { #if _DEBUG - int d = OverloadDistance(exp->mLeft->mDecValue->mBase, exp->mRight); + int d = OverloadDistance(exp->mLeft->mDecValue, exp->mRight); #endif mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call", exp->mLeft->mDecValue->mQualIdent); } @@ -5262,7 +5306,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) nexp->mRight = ParseExpression(false); ConsumeToken(TK_CLOSE_BRACKET); - if (exp->mDecType->mType == DT_TYPE_STRUCT || exp->mDecType->mType == DT_TYPE_REFERENCE && exp->mDecType->mBase->mType == DT_TYPE_STRUCT) + if (exp->mDecType->ValueType() == DT_TYPE_STRUCT) { nexp = CheckOperatorOverload(nexp); } @@ -5307,7 +5351,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) tdec->mBase = exp->mDecType; tdec->mVarIndex = mLocalIndex++; tdec->mSize = exp->mDecType->mSize; - tdec->mFlags |= DTF_DEFINED; + tdec->mFlags |= DTF_DEFINED | DTF_TEMPORARY; Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); vexp->mDecType = exp->mDecType; @@ -5365,13 +5409,28 @@ Expression* Parser::ParsePostfixExpression(bool lhs) exp = nexp; } - else + else if (pexp) { Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; nexp->mLeft = pexp; exp = nexp->ConstantFold(mErrors); } + else + { + Declaration* tdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + + tdec->mBase = exp->mDecType; + tdec->mVarIndex = mLocalIndex++; + tdec->mSize = exp->mDecType->mSize; + tdec->mFlags |= DTF_DEFINED | DTF_TEMPORARY; + + Expression* nexp = new Expression(mScanner->mLocation, EX_VARIABLE); + nexp->mDecType = exp->mDecType; + nexp->mDecValue = tdec; + + exp = nexp; + } } } else @@ -6270,7 +6329,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) else if (exp->mType == EX_INDEX) { Declaration* tdec = exp->mLeft->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; if (tdec->mType == DT_TYPE_STRUCT) @@ -6486,7 +6545,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) } Declaration* tdec = exp->mLeft->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; if (tdec->mType == DT_TYPE_STRUCT) @@ -6546,7 +6605,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) if (opident) { Declaration* tdec = exp->mLeft->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; if (tdec->mType == DT_TYPE_STRUCT) @@ -6585,7 +6644,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) { const Ident* opident = Ident::Unique("operator!"); Declaration* tdec = exp->mLeft->mDecType; - while (tdec->mType == DT_TYPE_REFERENCE) + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) tdec = tdec->mBase; if (tdec->mType == DT_TYPE_STRUCT) From 80426d974c9b435b32fa5bff29b16e1a68ffeb41 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 13 Aug 2023 20:53:39 +0200 Subject: [PATCH 081/169] Add RValue Reference --- include/opp/move.h | 5 +- include/opp/string.cpp | 18 ++++++ include/opp/string.h | 2 + include/opp/vector.h | 19 +++++-- oscar64/Declaration.cpp | 101 +++++++++++++++++++++++++++++++-- oscar64/Declaration.h | 4 ++ oscar64/InterCode.cpp | 5 +- oscar64/InterCodeGenerator.cpp | 43 ++++++++------ oscar64/Parser.cpp | 26 ++++++++- 9 files changed, 189 insertions(+), 34 deletions(-) diff --git a/include/opp/move.h b/include/opp/move.h index bdf4950..759781a 100644 --- a/include/opp/move.h +++ b/include/opp/move.h @@ -1,11 +1,10 @@ #ifndef OPP_MOVE_H #define OPP_MOVE_H - template -void move(T & dst, T & src) +T && move(T & m) { - dst = src; + return (T &&)m; } #endif diff --git a/include/opp/string.cpp b/include/opp/string.cpp index 72f134c..0c5821d 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -31,6 +31,12 @@ string::string(const string & s) cstr = nullptr; } +string::string(string && s) + : cstr(s.cstr) +{ + s.cstr = nullptr; +} + string::string(const char * s) { if (s) @@ -104,6 +110,18 @@ string & string::operator=(const string & s) return *this; } +string & string::operator=(string && s) +{ + if (cstr != s.cstr) + { + free(cstr); + cstr = s.cstr; + s.cstr = nullptr; + } + + return *this; +} + string & string::operator=(const char * s) { free(cstr); diff --git a/include/opp/string.h b/include/opp/string.h index 747c120..856edf6 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -9,6 +9,7 @@ private: public: string(void); string(const string & s); + string(string && s); string(const char * s); string(const char * s, char size); string(char c); @@ -17,6 +18,7 @@ public: unsigned size(void) const; string & operator=(const string & s); + string & operator=(string && s); string & operator=(const char * s); string & operator+=(const string & s); diff --git a/include/opp/vector.h b/include/opp/vector.h index d20f405..98f9e12 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -2,6 +2,7 @@ #define OPP_VECTOR_H #include +#include template class vector @@ -101,6 +102,8 @@ public: void push_back(const T & t); + void push_back(T && t); + void pop_back(void) { _size--; @@ -121,7 +124,7 @@ void vector::reserve(int n) T * d = (T *)malloc(_capacity * sizeof(T)); for(int i=0; i<_size; i++) { - new (d + i)T(_data[i]); + new (d + i)T(move(_data[i])); _data[i].~T(); } free(_data); @@ -160,7 +163,7 @@ void vector::shrink_to_fit(void) T * d = (T *)malloc(_capacity * sizeof(T)); for(int i=0; i<_size; i++) { - new (d + i)T(_data[i]); + new (d + i)T(move(_data[i])); _data[i].~T(); } free(_data); @@ -176,6 +179,14 @@ void vector::push_back(const T & t) new (_data + _size++)T(t); } +template +void vector::push_back(T && t) +{ + if (_size == _capacity) + reserve(_size + 1 + (_size >> 1)); + new (_data + _size++)T(t); +} + template void vector::insert(int at, const T & t) { @@ -183,7 +194,7 @@ void vector::insert(int at, const T & t) reserve(_size + 1 + (_size >> 1)); new (_data + _size)T; for(int i=_size; i>at; i--) - _data[i] = _data[i - 1]; + _data[i] = move(_data[i - 1]); _data[at] = t; } @@ -192,7 +203,7 @@ void vector::erase(int at, int n) { _size -= n; for(int i=at; i<_size; i++) - _data[i] = _data[i + n]; + _data[i] = move(_data[i + n]); _data[_size].~T(); } diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index c957ea4..36a0980 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -919,7 +919,7 @@ Declaration* Declaration::BuildConstRValueRef(const Location& loc) DecType Declaration::ValueType(void) const { - if (mType == DT_TYPE_REFERENCE || mType == DT_TYPE_RVALUEREF) + if (IsReference()) return mBase->mType; else return mType; @@ -1334,7 +1334,7 @@ bool Declaration::IsSubType(const Declaration* dec) const if (this == dec) return true; - if (mType == DT_TYPE_REFERENCE && dec->mType == DT_TYPE_REFERENCE) + if (IsReference() && dec->IsReference()) return mBase->IsSubType(dec->mBase); if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) @@ -1510,6 +1510,26 @@ bool Declaration::IsConstSame(const Declaration* dec) const return false; } +bool Declaration::IsTemplateSameParams(const Declaration* dec, const Declaration* tdec) const +{ + if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION) + { + // Skip this pointer for now + Declaration* ld = mParams->mNext, * rd = dec->mParams; + while (ld && rd) + { + if (!ld->mBase->IsTemplateSame(rd->mBase, tdec)) + return false; + ld = ld->mNext; + rd = rd->mNext; + } + + return !ld && !rd; + } + else + return false; +} + bool Declaration::IsSameParams(const Declaration* dec) const { if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION || mType == DT_TEMPLATE && dec->mType == DT_TEMPLATE) @@ -1587,7 +1607,7 @@ bool Declaration::IsSame(const Declaration* dec) const else return this->Stride() == dec->Stride() && mBase->IsSame(dec->mBase); } - else if (mType == DT_TYPE_REFERENCE) + else if (IsReference()) return mBase->IsSame(dec->mBase); else if (mType == DT_TYPE_STRUCT) return mScope == dec->mScope || (mIdent == dec->mIdent && mSize == dec->mSize); @@ -1616,6 +1636,72 @@ bool Declaration::IsSame(const Declaration* dec) const return false; } +bool Declaration::IsTemplateSame(const Declaration* dec, const Declaration * tdec) const +{ + if (dec->mType == DT_TYPE_TEMPLATE) + dec = tdec->mScope->Lookup(dec->mIdent); + + if (this == dec) + return true; + + if (mType != dec->mType) + return false; + if (mSize != dec->mSize) + return false; + if (mStripe != dec->mStripe) + return false; + + if ((mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)) != (dec->mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE))) + return false; + + if (mType == DT_TYPE_INTEGER) + return true; + else if (mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_VOID) + return true; + else if (mType == DT_TYPE_ENUM) + return mIdent == dec->mIdent; + else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) + { + if (mBase->mType == DT_TYPE_STRUCT && dec->mBase->mType == DT_TYPE_STRUCT && mBase->mStripe == dec->mBase->mStripe) + { + if (mBase->mQualIdent == dec->mBase->mQualIdent && + (mBase->mFlags & (DTF_CONST | DTF_VOLATILE)) == (dec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE))) + return true; + else + return false; + } + else + return this->Stride() == dec->Stride() && mBase->IsTemplateSame(dec->mBase, tdec); + } + else if (IsReference()) + return mBase->IsTemplateSame(dec->mBase, tdec); + else if (mType == DT_TYPE_STRUCT) + return mScope == dec->mScope || (mIdent == dec->mIdent && mSize == dec->mSize); + else if (mType == DT_TYPE_FUNCTION) + { + if (!mBase->IsTemplateSame(dec->mBase, tdec)) + return false; + Declaration* dl = mParams, * dr = dec->mParams; + while (dl && dr) + { + if (!dl->mBase->IsTemplateSame(dr->mBase, tdec)) + return false; + dl = dl->mNext; + dr = dr->mNext; + } + + if (dl || dr) + return false; + + if ((mFlags & DTF_VARIADIC) != (dec->mFlags & DTF_VARIADIC)) + return false; + + return true; + } + + return false; +} + bool Declaration::IsSameValue(const Declaration* dec) const { if (mType != dec->mType || mSize != dec->mSize) @@ -1638,9 +1724,9 @@ bool Declaration::IsSameValue(const Declaration* dec) const bool Declaration::CanAssign(const Declaration* fromType) const { - if (fromType->mType == DT_TYPE_REFERENCE) + if (fromType->IsReference()) return this->CanAssign(fromType->mBase); - if (mType == DT_TYPE_REFERENCE) + if (IsReference()) return mBase->IsSubType(fromType); if (this->IsSame(fromType)) @@ -1695,6 +1781,11 @@ bool Declaration::IsNumericType(void) const } +bool Declaration::IsReference(void) const +{ + return mType == DT_TYPE_REFERENCE || mType == DT_TYPE_RVALUEREF; +} + bool Declaration::IsSimpleType(void) const { return mType == DT_TYPE_INTEGER || mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_ENUM || mType == DT_TYPE_POINTER; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 1f1a9b0..d26e15d 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -283,9 +283,13 @@ public: bool IsSameParams(const Declaration* dec) const; bool IsSameMutable(const Declaration* dec) const; + bool IsTemplateSame(const Declaration* dec, const Declaration* tdec) const; + bool IsTemplateSameParams(const Declaration* dec, const Declaration* tdec) const; + bool IsIntegerType(void) const; bool IsNumericType(void) const; bool IsSimpleType(void) const; + bool IsReference(void) const; void SetDefined(void); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 6811f5f..cd03c94 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4532,7 +4532,8 @@ void InterCodeBasicBlock::Append(InterInstruction * code) assert(code->mConst.mVarIndex < mProc->mModule->mGlobalVars.Size()); assert(mProc->mModule->mGlobalVars[code->mConst.mVarIndex]); } - + if (code->mDst.mTemp >= 0) + assert(code->mDst.mType != IT_NONE); for (int i = 0; i < code->mNumOperands; i++) assert(code->mSrc[i].mType != IT_NONE); @@ -16748,7 +16749,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "join"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index a7fda9a..c887e95 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -34,13 +34,14 @@ static inline InterType InterTypeOf(const Declaration* dec) case DT_TYPE_FUNCTION: case DT_TYPE_ARRAY: case DT_TYPE_REFERENCE: + case DT_TYPE_RVALUEREF: return IT_POINTER; } } InterCodeGenerator::ExValue InterCodeGenerator::ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v) { - if (v.mType && v.mType->mType == DT_TYPE_REFERENCE) + if (v.mType && v.mType->IsReference()) { v.mType = v.mType->mBase; v.mReference++; @@ -81,9 +82,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p { int stemp = v.mTemp; - if (type->mType == DT_TYPE_REFERENCE) + if (type->IsReference()) { - if (v.mType->mType == DT_TYPE_REFERENCE) + if (v.mType->IsReference()) { if (!type->mBase->IsSubType(v.mType->mBase)) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Incompatible type for reference"); @@ -960,7 +961,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro vdec->mVarIndex = nindex; vdec->mBase = pdec->mBase; - if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE) + if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) ains->mConst.mOperandSize = 2; else ains->mConst.mOperandSize = pdec->mSize; @@ -992,7 +993,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, &vp); - if (!(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) + if (!(pdec && pdec->mBase->IsReference()) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) { if (pdec && !pdec->mBase->CanAssign(vr.mType)) mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); @@ -1026,7 +1027,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro { if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION) vr = Dereference(proc, texp, block, vr, 1); - else if (pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE && vr.mType->mType != DT_TYPE_REFERENCE)) + else if (pdec && (pdec->mBase->IsReference() && !vr.mType->IsReference())) vr = Dereference(proc, texp, block, vr, 1); else vr = Dereference(proc, texp, block, vr); @@ -1054,7 +1055,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro wins->mSrc[1].mTemp = ains->mDst.mTemp; if (pdec) { - if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE) + if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) wins->mSrc[1].mOperandSize = 2; else wins->mSrc[1].mOperandSize = pdec->mSize; @@ -1124,7 +1125,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro block->Append(ins); ExValue rv(rdec->mBase, ins->mDst.mTemp, 1); - if (rdec->mBase->mType != DT_TYPE_REFERENCE) + if (!rdec->mBase->IsReference()) rv = Dereference(proc, exp, block, rv); return rv; } @@ -1728,7 +1729,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!(dec->mBase->mFlags & DTF_DEFINED)) mErrors->Error(dec->mLocation, EERR_VARIABLE_TYPE, "Undefined variable type"); - if (exp->mDecType->mType == DT_TYPE_REFERENCE) + if (exp->mDecType->IsReference()) return ExValue(exp->mDecType->mBase, ins->mDst.mTemp, ref + 1); else return ExValue(exp->mDecType, ins->mDst.mTemp, ref); @@ -1743,7 +1744,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper, &vl); } - else if (exp->mType == EX_INITIALIZATION && exp->mLeft->mDecType && exp->mLeft->mDecType->mType == DT_TYPE_REFERENCE) + else if (exp->mType == EX_INITIALIZATION && exp->mLeft->mDecType && exp->mLeft->mDecType->IsReference()) { vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); @@ -1776,7 +1777,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } - if (vl.mType->mType == DT_TYPE_REFERENCE) + if (vl.mType->IsReference()) { vr = Dereference(proc, exp, block, vr, 1); vl = Dereference(proc, exp, block, vl, 2); @@ -3172,7 +3173,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ExValue vp(ptype ? ptype : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); - if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE && texp->mType == EX_CALL && texp->mDecType->mType != DT_TYPE_REFERENCE) + if (pdec && pdec->mBase->IsReference() && texp->mType == EX_CALL && !texp->mDecType->IsReference()) { mErrors->Error(texp->mLocation, EERR_MISSING_TEMP, "Missing temporary variable"); #if 0 @@ -3202,7 +3203,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, nullptr); - if (!(pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) + if (!(pdec && pdec->mBase->IsReference()) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) { if (pdec && !pdec->mBase->CanAssign(vr.mType)) mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); @@ -3244,7 +3245,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(texp->mLocation, EWARN_NUMERIC_0_USED_AS_NULLPTR, "Numeric 0 used for nullptr"); vr = CoerceType(proc, texp, block, vr, pdec->mBase); } - else if (pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE && vr.mType->mType != DT_TYPE_REFERENCE)) + else if (pdec && (pdec->mBase->IsReference() && !vr.mType->IsReference())) vr = Dereference(proc, texp, block, vr, 1); else vr = Dereference(proc, texp, block, vr); @@ -3272,7 +3273,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* wins->mSrc[1].mTemp = ains->mDst.mTemp; if (pdec) { - if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE) + if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) { wins->mSrc[1].mOperandSize = 2; wins->mSrc[0].mType = IT_POINTER; @@ -3359,7 +3360,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* return ExValue(ftype->mBase, vins->mDst.mTemp, 1); } - else if (ftype->mBase->mType == DT_TYPE_REFERENCE) + else if (ftype->mBase->IsReference()) return ExValue(ftype->mBase->mBase, cins->mDst.mTemp, 1); else return ExValue(ftype->mBase, cins->mDst.mTemp); @@ -3468,7 +3469,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RETURN); if (exp->mLeft) { - if (procType->mBase->mType == DT_TYPE_REFERENCE) + if (procType->mBase->IsReference()) { vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); @@ -4128,6 +4129,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (exp->mDecType->mType == DT_TYPE_VOID) { } + else if (exp->mDecType->IsReference() && exp->mDecType->mBase->IsConstSame(vr.mType)) + { + if (vr.mReference == 0) + mErrors->Error(exp->mLocation, EERR_NOT_AN_LVALUE, "Not an L value"); + + vr = Dereference(proc, exp, block, vr, 1); + return ExValue(exp->mDecType, vr.mTemp); + } else { vr = Dereference(proc, exp, block, vr); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index cde99e8..6c4686e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2035,7 +2035,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) adec->mOffset = 0; adec->mBase = new Declaration(mScanner->mLocation, DT_TYPE_REFERENCE); adec->mBase->mSize = 2; - adec->mBase->mBase = pthis->mBase; + adec->mBase->mBase = pthis->mBase->ToConstType(); adec->mBase->mFlags |= DTF_CONST | DTF_DEFINED; adec->mSize = adec->mBase->mSize; adec->mIdent = adec->mQualIdent = Ident::Unique("_"); @@ -4733,7 +4733,10 @@ Expression* Parser::ParseQualify(Expression* exp) { if (mflags & DTF_PROTECTED) { - if (!mThisPointer || mThisPointer->mBase->IsConstSame(dtype)) + Declaration* tp = mThisPointer; + if (tp && tp->mType == DT_ARGUMENT) + tp = tp->mBase; + if (!(tp && tp->mBase->IsConstSame(dtype))) mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", ident); } @@ -4952,6 +4955,13 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) dist += 512; else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_TYPE_STRUCT && etype->mType == DT_TYPE_STRUCT) { + if (ex->IsLValue()) + dist += 2; + else if (ptype->mBase->mFlags & DTF_CONST) + dist += 4; + else + return NOOVERLOAD; + int ncast = 0; Declaration* ext = ex->mDecType; while (ext && !ext->IsConstSame(ptype->mBase)) @@ -7379,6 +7389,8 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp if (!(mdec->mFlags & DTF_DEFINED)) { Declaration* mpdec = mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); + while (mpdec && !mdec->mBase->IsTemplateSameParams(mpdec->mBase, tdec)) + mpdec = mpdec->mNext; if (mpdec && mpdec->mTemplate) { p->ParseTemplateExpansion(mpdec->mTemplate, tdec); @@ -7411,6 +7423,8 @@ void Parser::CompleteTemplateExpansion(Declaration* tmpld) while (mdec) { Declaration* mpdec = mScope->Lookup(mdec->mQualIdent); + while (mpdec && !mpdec->IsSameParams(mdec->mParams)) + mpdec = mpdec->mNext; if (mpdec && mpdec->mType == DT_TEMPLATE) { ParseTemplateExpansion(mpdec, tmpld); @@ -7561,7 +7575,13 @@ void Parser::ParseTemplateDeclaration(void) tdec->mQualIdent = tdec->mBase->mQualIdent; tdec->mScope->mName = tdec->mQualIdent; - mScope->Insert(tdec->mQualIdent, tdec->mBase); + Declaration * pdec = mScope->Insert(tdec->mQualIdent, tdec->mBase); + if (pdec) + { + tdec->mBase->mNext = pdec->mNext; + pdec->mNext = tdec->mBase; + } + mCompilationUnits->mScope->Insert(tdec->mQualIdent, tdec->mBase); } From ae2fbb62565a88d3cb0cf8c2dbb032634cfa3781 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 14 Aug 2023 18:09:35 +0200 Subject: [PATCH 082/169] Global object initialization --- include/opp/iostream.cpp | 2 ++ include/opp/iostream.h | 2 ++ oscar64/InterCodeGenerator.cpp | 19 +++++++++++++++++++ oscar64/InterCodeGenerator.h | 3 +++ 4 files changed, 26 insertions(+) diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp index f069548..7df8992 100644 --- a/include/opp/iostream.cpp +++ b/include/opp/iostream.cpp @@ -973,3 +973,5 @@ void cistream::refill(void) } } +cistream cin; +costream cout; diff --git a/include/opp/iostream.h b/include/opp/iostream.h index 00577d8..bca344f 100644 --- a/include/opp/iostream.h +++ b/include/opp/iostream.h @@ -202,6 +202,8 @@ iosetfill setfill(char fill); ostream & operator<<(ostream & os, const iosetfill & s); +extern cistream cin; +extern costream cout; #pragma compile("iostream.cpp"); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index c887e95..1af651e 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -467,6 +467,11 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration* else mErrors->Error(dec->mLocation, EERR_INCOMPATIBLE_TYPES, "Incompatible constant initializer"); } + else if (dec->mValue->mType == EX_CONSTRUCT) + { + DestructStack* destack = nullptr; + TranslateExpression(nullptr, mMainInitProc, mMainInitBlock, dec->mValue, destack, BranchTarget(), BranchTarget(), nullptr); + } else mErrors->Error(dec->mLocation, EERR_CONSTANT_INITIALIZER, "Non constant initializer"); } @@ -4742,6 +4747,13 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod InterCodeBasicBlock* entryBlock = new InterCodeBasicBlock(proc); + if (!strcmp(proc->mIdent->mString, "main")) + { + mMainInitBlock = entryBlock; + mMainInitProc = proc; + entryBlock = new InterCodeBasicBlock(proc); + } + InterCodeBasicBlock* exitBlock = entryBlock; if (dec->mFlags & DTF_DEFINED) @@ -4781,6 +4793,13 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod TranslateExpression(dec->mBase, proc, exitBlock, exp, destack, BranchTarget(), BranchTarget(), nullptr); UnwindDestructStack(dec->mBase, proc, exitBlock, destack, nullptr, nullptr); + + if (!strcmp(proc->mIdent->mString, "main")) + { + InterInstruction* ins = new InterInstruction(proc->mLocation, IC_JUMP); + mMainInitBlock->Append(ins); + mMainInitBlock->Close(entryBlock, nullptr); + } } else mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent->mString); diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index cb4f5e2..9c48782 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -74,6 +74,9 @@ protected: typedef GrowingArray SwitchNodeArray; + InterCodeProcedure* mMainInitProc; + InterCodeBasicBlock* mMainInitBlock; + void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, InterCodeBasicBlock* dblock); ExValue ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v); From 50cc2afb52157c7be4dd8b2d900d9b38a1c0566b Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 15 Aug 2023 11:05:52 +0200 Subject: [PATCH 083/169] Add template algorithm sort --- include/opp/algorithm.h | 37 ++++++++++++ include/opp/string.cpp | 5 ++ include/opp/string.h | 4 ++ include/opp/vector.h | 30 ++++++++++ oscar64/Declaration.cpp | 26 ++++++++- oscar64/Declaration.h | 2 +- oscar64/InterCodeGenerator.cpp | 24 ++++++++ oscar64/Parser.cpp | 103 +++++++++++++++++++++++++++------ oscar64/Parser.h | 4 +- oscar64/Scanner.cpp | 3 + oscar64/Scanner.h | 1 + 11 files changed, 215 insertions(+), 24 deletions(-) create mode 100644 include/opp/algorithm.h diff --git a/include/opp/algorithm.h b/include/opp/algorithm.h new file mode 100644 index 0000000..b5586b2 --- /dev/null +++ b/include/opp/algorithm.h @@ -0,0 +1,37 @@ +#ifndef OPP_ALGORITHM_H +#define OPP_ALGORITHM_H + +template +inline void swap(T & x, T & y) +{ + T t(x); x = y; y = t; +} + +template +void sort(T s, T e) +{ + while (s != e) + { + auto p = s; + auto q = s; + + q++; + while (q != e) + { + if (LT(*q, *p)) + { + swap(*q, *p); + p++; + swap(*q, *p); + } + q++; + } + + sort(s, p); + p++; + s = p; + } +} + + +#endif diff --git a/include/opp/string.cpp b/include/opp/string.cpp index 0c5821d..a8476dd 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -16,6 +16,11 @@ static inline char sstrlen(const char * sp) return n; } +inline void swap(string & u, string & v) +{ + char * p = u.cstr; u.cstr = v.cstr; v.cstr = p; +} + string::string(void) : cstr(nullptr) {} diff --git a/include/opp/string.h b/include/opp/string.h index 856edf6..bcf58cd 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -6,6 +6,8 @@ class string private: char * cstr; + friend void swap(string & u, string & v); + public: string(void); string(const string & s); @@ -70,6 +72,8 @@ protected: string(char l, char * b); }; +void swap(string & u, string & v); + #pragma compile("string.cpp") #endif diff --git a/include/opp/vector.h b/include/opp/vector.h index 98f9e12..f5fbdde 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -70,6 +70,36 @@ public: return _data[at]; } + T * begin(void) + { + return _data; + } + + const T * begin(void) const + { + return _data; + } + + const T * cbegin(void) const + { + return _data; + } + + T * end(void) + { + return _data + _size; + } + + const T * end(void) const + { + return _data + _size; + } + + const T * cend(void) const + { + return _data + _size; + } + T & front(void) { return _data[0]; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 36a0980..255de13 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -842,7 +842,7 @@ Declaration::Declaration(const Location& loc, DecType type) mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), mVTable(nullptr), mTemplate(nullptr), - mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), + mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr) {} @@ -947,6 +947,10 @@ const Ident* Declaration::MangleIdent(void) sprintf_s(buffer, "%d", (int)mInteger); mMangleIdent = Ident::Unique(buffer); } + else if (mType == DT_CONST_FUNCTION) + { + mMangleIdent = mQualIdent; + } else if (mType == DT_TYPE_INTEGER) { char buffer[20]; @@ -1532,7 +1536,7 @@ bool Declaration::IsTemplateSameParams(const Declaration* dec, const Declaration bool Declaration::IsSameParams(const Declaration* dec) const { - if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION || mType == DT_TEMPLATE && dec->mType == DT_TEMPLATE) + if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION) { Declaration* ld = mParams, * rd = dec->mParams; while (ld && rd) @@ -1545,6 +1549,24 @@ bool Declaration::IsSameParams(const Declaration* dec) const return !ld && !rd; } + else if (mType == DT_TEMPLATE && dec->mType == DT_TEMPLATE) + { + Declaration* ld = mParams, * rd = dec->mParams; + while (ld && rd) + { + if (ld->mType == DT_CONST_FUNCTION && rd->mType == DT_CONST_FUNCTION) + { + if (ld->mValue != rd->mValue) + return false; + } + else if (!ld->mBase->IsSame(rd->mBase)) + return false; + ld = ld->mNext; + rd = rd->mNext; + } + + return !ld && !rd; + } else return false; } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index d26e15d..084d7df 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -272,7 +272,7 @@ public: TokenSequence * mTokens; Parser * mParser; - GrowingArray mCallers, mCalled; + GrowingArray mCallers, mCalled, mFriends; bool CanAssign(const Declaration* fromType) const; bool IsSame(const Declaration* dec) const; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 1af651e..2b674f2 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -162,6 +162,28 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p { mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign numeric value to pointer"); } + else if( type->mType == DT_TYPE_BOOL && v.mType->mType == DT_TYPE_POINTER) + { + InterInstruction* zins = new InterInstruction(exp->mLocation, IC_CONSTANT); + zins->mDst.mType = IT_POINTER; + zins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + zins->mConst.mType = IT_POINTER; + zins->mConst.mMemory = IM_ABSOLUTE; + zins->mConst.mIntConst = 0; + block->Append(zins); + + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); + cins->mOperator = IA_CMPNE; + cins->mSrc[0].mType = IT_POINTER; + cins->mSrc[0].mTemp = v.mTemp; + cins->mSrc[1].mType = IT_POINTER; + cins->mSrc[1].mTemp = zins->mDst.mTemp; + cins->mDst.mType = IT_BOOL; + cins->mDst.mTemp = proc->AddTemporary(IT_BOOL); + block->Append(cins); + v.mTemp = cins->mDst.mTemp; + v.mType = type; + } else if (v.mType->mSize < type->mSize) { if (v.mType->mSize == 1 && type->mSize == 2) @@ -3697,6 +3719,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID) mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Function has void return type"); + else if (procType->mBase->mType == DT_TYPE_BOOL && (vr.mType->IsIntegerType() || vr.mType->mType == DT_TYPE_POINTER)) + ; else if (!procType->mBase->CanAssign(vr.mType)) mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type"); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 6c4686e..3b94c1d 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -19,6 +19,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn mInlineCall = false; mCompilerOptionSP = 0; mThisPointer = nullptr; + mFunction = nullptr; for (int i = 0; i < 256; i++) mCharMap[i] = i; @@ -248,6 +249,13 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) flags |= DTF_PRIVATE | DTF_PROTECTED; ConsumeToken(TK_COLON); } + else if (ConsumeTokenIf(TK_FRIEND)) + { + mScope = oscope; + Declaration* fdec = ParseDeclaration(nullptr, true, false); + dec->mFriends.Push(fdec); + mScope = dec->mScope; + } else if (ConsumeTokenIf(TK_CLOSE_BRACE)) { break; @@ -3210,7 +3218,7 @@ void Parser::ParseVariableInit(Declaration* ndec) mErrors->Error(pexp->mLocation, EERR_INCOMPATIBLE_TYPES, "Can not initialize variable with expression", ndec->mIdent); } -Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis) +Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis, Declaration* ptempl) { bool definingType = false, destructor = false; uint64 storageFlags = 0, typeFlags = 0; @@ -3734,14 +3742,30 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else { - if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) - { - if (ConsumeTokenIf(TK_CONST)) - PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildConstPointer(ndec->mLocation)); - else - PrependThisArgument(ndec->mBase, pthis); + if (ptempl) + ptempl->mBase = ndec; + + if (ptempl && mTemplateScope && ndec->mIdent) + { + if (!strstr(ndec->mQualIdent->mString, mTemplateScope->mName->mString)) + { + ndec->mIdent = ndec->mIdent->Mangle(mTemplateScope->mName->mString); + ndec->mQualIdent = ndec->mQualIdent->Mangle(mTemplateScope->mName->mString); + } } + if (ndec->mBase->mType == DT_TYPE_FUNCTION) + { + if (pthis) + { + if (ConsumeTokenIf(TK_CONST)) + PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildConstPointer(ndec->mLocation)); + else + PrependThisArgument(ndec->mBase, pthis); + } + } + + if (variable) { ndec->mFlags |= storageFlags; @@ -3776,11 +3800,15 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ndec->mIdent == ndec->mQualIdent) { Declaration* ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec); +#if 0 if (ldec && ldec->mTemplate && mTemplateScope) { ndec->mQualIdent = ndec->mQualIdent->Mangle(mTemplateScope->mName->mString); } - else if (ldec && ldec != pdec) + else +#endif + + if (ldec && ldec != pdec) mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); } else if (!pdec) @@ -4085,14 +4113,16 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ndec->mBase->mType == DT_TYPE_FUNCTION) { if (ndec->mFlags & DTF_DEFINED) - mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition"); + mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition", ndec->mQualIdent); ndec->mCompilerOptions = mCompilerOptions; ndec->mBase->mCompilerOptions = mCompilerOptions; ndec->mVarIndex = -1; + mFunction = ndec; ndec->mValue = ParseFunction(ndec->mBase); + mFunction = nullptr; if (pthis) ndec->mFlags |= DTF_REQUEST_INLINE; @@ -4309,6 +4339,10 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp = new Expression(mScanner->mLocation, EX_TYPE); exp->mDecValue = nullptr; exp->mDecType = ParseBaseTypeDeclaration(0, true); + while (ConsumeTokenIf(TK_MUL)) + exp->mDecType = exp->mDecType->BuildPointer(mScanner->mLocation); + while (ConsumeTokenIf(TK_BINARY_AND)) + exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation); } break; case TK_CONST: @@ -4555,6 +4589,10 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp = new Expression(mScanner->mLocation, EX_TYPE); exp->mDecValue = nullptr; exp->mDecType = dec; + while (ConsumeTokenIf(TK_MUL)) + exp->mDecType = exp->mDecType->BuildPointer(mScanner->mLocation); + while (ConsumeTokenIf(TK_BINARY_AND)) + exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation); } } else if (dec->mType == DT_ELEMENT) @@ -4737,7 +4775,12 @@ Expression* Parser::ParseQualify(Expression* exp) if (tp && tp->mType == DT_ARGUMENT) tp = tp->mBase; if (!(tp && tp->mBase->IsConstSame(dtype))) - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", ident); + { + if (dtype->mFriends.Contains(mFunction)) + ; + else + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", ident); + } } mScanner->NextToken(); @@ -4952,7 +4995,13 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) else if (ptype->IsSame(ex->mDecType)) ; else if (CanCoerceExpression(ex, ptype)) + { dist += 512; + if (ptype->mType == DT_TYPE_REFERENCE) + dist += 4; + else if (ptype->mType == DT_TYPE_RVALUEREF) + dist += 2; + } else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_TYPE_STRUCT && etype->mType == DT_TYPE_STRUCT) { if (ex->IsLValue()) @@ -5247,7 +5296,9 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) while (fdec) { int d = OverloadDistance(fdec, exp->mRight); - if (d < ibest) + if (d == NOOVERLOAD) + ; + else if (d < ibest) { dbest = fdec; pbest = exp->mRight; @@ -5262,7 +5313,9 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) while (fdec2) { int d = OverloadDistance(fdec2, exp2->mRight); - if (d < ibest) + if (d == NOOVERLOAD) + ; + else if (d < ibest) { dbest = fdec2; pbest = exp2->mRight; @@ -6244,6 +6297,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) if (exp->mType == EX_ASSIGNMENT) { Declaration* tdec = exp->mLeft->mDecType; + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) + tdec = tdec->mBase; + if (tdec->mType == DT_TYPE_STRUCT) { const Ident* opident = nullptr; @@ -6320,7 +6376,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mLeft = exp->mLeft; texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = exp->mDecType; + texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); @@ -7138,7 +7194,10 @@ Expression* Parser::ParseStatement(void) exp = new Expression(mScanner->mLocation, EX_RETURN); if (mScanner->mToken != TK_SEMICOLON) { - exp->mLeft = CleanupExpression(ParseRExpression()); + exp->mLeft = ParseRExpression(); + if (mReturnType) + exp->mLeft = CoerceExpression(exp->mLeft, mReturnType); + exp->mLeft = CleanupExpression(exp->mLeft); if (exp->mLeft->mType == EX_CONSTRUCT && mReturnType && mReturnType->mType == DT_TYPE_STRUCT) { Expression* cexp = exp->mLeft->mLeft->mLeft; @@ -7325,8 +7384,13 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp { if (exp->mType == EX_TYPE) epdec->mBase = exp->mDecType; + else if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_FUNCTION) + epdec->mBase = exp->mDecValue; else + { mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Type parameter expected", pdec->mIdent); + epdec->mBase = TheVoidTypeDeclaration; + } } else { @@ -7367,14 +7431,13 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp p->mScanner->Replay(tmpld->mTokens); tdec->mScope->mName = tdec->MangleIdent(); - - p->mTemplateScope = tdec->mScope; - tdec->mBase = p->ParseDeclaration(nullptr, true, false); - p->mTemplateScope = nullptr; - tdec->mNext = tmpld->mNext; tmpld->mNext = tdec; + p->mTemplateScope = tdec->mScope; + tdec->mBase = p->ParseDeclaration(nullptr, true, false, nullptr, tdec); + p->mTemplateScope = nullptr; + if (tdec->mBase->mType == DT_ANON) { tdec->mBase = tdec->mBase->mBase; @@ -7533,6 +7596,8 @@ void Parser::ParseTemplateDeclaration(void) // Function template mTemplateScope = tdec->mScope; + ConsumeTokenIf(TK_INLINE); + Declaration* bdec = ParseBaseTypeDeclaration(0, false); Declaration* adec = ParsePostfixDeclaration(); diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 892c52b..2eb21bc 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -15,7 +15,7 @@ public: DeclarationScope * mGlobals, * mScope, * mTemplateScope; int mLocalIndex; CompilationUnits * mCompilationUnits; - Declaration * mThisPointer, * mReturnType; + Declaration * mThisPointer, * mReturnType, * mFunction; LinkerSection * mCodeSection, * mDataSection, * mBSSection; @@ -58,7 +58,7 @@ protected: Expression* CleanupExpression(Expression* exp); Declaration* ParseBaseTypeDeclaration(uint64 flags, bool qualified); - Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr); + Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr, Declaration * ptempl = nullptr); Declaration* ParseStructDeclaration(uint64 flags, DecType dt); Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 88e63f8..4514311 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -163,6 +163,7 @@ const char* TokenNames[] = "'virtual'", "'operator'", "'template'", + "'friend'", }; @@ -1511,6 +1512,8 @@ void Scanner::NextRawToken(void) mToken = TK_VIRTUAL; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "template")) mToken = TK_TEMPLATE; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "friend")) + mToken = TK_FRIEND; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 984fcf3..98b5756 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -162,6 +162,7 @@ enum Token TK_VIRTUAL, TK_OPERATOR, TK_TEMPLATE, + TK_FRIEND, NUM_TOKENS }; From 69b46c4b7b452f5638b2573e2beb36674125b4d8 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 15 Aug 2023 12:46:57 +0200 Subject: [PATCH 084/169] Fix namespaces for templates --- autotest/opp_array.cpp | 4 ++-- autotest/opp_streamtest.cpp | 8 +++++--- autotest/opp_string.cpp | 2 ++ autotest/opp_vector.cpp | 2 +- autotest/opp_vector_string.cpp | 3 +++ include/opp/algorithm.h | 3 +++ include/opp/array.h | 15 +++----------- include/opp/ifstream.cpp | 3 +++ include/opp/ifstream.h | 3 ++- include/opp/iostream.cpp | 4 ++++ include/opp/iostream.h | 4 ++++ include/opp/move.h | 4 ++++ include/opp/ofstream.cpp | 3 +++ include/opp/ofstream.h | 3 ++- include/opp/sstream.cpp | 4 ++++ include/opp/sstream.h | 3 +++ include/opp/string.cpp | 4 ++++ include/opp/string.h | 4 ++++ include/opp/vector.h | 3 +++ oscar64/Declaration.cpp | 5 ++++- oscar64/Declaration.h | 1 + oscar64/Parser.cpp | 36 +++++++++++++++++++++++----------- 22 files changed, 89 insertions(+), 32 deletions(-) diff --git a/autotest/opp_array.cpp b/autotest/opp_array.cpp index cf105c0..b4d0984 100644 --- a/autotest/opp_array.cpp +++ b/autotest/opp_array.cpp @@ -3,8 +3,8 @@ int main(void) { - array a10; - array a20; + opp::array a10; + opp::array a20; for(int i=0; i<10; i++) a10[i] = i; diff --git a/autotest/opp_streamtest.cpp b/autotest/opp_streamtest.cpp index 1a9bfc5..940f106 100644 --- a/autotest/opp_streamtest.cpp +++ b/autotest/opp_streamtest.cpp @@ -4,6 +4,10 @@ #include #include +using opp::ostringstream; +using opp::istringstream; +using opp::endl; + float fdist(float a, float b) { float d = fabs(a - b); @@ -21,8 +25,6 @@ int main(void) os << i << endl; } - costream cout; - istringstream is(os.str()); int j = 0, k = 47; @@ -35,7 +37,7 @@ int main(void) assert(j == 40); #endif - os.str(string()); + os.str(opp::string()); #if 0 cout << "[" << os.str() << "]" << endl; diff --git a/autotest/opp_string.cpp b/autotest/opp_string.cpp index 8df38de..bf2b789 100644 --- a/autotest/opp_string.cpp +++ b/autotest/opp_string.cpp @@ -3,6 +3,8 @@ #include #include +using opp::string; + static const char HelloWorld[] = "Hello World"; static const char AndBeyond[] = "And Beyond"; static const char And[] = "And"; diff --git a/autotest/opp_vector.cpp b/autotest/opp_vector.cpp index 91ecca3..5e82699 100644 --- a/autotest/opp_vector.cpp +++ b/autotest/opp_vector.cpp @@ -3,7 +3,7 @@ int main(void) { - vector a; + opp::vector a; for(int i=0; i<10; i++) a.push_back(i); diff --git a/autotest/opp_vector_string.cpp b/autotest/opp_vector_string.cpp index ada3f16..96642be 100644 --- a/autotest/opp_vector_string.cpp +++ b/autotest/opp_vector_string.cpp @@ -4,6 +4,9 @@ #include #include +using opp::string; +using opp::vector; + string join(const vector & vs) { string sj; diff --git a/include/opp/algorithm.h b/include/opp/algorithm.h index b5586b2..56cc828 100644 --- a/include/opp/algorithm.h +++ b/include/opp/algorithm.h @@ -1,6 +1,8 @@ #ifndef OPP_ALGORITHM_H #define OPP_ALGORITHM_H +namespace opp { + template inline void swap(T & x, T & y) { @@ -33,5 +35,6 @@ void sort(T s, T e) } } +} #endif diff --git a/include/opp/array.h b/include/opp/array.h index 0956811..33d413b 100644 --- a/include/opp/array.h +++ b/include/opp/array.h @@ -1,6 +1,7 @@ #ifndef OPP_ARRAY_H #define OPP_ARRAY_H +namespace opp { template class array @@ -109,18 +110,8 @@ public: _data[i] = t; } }; - -#if 0 - void swap(array & a) - { - for(int i=0; i +namespace opp { + ifstream::ifstream(char fnum, char device, char channel, const string & name) { this->fnum = fnum; @@ -19,3 +21,4 @@ void ifstream::refill(void) mBufferFill = krnio_read(fnum, mBuffer, 32); } +} diff --git a/include/opp/ifstream.h b/include/opp/ifstream.h index 42d59cc..6a0394e 100644 --- a/include/opp/ifstream.h +++ b/include/opp/ifstream.h @@ -4,6 +4,7 @@ #include "iostream.h" #include "string.h" +namespace opp { class ifstream : public istream { @@ -17,7 +18,7 @@ protected: char fnum; }; - +} #pragma compile("ifstream.cpp") diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp index 7df8992..5e730d2 100644 --- a/include/opp/iostream.cpp +++ b/include/opp/iostream.cpp @@ -2,6 +2,8 @@ #include #include +namespace opp { + ios::ios(void) : mFlags(0), mState(0), mWidth(0), mPrecision(6), mFill(' ') {} @@ -975,3 +977,5 @@ void cistream::refill(void) cistream cin; costream cout; + +} \ No newline at end of file diff --git a/include/opp/iostream.h b/include/opp/iostream.h index bca344f..42c0e89 100644 --- a/include/opp/iostream.h +++ b/include/opp/iostream.h @@ -3,6 +3,8 @@ #include +namespace opp { + class ios { public: @@ -205,6 +207,8 @@ ostream & operator<<(ostream & os, const iosetfill & s); extern cistream cin; extern costream cout; +} + #pragma compile("iostream.cpp"); #endif diff --git a/include/opp/move.h b/include/opp/move.h index 759781a..977fb64 100644 --- a/include/opp/move.h +++ b/include/opp/move.h @@ -1,10 +1,14 @@ #ifndef OPP_MOVE_H #define OPP_MOVE_H +namespace opp { + template T && move(T & m) { return (T &&)m; } +} + #endif diff --git a/include/opp/ofstream.cpp b/include/opp/ofstream.cpp index a447870..bbbbaaa 100644 --- a/include/opp/ofstream.cpp +++ b/include/opp/ofstream.cpp @@ -1,6 +1,8 @@ #include "ofstream.h" #include +namespace opp { + ofstream::ofstream(char fnum, char device, char channel, const string & name) { this->fnum = fnum; @@ -27,3 +29,4 @@ void ofstream::bput(char ch) } } +} diff --git a/include/opp/ofstream.h b/include/opp/ofstream.h index 65b47d9..6367fec 100644 --- a/include/opp/ofstream.h +++ b/include/opp/ofstream.h @@ -4,6 +4,7 @@ #include "iostream.h" #include "string.h" +namespace opp { class ofstream : public ostream { @@ -20,7 +21,7 @@ protected: char fnum; }; - +} #pragma compile("ofstream.cpp") diff --git a/include/opp/sstream.cpp b/include/opp/sstream.cpp index ca0ff9e..5954939 100644 --- a/include/opp/sstream.cpp +++ b/include/opp/sstream.cpp @@ -1,6 +1,8 @@ #include "sstream.h" #include +namespace opp { + ostringstream::ostringstream(void) { mBuffer = nullptr; @@ -80,3 +82,5 @@ void istringstream::refill(void) mBuffer[mBufferFill++] = mString[mSPos++]; } } + +} diff --git a/include/opp/sstream.h b/include/opp/sstream.h index 686f65a..8a0b4a7 100644 --- a/include/opp/sstream.h +++ b/include/opp/sstream.h @@ -3,6 +3,8 @@ #include "iostream.h" +namespace opp { + class ostringstream : public ostream { public: @@ -33,6 +35,7 @@ protected: char mSPos; }; +} #pragma compile("sstream.cpp") diff --git a/include/opp/string.cpp b/include/opp/string.cpp index a8476dd..cbfb8a5 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -2,6 +2,8 @@ #include #include +namespace opp { + static inline void smemcpy(char * dp, const char * sp, char s) { for(char i=0; i #include +namespace opp { + template class vector { @@ -237,4 +239,5 @@ void vector::erase(int at, int n) _data[_size].~T(); } +} #endif diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 255de13..7c5f71c 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -121,11 +121,14 @@ Declaration* DeclarationScope::Lookup(const Ident* ident, ScopeLevel limit) for (int i = 0; i < mUsed.Size(); i++) { - Declaration* dec = mUsed[i]->Lookup(ident, limit); + Declaration* dec = mUsed[i]->Lookup(ident, SLEVEL_NAMESPACE); if (dec) return dec; } + if (limit == SLEVEL_USING) + return nullptr; + return mParent ? mParent->Lookup(ident, limit) : nullptr; } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 084d7df..29a9fdb 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -118,6 +118,7 @@ class Declaration; enum ScopeLevel { SLEVEL_SCOPE, + SLEVEL_USING, SLEVEL_GLOBAL, SLEVEL_STATIC, SLEVEL_NAMESPACE, diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 3b94c1d..bcb2c02 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -166,7 +166,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) { dec->mIdent = structName; dec->mQualIdent = mScope->Mangle(structName); - dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, structName); + dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, dec->mQualIdent); } if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_COLON) @@ -607,7 +607,7 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) if (dec && dec->mTemplate) dec = ParseTemplateExpansion(dec->mTemplate, nullptr); - while (qualified && dec && dec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON)) + while (qualified && dec && (dec->mType == DT_TYPE_STRUCT || dec->mType == DT_NAMESPACE) && ConsumeTokenIf(TK_COLCOLON)) { if (ExpectToken(TK_IDENT)) { @@ -3797,7 +3797,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { pdec = mCompilationUnits->mScope->Insert(ndec->mQualIdent, ndec); - if (ndec->mIdent == ndec->mQualIdent) + if (mScope->Mangle(ndec->mIdent) == ndec->mQualIdent) { Declaration* ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec); #if 0 @@ -4290,7 +4290,7 @@ Declaration* Parser::ParseQualIdent(void) { if (dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_STRUCT) { - Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS); + Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_USING); if (ndec) dec = ndec; @@ -7451,7 +7451,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp { if (!(mdec->mFlags & DTF_DEFINED)) { - Declaration* mpdec = mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); + Declaration* mpdec = mCompilationUnits->mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); while (mpdec && !mdec->mBase->IsTemplateSameParams(mpdec->mBase, tdec)) mpdec = mpdec->mNext; if (mpdec && mpdec->mTemplate) @@ -7485,7 +7485,7 @@ void Parser::CompleteTemplateExpansion(Declaration* tmpld) { while (mdec) { - Declaration* mpdec = mScope->Lookup(mdec->mQualIdent); + Declaration* mpdec = mCompilationUnits->mScope->Lookup(mdec->mQualIdent); while (mpdec && !mpdec->IsSameParams(mdec->mParams)) mpdec = mpdec->mNext; if (mpdec && mpdec->mType == DT_TEMPLATE) @@ -7569,7 +7569,7 @@ void Parser::ParseTemplateDeclaration(void) if (mScanner->mToken == TK_IDENT) { bdec->mIdent = mScanner->mTokenIdent; - bdec->mQualIdent = mScope->Mangle(bdec->mIdent); + bdec->mQualIdent = mScope->Mangle(mScanner->mTokenIdent); while (mScanner->mToken != TK_SEMICOLON && mScanner->mToken != TK_OPEN_BRACE) mScanner->NextToken(); @@ -7631,7 +7631,12 @@ void Parser::ParseTemplateDeclaration(void) } } else + { mErrors->Error(bdec->mLocation, EERR_FUNCTION_TEMPLATE, "Function template expected"); + adec->mType = DT_TYPE_VOID; + tdec->mBase = adec; + adec->mTemplate = tdec; + } } tdec->mTokens = mScanner->CompleteRecord(); @@ -7640,14 +7645,15 @@ void Parser::ParseTemplateDeclaration(void) tdec->mQualIdent = tdec->mBase->mQualIdent; tdec->mScope->mName = tdec->mQualIdent; - Declaration * pdec = mScope->Insert(tdec->mQualIdent, tdec->mBase); + if (tdec->mQualIdent == mScope->Mangle(tdec->mIdent)) + mScope->Insert(tdec->mIdent, tdec->mBase); + + Declaration* pdec = mCompilationUnits->mScope->Insert(tdec->mQualIdent, tdec->mBase); if (pdec) { tdec->mBase->mNext = pdec->mNext; pdec->mNext = tdec->mBase; } - - mCompilationUnits->mScope->Insert(tdec->mQualIdent, tdec->mBase); } @@ -9180,8 +9186,11 @@ void Parser::ParseNamespace(void) if (!ns) { ns = new Declaration(mScanner->mLocation, DT_NAMESPACE); - mScope->Insert(ident, ns); ns->mScope = new DeclarationScope(mScope, SLEVEL_NAMESPACE, ident); + ns->mIdent = ident; + ns->mQualIdent = mScope->Mangle(ident); + + mScope->Insert(ident, ns); } mScanner->NextToken(); @@ -9198,6 +9207,11 @@ void Parser::ParseNamespace(void) } else if (mScanner->mToken == TK_SEMICOLON) mScanner->NextToken(); + else if (mScanner->mToken == TK_TEMPLATE) + { + mScanner->NextToken(); + ParseTemplateDeclaration(); + } else if (mScanner->mToken == TK_NAMESPACE) { mScanner->NextToken(); From 952d087a2ba3a82c0359c0e4c1f40a5d6f1f31b0 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 15 Aug 2023 13:16:39 +0200 Subject: [PATCH 085/169] Add using with list of names --- oscar64/Parser.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index bcb2c02..5deb802 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3256,13 +3256,20 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else { - Declaration* dec = ParseQualIdent(); - if (dec) - { - Declaration* pdec = mScope->Insert(dec->mIdent, dec); - if (pdec && pdec != dec) - mErrors->Error(dec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate declaration", dec->mIdent); - } + Declaration* dec; + + do { + dec = ParseQualIdent(); + if (dec) + { + Declaration* pdec = mScope->Insert(dec->mIdent, dec); + if (pdec && pdec != dec) + mErrors->Error(dec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate declaration", dec->mIdent); + } + else + break; + + } while (ConsumeTokenIf(TK_COMMA)); return dec; } From 82dff88ba8e16c1e4bff2dc992929d0774a392d9 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 15 Aug 2023 16:55:58 +0200 Subject: [PATCH 086/169] Added numeric conversion to opp strings --- include/opp/string.cpp | 519 ++++++++++++++++++++++++++++++++++++++++- include/opp/string.h | 16 ++ 2 files changed, 534 insertions(+), 1 deletion(-) diff --git a/include/opp/string.cpp b/include/opp/string.cpp index cbfb8a5..38256c2 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -573,4 +573,521 @@ int string::find(char c, char pos) const return -1; } -} \ No newline at end of file +string to_string(int val) +{ + char buffer[10]; + + bool sign = false; + if (val < 0) + { + val = -val; + sign = true; + } + + char i = 10; + + while (val) + { + char d = val % 10; + val /= 10; + buffer[--i] = d + '0'; + } + + if (i == 10) + buffer[--i] = '0'; + if (sign) + buffer[--i] = '-'; + + return string(buffer + i, 10 - i); +} + +string to_string(long val) +{ + char buffer[12]; + + bool sign = false; + if (val < 0) + { + val = -val; + sign = true; + } + + char i = 12; + + while (val) + { + char d = val % 10; + val /= 10; + buffer[--i] = d + '0'; + } + + if (i == 12) + buffer[--i] = '0'; + if (sign) + buffer[--i] = '-'; + + return string(buffer + i, 12 - i); +} + +string to_string(unsigned int val) +{ + char buffer[10]; + + char i = 10; + + while (val) + { + char d = val % 10; + val /= 10; + buffer[--i] = d + '0'; + } + + if (i == 10) + buffer[--i] = '0'; + + return string(buffer + i, 10 - i); +} + +string to_string(unsigned long val) +{ + char buffer[12]; + + char i = 12; + + while (val) + { + char d = val % 10; + val /= 10; + buffer[--i] = d + '0'; + } + + if (i == 12) + buffer[--i] = '0'; + + return string(buffer + i, 12 - i); +} + +static float fround5[] = { + 0.5e-0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6 +}; + +string to_string(float val) +{ + char buffer[20]; + + char d = 0; + + float f = val; + + if (f < 0.0) + { + f = -f; + buffer[d++] = '-'; + } + + char prefix = d; + + if (isinf(f)) + { + buffer[d++] = 'I'; + buffer[d++] = 'N'; + buffer[d++] = 'F'; + } + else + { + int exp = 0; + + char fdigits = 6; + + if (f != 0.0) + { + while (f >= 1000.0) + { + f /= 1000; + exp += 3; + } + + while (f < 1.0) + { + f *= 1000; + exp -= 3; + } + + while (f >= 10.0) + { + f /= 10; + exp ++; + } + + } + + char digits = fdigits + 1; + + while (exp < 0) + { + f /= 10.0; + exp++; + } + + digits = fdigits + exp + 1; + + if (digits < 7) + f += fround5[digits - 1]; + else + f += fround5[6]; + + if (f >= 10.0) + { + f /= 10.0; + fdigits--; + } + + char pdigits = digits - fdigits; + + if (digits > 20) + digits = 20; + + if (pdigits == 0) + buffer[d++] = '0'; + + for(char i=0; i 6) + buffer[d++] = '0'; + else + { + int c = (int)f; + f -= (float)c; + f *= 10.0; + buffer[d++] = c + '0'; + } + } + } + + return string(buffer, d); +} + + +int string::to_int(char * idx, char base) const +{ + char i = 1; + unsigned n = 0; + bool sign = false; + + if (cstr) + { + const char * cp = cstr; + + char ch = cp[i]; + + if (ch == '-') + { + sign = true; + ch = cp[++i]; + } + else if (ch == '+') + ch = cp[++i]; + + if (ch == '0' && base == 0) + { + ch = cp[++i]; + if (ch == 'x' || ch == 'X') + { + base = 16; + ch = cp[++i]; + } + else if (ch == 'b' || ch == 'B') + { + base = 2; + ch = cp[++i]; + } + } + + for(;;) + { + char d; + if (ch >= '0' && ch <= '9') + d = (ch - '0'); + else if (base > 10 && ch >= 'A' && ch <= 'F') + d = (ch - 'A' + 10); + else if (base > 10 && ch >= 'a' && ch <= 'f') + d = (ch - 'a' + 10); + else + break; + + n = n * base + d; + ch = cp[++i]; + } + } + + if (idx) + *idx = i - 1; + + if (sign) + return -(int)n; + else + return n; +} + +long string::to_long(char * idx, char base) const +{ + char i = 1; + unsigned long n = 0; + bool sign = false; + + if (cstr) + { + const char * cp = cstr; + + char ch = cp[i++]; + + if (ch == '-') + { + sign = true; + ch = cp[i++]; + } + else if (ch == '+') + ch = cp[i++]; + + if (ch == '0' && base == 0) + { + ch = cp[i++]; + if (ch == 'x' || ch == 'X') + { + base = 16; + ch = cp[i++]; + } + else if (ch == 'b' || ch == 'B') + { + base = 2; + ch = cp[i++]; + } + } + + for(;;) + { + char d; + if (ch >= '0' && ch <= '9') + d = (ch - '0'); + else if (base > 10 && ch >= 'A' && ch <= 'F') + d = (ch - 'A' + 10); + else if (base > 10 && ch >= 'a' && ch <= 'f') + d = (ch - 'a' + 10); + else + break; + + n = n * base + d; + ch = cp[i++]; + } + i--; + } + + if (idx) + *idx = i - 1; + + if (sign) + return -(long)n; + else + return n; +} + +unsigned string::to_uint(char * idx, char base) const +{ + char i = 1; + unsigned n = 0; + + if (cstr) + { + const char * cp = cstr; + + char ch = cp[i]; + + if (ch == '0' && base == 0) + { + ch = cp[++i]; + if (ch == 'x' || ch == 'X') + { + base = 16; + ch = cp[++i]; + } + else if (ch == 'b' || ch == 'B') + { + base = 2; + ch = cp[++i]; + } + } + + for(;;) + { + char d; + if (ch >= '0' && ch <= '9') + d = (ch - '0'); + else if (base > 10 && ch >= 'A' && ch <= 'F') + d = (ch - 'A' + 10); + else if (base > 10 && ch >= 'a' && ch <= 'f') + d = (ch - 'a' + 10); + else + break; + + n = n * base + d; + ch = cp[++i]; + } + } + + if (idx) + *idx = i - 1; + + return n; +} + +unsigned long string::to_ulong(char * idx, char base) const +{ + char i = 1; + unsigned long n = 0; + + if (cstr) + { + const char * cp = cstr; + + char ch = cp[i++]; + + if (ch == '0' && base == 0) + { + ch = cp[i++]; + if (ch == 'x' || ch == 'X') + { + base = 16; + ch = cp[i++]; + } + else if (ch == 'b' || ch == 'B') + { + base = 2; + ch = cp[i++]; + } + } + + for(;;) + { + char d; + if (ch >= '0' && ch <= '9') + d = (ch - '0'); + else if (base > 10 && ch >= 'A' && ch <= 'F') + d = (ch - 'A' + 10); + else if (base > 10 && ch >= 'a' && ch <= 'f') + d = (ch - 'a' + 10); + else + break; + + n = n * base + d; + ch = cp[i++]; + } + i--; + } + + if (idx) + *idx = i - 1; + + return n; +} + +float string::to_float(char * idx) const +{ + char i = 1; + float vf = 0; + bool sign = false; + + if (cstr) + { + const char * cp = cstr; + + char ch = cp[i++]; + if (ch == '-') + { + sign = true; + ch = cp[i++]; + } + else if (ch == '+') + ch = cp[i++]; + + if (ch >= '0' && ch <= '9' || ch == '.') + { + while (ch >= '0' && ch <= '9') + { + vf = vf * 10 + (int)(ch - '0'); + ch = cp[i++]; + } + + if (ch == '.') + { + float digits = 1.0; + ch = cp[i++]; + while (ch >= '0' && ch <= '9') + { + vf = vf * 10 + (int)(ch - '0'); + digits *= 10; + ch = cp[i++]; + } + vf /= digits; + } + + char e = 0; + bool eneg = false; + + if (ch == 'e' || ch == 'E') + { + ch = cp[i++]; + if (ch == '-') + { + eneg = true; + ch = cp[i++]; + } + else if (ch == '+') + { + ch = cp[i++]; + } + + while (ch >= '0' && ch <= '9') + { + e = e * 10 + ch - '0'; + ch = cp[i++]; + } + + } + + if (e) + { + if (eneg) + { + while (e > 6) + { + vf /= 1000000.0; + e -= 6; + } + vf /= tpow10[e]; + } + else + { + while (e > 6) + { + vf *= 1000000.0; + e -= 6; + } + vf *= tpow10[e]; + } + } + } + i--; + } + + if (idx) + *idx = i - 1; + + if (sign) + return -vf; + else + return vf; +} + +} diff --git a/include/opp/string.h b/include/opp/string.h index c08754c..35ccd47 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -70,12 +70,28 @@ public: int find(char c, char pos) const; void copyseg(char * p, char at, char num) const; + + int to_int(char * idx = nullptr, char base = 10) const; + long to_long(char * idx = nullptr, char base = 10) const; + unsigned to_uint(char * idx = nullptr, char base = 10) const; + unsigned long to_ulong(char * idx = nullptr, char base = 10) const; + float to_float(char * idx = nullptr) const; protected: string(char l, char * b); }; void swap(string & u, string & v); +string to_string(int val); + +string to_string(long val); + +string to_string(unsigned int val); + +string to_string(unsigned long val); + +string to_string(float val); + } #pragma compile("string.cpp") From b7daafcac823d959832470ea88bf6e584237f9d5 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 16 Aug 2023 16:16:04 +0200 Subject: [PATCH 087/169] Add list and iterators to opp --- include/opp/algorithm.h | 11 ++ include/opp/array.h | 2 + include/opp/iterator.h | 137 +++++++++++++++ include/opp/list.h | 286 ++++++++++++++++++++++++++++++++ include/opp/string.cpp | 1 + include/opp/vector.h | 2 + oscar64/Declaration.cpp | 17 +- oscar64/Declaration.h | 2 +- oscar64/Ident.cpp | 4 +- oscar64/InterCodeGenerator.cpp | 9 +- oscar64/NativeCodeGenerator.cpp | 2 +- oscar64/Parser.cpp | 235 +++++++++++++++----------- 12 files changed, 602 insertions(+), 106 deletions(-) create mode 100644 include/opp/iterator.h create mode 100644 include/opp/list.h diff --git a/include/opp/algorithm.h b/include/opp/algorithm.h index 56cc828..d3d692e 100644 --- a/include/opp/algorithm.h +++ b/include/opp/algorithm.h @@ -35,6 +35,17 @@ void sort(T s, T e) } } +template +OI copy(II first, II last, OI result) +{ + while (first != last) + { + *result = *first; + ++result; ++first; + } + return result; +} + } #endif diff --git a/include/opp/array.h b/include/opp/array.h index 33d413b..207e2e2 100644 --- a/include/opp/array.h +++ b/include/opp/array.h @@ -9,6 +9,8 @@ class array protected: T _data[n]; public: + typedef T element_type; + int size(void) const { return n; diff --git a/include/opp/iterator.h b/include/opp/iterator.h new file mode 100644 index 0000000..6d50174 --- /dev/null +++ b/include/opp/iterator.h @@ -0,0 +1,137 @@ +#ifndef OPP_ITERATOR_H +#define OPP_ITERATOR_H + +namespace opp +{ + +template +class back_insert_iterator +{ +protected: + CT * co; + +public: + back_insert_iterator (CT & c) : co(&c) {} + + back_insert_iterator & operator= (const CT::element_type & t) + { + co->push_back(t); + return *this; + } + + back_insert_iterator & operator= (CT::element_type && t) + { + co->push_back(t); + return *this; + } + + back_insert_iterator & operator* (void) + { + return *this; + } + + back_insert_iterator & operator++ (void) + { + return *this; + } + + back_insert_iterator operator++ (int) + { + return *this; + } +}; + +template +class front_insert_iterator +{ +protected: + CT * co; + +public: + front_insert_iterator (CT & c) : co(&c) {} + + front_insert_iterator & operator= (const CT::element_type & t) + { + co->push_front(t); + return *this; + } + + front_insert_iterator & operator= (CT::element_type && t) + { + co->push_front(t); + return *this; + } + + front_insert_iterator & operator* (void) + { + return *this; + } + + front_insert_iterator & operator++ (void) + { + return *this; + } + + front_insert_iterator operator++ (int) + { + return *this; + } +}; + +template +class insert_iterator +{ +protected: + CT * co; + CT::iterator_type ci; + +public: + insert_iterator (CT & c, const CT::iterator_type & i) : co(&c), ci(i) {} + + insert_iterator & operator= (const CT::element_type & t) + { + ci = co->insert(ci, t); ++ci; + return *this; + } + + insert_iterator & operator= (CT::element_type && t) + { + ci = co->insert(ci, t); ++ci; + return *this; + } + + insert_iterator & operator* (void) + { + return *this; + } + + insert_iterator & operator++ (void) + { + return *this; + } + + insert_iterator operator++ (int) + { + return *this; + } +}; + +template +front_insert_iterator front_inserter (CT & c) +{ + return front_insert_iterator(c); +} + +template +back_insert_iterator back_inserter (CT & c) +{ + return back_insert_iterator(c); +} + +template +insert_iterator inserter (CT & c, const CI & i) +{ + return insert_iterator(c, i); +} + +} diff --git a/include/opp/list.h b/include/opp/list.h new file mode 100644 index 0000000..00b0a20 --- /dev/null +++ b/include/opp/list.h @@ -0,0 +1,286 @@ +#ifndef OPP_LIST +#define OPP_LIST + +namespace opp +{ + +template +class listnode +{ +public: + listnode * succ, * pred; + T data; + + listnode() + { + succ = this; + pred = this; + } + + listnode(const T & t) : data(t) {} + listnode(T && t) : data(t) {} +}; + +template +class list_iterator +{ +public: + listnode * node; +public: + list_iterator(void) : node(nullptr) {} + list_iterator(listnode * n) : node(n) {} + list_iterator(const list_iterator & li) : node(li.node) {} + list_iterator & operator=(const list_iterator & li) + { + node = li.node; + return *this; + } + + T & operator*() + { + return node->data; + } + + list_iterator & operator++(void) + { + node = node->succ; + return *this; + } + + list_iterator operator++(int) + { + listnode * n = node; + node = node->succ; + return list_iterator(n); + } + + list_iterator & operator+=(int n) + { + while (n--) + node = node->succ; + return *this; + } + + list_iterator & operator--(void) + { + node = node->pred; + return *this; + } + + list_iterator operator++(int) + { + listnode * n = node; + node = node->pred; + return list_iterator(n); + } + + list_iterator & operator-=(int n) + { + while (n--) + node = node->pred; + return *this; + } + + bool operator==(const list_iterator & li) + { + return node == li.node; + } + + bool operator!=(const list_iterator & li) + { + return node != li.node; + } + +}; + + +template +class list +{ +private: + listnode node; +public: + typedef T element_type; + typedef list_iterator iterator_type; + + list(void) + {} + + ~list(void) + { + listnode * n = node.succ; + while (n != &node) + { + listnode * m = n->succ; + delete n; + n = m; + } + } + + list_iterator begin(void) + { + return list_iterator(node.succ); + } + + list_iterator end(void) + { + return list_iterator(&node); + } + + T & front(void) + { + return node.succ->data; + } + + const T & front(void) const + { + return node.succ->data; + } + + T & back(void) + { + return node.pred->data; + } + + const T & back(void) const + { + return node.pred->data; + } + + list_iterator erase(list_iterator it); + + list_iterator erase(list_iterator first, list_iterator last); + + void pop_front(void); + + void pop_back(void); + + void push_front(const T & t); + + void push_front(T && t); + + void push_back(const T & t); + + void push_back(T && t); + + list_iterator insert(list_iterator it, const T & t); + + list_iterator insert(list_iterator it, T && t); +}; + +template +void list::pop_front(void) +{ + listnode * n = node.succ; + node.succ = n->succ; + n->succ->pred = &node; + delete n; +} + +template +void list::pop_back(void) +{ + listnode * n = node.pred; + node.pred = n->pred; + n->pred->succ = &node; + delete n; +} + +template +void list::push_front(const T & t) +{ + listnode * n = new listnode(t); + n->pred = &node; + n->succ = node.succ; + node.succ->pred = n; + node.succ = n; +} + +template +void list::push_front(T && t) +{ + listnode * n = new listnode(t); + n->pred = &node; + n->succ = node.succ; + node.succ->pred = n; + node.succ = n; +} + +template +void list::push_back(const T & t) +{ + listnode * n = new listnode(t); + n->succ = &node; + n->pred = node.pred; + node.pred->succ = n; + node.pred = n; +} + +template +void list::push_back(T && t) +{ + listnode * n = new listnode(t); + n->succ = &node; + n->pred = node.pred; + node.pred->succ = n; + node.pred = n; +} + + +template +list_iterator list::erase(list_iterator it) +{ + listnode * n = it.node; + listnode * s = n->succ; + + n->succ->pred = n->pred; + n->pred->succ = n->succ; + delete n; + + return list_iterator(s); +} + +template +list_iterator list::erase(list_iterator first, list_iterator last) +{ + listnode * n = first.node; + listnode * s = last.node; + + n->pred->succ = s; + s->pred = n->pred; + + while (n != s) + { + listnode * m = n->succ; + delete n; + n = m; + } + + return list_iterator(s); +} + +template +list_iterator list::insert(list_iterator it, const T & t) +{ + listnode * n = new listnode(t); + n->succ = it.node; + n->pred = it.node->pred; + it.node->pred->succ = n; + it.node->pred = n; + return list_iterator(n); +} + +template +list_iterator list::insert(list_iterator it, T && t) +{ + listnode * n = new listnode(t); + n->succ = it.node; + n->pred = it.node->pred; + it.node->pred->succ = n; + it.node->pred = n; + return list_iterator(n); +} + +} + +#endif diff --git a/include/opp/string.cpp b/include/opp/string.cpp index 38256c2..e9de1c7 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -1,6 +1,7 @@ #include "string.h" #include #include +#include namespace opp { diff --git a/include/opp/vector.h b/include/opp/vector.h index dde075e..07bd2d2 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -13,6 +13,8 @@ protected: T * _data; int _size, _capacity; public: + typedef T element_type; + vector(void) : _data(nullptr), _size(0), _capacity(0) {} vector(int n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n) { diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 7c5f71c..6cdabfe 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -203,7 +203,7 @@ void Expression::Dump(int ident) const printf("INDEX"); break; case EX_QUALIFY: - printf("QUALIFY"); + printf("QUALIFY<%s>", mDecValue->mIdent->mString); break; case EX_CALL: printf("CALL"); @@ -991,7 +991,9 @@ const Ident* Declaration::MangleIdent(void) Declaration* dec = mParams; while (dec) { - mMangleIdent = mMangleIdent->Mangle(dec->mBase->MangleIdent()->mString); + const Ident* id = dec->mBase->MangleIdent(); + if (id) + mMangleIdent = mMangleIdent->Mangle(id->mString); dec = dec->mNext; if (dec) mMangleIdent = mMangleIdent->Mangle(","); @@ -1663,20 +1665,29 @@ bool Declaration::IsSame(const Declaration* dec) const bool Declaration::IsTemplateSame(const Declaration* dec, const Declaration * tdec) const { + uint64 dflags = dec->mFlags; + if (dec->mType == DT_TYPE_TEMPLATE) + { dec = tdec->mScope->Lookup(dec->mIdent); + dflags |= dec->mFlags; + } if (this == dec) return true; if (mType != dec->mType) return false; + + if (dec->mType == DT_TYPE_STRUCT && dec->mTemplate) + return true; + if (mSize != dec->mSize) return false; if (mStripe != dec->mStripe) return false; - if ((mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)) != (dec->mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE))) + if ((mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)) != (dflags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE))) return false; if (mType == DT_TYPE_INTEGER) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 29a9fdb..12e4d72 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -24,10 +24,10 @@ enum DecType DT_TYPE_ARRAY, DT_TYPE_STRUCT, DT_TYPE_UNION, + DT_TYPE_TEMPLATE, DT_TYPE_FUNCTION, DT_TYPE_ASSEMBLER, DT_TYPE_AUTO, - DT_TYPE_TEMPLATE, DT_TYPE_CONST, DT_TYPE_VOLATILE, diff --git a/oscar64/Ident.cpp b/oscar64/Ident.cpp index 29e89f6..9bd9e5c 100644 --- a/oscar64/Ident.cpp +++ b/oscar64/Ident.cpp @@ -47,7 +47,7 @@ const Ident* Ident::Unique(const char* str) const Ident* Ident::PreMangle(const char* str) const { - char buffer[100]; + char buffer[200]; strcpy_s(buffer, str); strcat_s(buffer, mString); return Unique(buffer); @@ -55,7 +55,7 @@ const Ident* Ident::PreMangle(const char* str) const const Ident* Ident::Mangle(const char* str) const { - char buffer[100]; + char buffer[200]; strcpy_s(buffer, mString); strcat_s(buffer, str); return Unique(buffer); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 2b674f2..ce7a70f 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1152,7 +1152,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro block->Append(ins); ExValue rv(rdec->mBase, ins->mDst.mTemp, 1); - if (!rdec->mBase->IsReference()) + if (!rdec->mBase->IsReference() && rdec->mBase->mType != DT_TYPE_STRUCT) rv = Dereference(proc, exp, block, rv); return rv; } @@ -3274,6 +3274,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else if (pdec && (pdec->mBase->IsReference() && !vr.mType->IsReference())) vr = Dereference(proc, texp, block, vr, 1); + else if (vr.mType->IsReference() && !(pdec && pdec->mBase->IsReference())) + { + vr.mReference++; + vr = Dereference(proc, texp, block, vr); + } else vr = Dereference(proc, texp, block, vr); @@ -4706,7 +4711,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, "join")) + if (proc->mIdent && !strcmp(proc->mIdent->mString, "opp::insert_iterator>::+insert_iterator")) exp->Dump(0); #endif #if 0 diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 9fdf5f6..d0964bf 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -29989,7 +29989,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc } mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; } - else if (j > i && !(mIns[i + 0].mLive & LIVE_MEM) && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && !mExitRequiredRegs[mIns[i + 1].mAddress]) + else if (j > i && !(mIns[i + 0].mLive & LIVE_MEM) && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && !mExitRequiredRegs[mIns[i + 1].mAddress] && !ReferencesZeroPage(mIns[i + 0].mAddress, 0, i)) { int j = mIns.Size() - 1; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 5deb802..80982a5 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -263,81 +263,83 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) else { Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis); - - mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED); - - mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent); - - int offset = dec->mSize; - if (dt == DT_TYPE_UNION) - offset = 0; - - if (mdec->mBase->mType == DT_TYPE_FUNCTION) + if (mdec) { - if (mdec->mBase->mFlags & DTF_VIRTUAL) - needVTable = true; + mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED); - mdec->mType = DT_CONST_FUNCTION; - mdec->mSection = mCodeSection; - mdec->mFlags |= DTF_GLOBAL; - mdec->mBase->mFlags |= DTF_FUNC_THIS; + mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent); - if (mCompilerOptions & COPT_NATIVE) - mdec->mFlags |= DTF_NATIVE; + int offset = dec->mSize; + if (dt == DT_TYPE_UNION) + offset = 0; - AddMemberFunction(dec, mdec); - } - else if ((mCompilerOptions & COPT_CPLUSPLUS) && mdec->mType == DT_ANON) - { - ConsumeToken(TK_SEMICOLON); - // anon element - } - else - { - while (mdec) + if (mdec->mBase->mType == DT_TYPE_FUNCTION) { - if (!(mdec->mBase->mFlags & DTF_DEFINED)) - mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); + if (mdec->mBase->mFlags & DTF_VIRTUAL) + needVTable = true; - if (mdec->mType != DT_VARIABLE) - { - mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected"); - break; - } + mdec->mType = DT_CONST_FUNCTION; + mdec->mSection = mCodeSection; + mdec->mFlags |= DTF_GLOBAL; + mdec->mBase->mFlags |= DTF_FUNC_THIS; - mdec->mType = DT_ELEMENT; - mdec->mOffset = offset; + if (mCompilerOptions & COPT_NATIVE) + mdec->mFlags |= DTF_NATIVE; - offset += mdec->mBase->mSize; - if (offset > dec->mSize) - dec->mSize = offset; - - if (dec->mScope->Insert(mdec->mIdent, mdec)) - mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); - - if (dec->mConst) - { - Declaration* cmdec = mdec->Clone(); - cmdec->mBase = mdec->mBase->ToConstType(); - - dec->mConst->mScope->Insert(cmdec->mIdent, cmdec); - dec->mConst->mSize = dec->mSize; - } - - if (mlast) - mlast->mNext = mdec; - else - dec->mParams = mdec; - mlast = mdec; - mdec = mdec->mNext; + AddMemberFunction(dec, mdec); + } + else if ((mCompilerOptions & COPT_CPLUSPLUS) && mdec->mType == DT_ANON) + { + ConsumeToken(TK_SEMICOLON); + // anon element } - - if (mScanner->mToken == TK_SEMICOLON) - mScanner->NextToken(); else { - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); - break; + while (mdec) + { + if (!(mdec->mBase->mFlags & DTF_DEFINED)) + mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); + + if (mdec->mType != DT_VARIABLE) + { + mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected"); + break; + } + + mdec->mType = DT_ELEMENT; + mdec->mOffset = offset; + + offset += mdec->mBase->mSize; + if (offset > dec->mSize) + dec->mSize = offset; + + if (dec->mScope->Insert(mdec->mIdent, mdec)) + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + + if (dec->mConst) + { + Declaration* cmdec = mdec->Clone(); + cmdec->mBase = mdec->mBase->ToConstType(); + + dec->mConst->mScope->Insert(cmdec->mIdent, cmdec); + dec->mConst->mSize = dec->mSize; + } + + if (mlast) + mlast->mNext = mdec; + else + dec->mParams = mdec; + mlast = mdec; + mdec = mdec->mNext; + } + + if (mScanner->mToken == TK_SEMICOLON) + mScanner->NextToken(); + else + { + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); + break; + } } } } @@ -606,52 +608,55 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) if (dec && dec->mTemplate) dec = ParseTemplateExpansion(dec->mTemplate, nullptr); + } + else + mScanner->NextToken(); - while (qualified && dec && (dec->mType == DT_TYPE_STRUCT || dec->mType == DT_NAMESPACE) && ConsumeTokenIf(TK_COLCOLON)) + while (qualified && dec && (dec->mType == DT_TYPE_STRUCT || dec->mType == DT_NAMESPACE) && ConsumeTokenIf(TK_COLCOLON)) + { + if (ExpectToken(TK_IDENT)) { - if (ExpectToken(TK_IDENT)) - { - pident = mScanner->mTokenIdent; - dec = dec->mScope->Lookup(mScanner->mTokenIdent); - mScanner->NextToken(); - } + pident = mScanner->mTokenIdent; + dec = dec->mScope->Lookup(mScanner->mTokenIdent); + mScanner->NextToken(); } + } - if (dec && dec->mType <= DT_TYPE_FUNCTION) + if (dec && dec->mType <= DT_TYPE_FUNCTION) + { + if ((flags & ~dec->mFlags) == DTF_CONST) + dec = dec->ToConstType(); + else if (dec->IsSimpleType() && (flags & ~dec->mFlags)) { - if (dec->IsSimpleType() && (flags & ~dec->mFlags)) + Declaration* ndec = new Declaration(dec->mLocation, dec->mType); + ndec->mFlags = dec->mFlags | flags; + ndec->mSize = dec->mSize; + ndec->mBase = dec->mBase; + dec = ndec; + } + else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) + { + if ((flags & ~dec->mFlags) == DTF_CONST) + dec = dec->ToConstType(); + else { Declaration* ndec = new Declaration(dec->mLocation, dec->mType); ndec->mFlags = dec->mFlags | flags; ndec->mSize = dec->mSize; ndec->mBase = dec->mBase; + ndec->mScope = dec->mScope; + ndec->mParams = dec->mParams; + ndec->mIdent = dec->mIdent; + ndec->mQualIdent = dec->mQualIdent; dec = ndec; } - else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) - { - if ((flags & ~dec->mFlags) == DTF_CONST) - dec = dec->ToConstType(); - else - { - Declaration* ndec = new Declaration(dec->mLocation, dec->mType); - ndec->mFlags = dec->mFlags | flags; - ndec->mSize = dec->mSize; - ndec->mBase = dec->mBase; - ndec->mScope = dec->mScope; - ndec->mParams = dec->mParams; - ndec->mIdent = dec->mIdent; - ndec->mQualIdent = dec->mQualIdent; - dec = ndec; - } - } } - else if (!dec) - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); - else - mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); } + else if (!dec) + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); else - mScanner->NextToken(); + mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); + break; case TK_ENUM: @@ -989,7 +994,7 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) } else { - if (!(adec->mBase->mFlags & DTF_DEFINED) && adec->mBase->mType != DT_TYPE_ARRAY) + if (!(adec->mBase->mFlags & DTF_DEFINED) && adec->mBase->mType != DT_TYPE_ARRAY && !adec->mBase->mTemplate) mErrors->Error(adec->mLocation, EERR_UNDEFINED_OBJECT, "Type of argument not defined"); adec->mType = DT_ARGUMENT; @@ -2173,6 +2178,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) else { mexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + mexp->mToken = TK_ASSIGN; mexp->mLeft = lexp; mexp->mRight = rexp; mexp->mDecType = lexp->mDecType; @@ -5397,6 +5403,12 @@ Expression* Parser::ParsePostfixExpression(bool lhs) { Expression * pexp = nullptr; + if (exp->mDecType->mTemplate) + { + mErrors->Error(mScanner->mLocation, EERR_TEMPLATE_PARAMS, "Missing template parameters", exp->mDecType->mQualIdent); + exp->mDecType = TheConstVoidTypeDeclaration; + } + mScanner->NextToken(); if (mScanner->mToken != TK_CLOSE_PARENTHESIS) { @@ -6012,6 +6024,10 @@ Expression* Parser::ParsePrefixExpression(bool lhs) return nexp->mLeft; nexp->mDecType = nexp->mLeft->mDecType->mBase; } + else if ((mCompilerOptions & COPT_CPLUSPLUS) && nexp->mLeft->mDecType->mType == DT_TYPE_STRUCT) + { + nexp->mDecType = nexp->mLeft->mDecType; + } else { mErrors->Error(nexp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Pointer or array type expected"); @@ -7370,10 +7386,16 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp { tdec->mParams = expd->mParams; Declaration* dec = tdec->mParams; + Declaration* xdec = tmpld->mParams; while (dec) { - tdec->mScope->Insert(dec->mIdent, dec->mBase); + if (dec->mBase->mType == DT_TYPE_TEMPLATE) + { + printf("oopsi"); + } + tdec->mScope->Insert(xdec->mIdent, dec->mBase); dec = dec->mNext; + xdec = xdec->mNext; } } else @@ -7433,6 +7455,21 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp } else { + Declaration* epdec = tdec->mParams; + while (epdec && epdec->mBase->mType != DT_TYPE_TEMPLATE) + epdec = epdec->mNext; + + if (epdec) + { + // Partial template specification + Declaration * bdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT); + tdec->mBase = bdec; + bdec->mTemplate = tdec; + bdec->mBase = tmpld->mBase; + + return bdec; + } + Parser* p = tmpld->mParser; p->mScanner->Replay(tmpld->mTokens); @@ -7614,6 +7651,9 @@ void Parser::ParseTemplateDeclaration(void) if (adec->mBase->mType == DT_TYPE_FUNCTION) { + if (ConsumeTokenIf(TK_CONST)) + adec->mBase->mFlags |= DTF_CONST; + adec->mType = DT_CONST_FUNCTION; adec->mSection = mCodeSection; @@ -7642,6 +7682,7 @@ void Parser::ParseTemplateDeclaration(void) mErrors->Error(bdec->mLocation, EERR_FUNCTION_TEMPLATE, "Function template expected"); adec->mType = DT_TYPE_VOID; tdec->mBase = adec; + adec->mIdent = adec->mQualIdent = Ident::Unique("_"); adec->mTemplate = tdec; } } From 0440f0ef19912fadeddb54268f67878b388b145f Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 17 Aug 2023 14:55:43 +0200 Subject: [PATCH 088/169] More template support --- include/opp/iostream.cpp | 14 +++-- include/opp/iterator.h | 4 +- include/opp/vector.h | 17 ++++++ include/stdio.c | 2 +- oscar64/Declaration.cpp | 17 +++++- oscar64/GlobalAnalyzer.cpp | 27 ++++++++- oscar64/GlobalAnalyzer.h | 1 + oscar64/InterCode.cpp | 101 +++++++++++++++++++++++++++++++- oscar64/InterCode.h | 10 ++-- oscar64/InterCodeGenerator.cpp | 14 ++++- oscar64/NativeCodeGenerator.cpp | 2 +- oscar64/Parser.cpp | 42 +++++++++---- 12 files changed, 218 insertions(+), 33 deletions(-) diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp index 5e730d2..1faabed 100644 --- a/include/opp/iostream.cpp +++ b/include/opp/iostream.cpp @@ -253,10 +253,11 @@ void ostream::numput(unsigned n, char sign) if (mFlags & uppercase) o = 'A' - 10; - while (n) + unsigned nt = n; + while (nt) { - char d = n % base; - n /= base; + char d = nt % base; + nt /= base; if (d < 10) d += '0'; @@ -289,10 +290,11 @@ void ostream::numput(unsigned long n, char sign) if (mFlags & uppercase) o = 'A' - 10; - while (n) + unsigned long nt = n; + while (nt) { - char d = n % base; - n /= base; + char d = nt % base; + nt /= base; if (d < 10) d += '0'; diff --git a/include/opp/iterator.h b/include/opp/iterator.h index 6d50174..2cedc75 100644 --- a/include/opp/iterator.h +++ b/include/opp/iterator.h @@ -128,8 +128,8 @@ back_insert_iterator back_inserter (CT & c) return back_insert_iterator(c); } -template -insert_iterator inserter (CT & c, const CI & i) +template +insert_iterator inserter (CT & c, const CT::iterator_type & i) { return insert_iterator(c, i); } diff --git a/include/opp/vector.h b/include/opp/vector.h index 07bd2d2..30c8013 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -16,11 +16,28 @@ public: typedef T element_type; vector(void) : _data(nullptr), _size(0), _capacity(0) {} + vector(int n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n) { for(int i=0; iPreMangle("enum "); } + else if (mType == DT_TYPE_VOID) + { + mMangleIdent = Ident::Unique("void"); + } else if (mType == DT_TEMPLATE) { mMangleIdent = Ident::Unique("<"); @@ -1151,7 +1155,18 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) } else if (tdec->mType == DT_TYPE_TEMPLATE) { - Declaration* pdec = mScope->Insert(tdec->mIdent, fdec); + Declaration* pdec; + if (tdec->mBase) + { + pdec = mScope->Lookup(tdec->mBase->mIdent); + if (!pdec) + return false; + if (pdec->mType == DT_TYPE_STRUCT) + pdec = pdec->mScope->Lookup(tdec->mIdent); + } + else + pdec = mScope->Insert(tdec->mIdent, fdec); + if (pdec && !pdec->IsSame(fdec)) return false; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 479330f..558af40 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -220,7 +220,7 @@ void GlobalAnalyzer::AutoInline(void) { pdec->mVarIndex = dec->mNumVars++; - Expression* aexp = new Expression(pdec->mLocation, EX_ASSIGNMENT); + Expression* aexp = new Expression(pdec->mLocation, EX_INITIALIZATION); Expression* pexp = new Expression(pdec->mLocation, EX_VARIABLE); Expression* lexp = new Expression(dec->mLocation, EX_SEQUENCE); @@ -476,6 +476,27 @@ void GlobalAnalyzer::CheckInterrupt(void) } while (changed); } +bool GlobalAnalyzer::IsStackParam(const Declaration* pdec) const +{ + if (pdec->mType == DT_TYPE_STRUCT) + { + if (pdec->mSize > 4) + return true; + if (pdec->mCopyConstructor) + { + if (!((mCompilerOptions & COPT_OPTIMIZE_INLINE) && (pdec->mCopyConstructor->mFlags & DTF_REQUEST_INLINE))) + return true; + } + if (pdec->mDestructor) + { + if (!((mCompilerOptions & COPT_OPTIMIZE_INLINE) && (pdec->mDestructor->mFlags & DTF_REQUEST_INLINE))) + return true; + } + } + + return false; +} + void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) { dec->mUseCount++; @@ -495,7 +516,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) Declaration* pdec = dec->mBase->mParams; while (pdec) { - if (pdec->mBase->mType == DT_TYPE_STRUCT && (pdec->mBase->mCopyConstructor || pdec->mBase->mDestructor)) + if (IsStackParam(pdec->mBase)) dec->mBase->mFlags |= DTF_STACKCALL; pdec = pdec->mNext; } @@ -802,7 +823,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo RegisterCall(procDec, pdec->mBase->mCopyConstructor); } - if (pex->mType == EX_CALL && pex->mDecType->mType == DT_TYPE_STRUCT && !(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; if (pdec) diff --git a/oscar64/GlobalAnalyzer.h b/oscar64/GlobalAnalyzer.h index 7b8570d..ddcfad7 100644 --- a/oscar64/GlobalAnalyzer.h +++ b/oscar64/GlobalAnalyzer.h @@ -34,6 +34,7 @@ protected: Declaration* Analyze(Expression* exp, Declaration* procDec, bool lhs); + bool IsStackParam(const Declaration* pdec) const; bool MarkCycle(Declaration* rootDec, Declaration* procDec); uint64 GetProcFlags(Declaration* to) const; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index cd03c94..aa32b2c 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -11156,6 +11156,43 @@ void InterCodeBasicBlock::RemoveNonRelevantStatics(void) } } +bool InterCodeBasicBlock::RecheckOuterFrame(void) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* ins(mInstructions[i]); + if (ins->mCode == IC_LOAD) + { + if (ins->mSrc[0].mMemory == IM_FRAME) + return true; + } + else if (ins->mCode == IC_STORE || ins->mCode == IC_LEA) + { + if (ins->mSrc[1].mMemory == IM_FRAME) + return true; + } + else if (ins->mCode == IC_CONSTANT) + { + if (ins->mConst.mType == IT_POINTER && ins->mConst.mMemory == IM_FRAME) + return true; + } + else if (ins->mCode == IC_PUSH_FRAME) + return true; + } + + if (mTrueJump && mTrueJump->RecheckOuterFrame()) + return true; + if (mFalseJump && mFalseJump->RecheckOuterFrame()) + return true; + } + + return false; +} + void InterCodeBasicBlock::CollectOuterFrame(int level, int& size, bool &inner, bool &inlineAssembler, bool &byteCodeCall) { int i; @@ -11352,6 +11389,44 @@ bool InterCodeBasicBlock::IsEqual(const InterCodeBasicBlock* block) const return false; } +bool InterCodeBasicBlock::PreventsCallerStaticStack(void) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* ins(mInstructions[i]); + if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE) + { + if (ins->mSrc[0].mTemp >= 0 || !ins->mSrc[0].mLinkerObject) + return false; + else if (ins->mSrc[0].mLinkerObject == mProc->mLinkerObject) + ; // Simple recursion + else if (!(ins->mSrc[0].mLinkerObject->mFlags & LOBJF_STATIC_STACK)) + return false; + } + else if (ins->mCode == IC_DISPATCH) + { + for (int j = 0; j < mProc->mCalledFunctions.Size(); j++) + { + if (!(mProc->mCalledFunctions[j]->mLinkerObject && (mProc->mCalledFunctions[j]->mLinkerObject->mFlags & LOBJF_STATIC_STACK))) + return false; + } + } + } + + if (mTrueJump && mTrueJump->PreventsCallerStaticStack()) + return true; + if (mFalseJump && mFalseJump->PreventsCallerStaticStack()) + return true; + } + + return false; +} + + bool InterCodeBasicBlock::CheckStaticStack(void) { if (!mVisited) @@ -11368,7 +11443,13 @@ bool InterCodeBasicBlock::CheckStaticStack(void) return false; } else if (mInstructions[i]->mCode == IC_DISPATCH) - return false; + { + for (int j = 0; j < mProc->mCalledFunctions.Size(); j++) + { + if (!(mProc->mCalledFunctions[j]->mLinkerObject && (mProc->mCalledFunctions[j]->mLinkerObject->mFlags & LOBJF_STATIC_STACK))) + return false; + } + } } if (mTrueJump && !mTrueJump->CheckStaticStack()) @@ -12571,6 +12652,8 @@ static int FindStore(InterCodeBasicBlock* block, int pos, const InterOperand& op op.mVarIndex == ins->mSrc[1].mVarIndex) return pos; } + if (ins->mCode == IC_POP_FRAME && op.mMemory == IM_PARAM) + return -1; } return -1; @@ -17592,6 +17675,13 @@ void InterCodeProcedure::Close(void) mLinkerObject->mFlags |= LOBJF_STATIC_STACK; } + if (!(mLinkerObject->mFlags & LOBJF_STATIC_STACK)) + { + ResetVisited(); + if (!mEntryBlock->PreventsCallerStaticStack()) + mLinkerObject->mFlags |= LOBJF_STATIC_STACK; + } + if (!mEntryBlock->mTrueJump) { int nconst = 0, nvariables = 0, nparams = 0, ncalls = 0, nret = 0, nother = 0, nops = 0; @@ -17668,7 +17758,14 @@ void InterCodeProcedure::Close(void) mLoadsIndirect = false; mReferencedGlobals.Reset(mModule->mGlobalVars.Size()); mModifiedGlobals.Reset(mModule->mGlobalVars.Size()); - +#if 1 + if (!mLeafProcedure && mCommonFrameSize > 0) + { + ResetVisited(); + if (!mEntryBlock->RecheckOuterFrame()) + mCommonFrameSize = 0; + } +#endif ResetVisited(); mEntryBlock->CollectGlobalReferences(mReferencedGlobals, mModifiedGlobals, mStoresIndirect, mLoadsIndirect, mGlobalsChecked); } diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 1049569..0f4b4f8 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -60,16 +60,16 @@ extern int InterTypeSize[]; enum InterMemory { IM_NONE, - IM_PARAM, + IM_PARAM, // Memory used to access parameters on stack IM_LOCAL, IM_GLOBAL, - IM_FRAME, + IM_FRAME, // Memory used to pass parameters on stack IM_PROCEDURE, IM_INDIRECT, IM_TEMPORARY, IM_ABSOLUTE, - IM_FPARAM, - IM_FFRAME, + IM_FPARAM, // Memory used to access parameters in zp + IM_FFRAME, // Memory used to pass parameters in zp }; enum InterOperator @@ -488,8 +488,10 @@ public: void MapVariables(GrowingVariableArray& globalVars, GrowingVariableArray& localVars); void CollectOuterFrame(int level, int& size, bool& inner, bool& inlineAssembler, bool& byteCodeCall); + bool RecheckOuterFrame(void); bool IsLeafProcedure(void); + bool PreventsCallerStaticStack(void); bool ForwardDiamondMovedTemp(void); bool ForwardLoopMovedTemp(void); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index ce7a70f..e4d6c1a 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1018,7 +1018,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro ExValue vp(pdec ? pdec->mBase : TheSignedIntTypeDeclaration, ains->mDst.mTemp, 1); - vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, &vp); + if (pdec && (pdec->mBase->mType == DT_TYPE_STRUCT || pdec->mBase->mType == DT_TYPE_UNION)) + vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, &vp); + else + vr = TranslateExpression(procType, proc, block, texp, destack, breakBlock, continueBlock, inlineMapper, nullptr); if (!(pdec && pdec->mBase->IsReference()) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) { @@ -1056,6 +1059,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro vr = Dereference(proc, texp, block, vr, 1); else if (pdec && (pdec->mBase->IsReference() && !vr.mType->IsReference())) vr = Dereference(proc, texp, block, vr, 1); + else if (vr.mType->IsReference() && !(pdec && pdec->mBase->IsReference())) + { + vr.mReference++; + vr = Dereference(proc, texp, block, vr); + } else vr = Dereference(proc, texp, block, vr); @@ -4710,8 +4718,8 @@ 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, "opp::insert_iterator>::+insert_iterator")) +#if 1 + if (proc->mIdent && !strcmp(proc->mIdent->mString, "dividers")) exp->Dump(0); #endif #if 0 diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index d0964bf..9c83f53 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -40784,7 +40784,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "dump>"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 80982a5..ce6bce8 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -612,12 +612,22 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) else mScanner->NextToken(); - while (qualified && dec && (dec->mType == DT_TYPE_STRUCT || dec->mType == DT_NAMESPACE) && ConsumeTokenIf(TK_COLCOLON)) + 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; - dec = dec->mScope->Lookup(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(); } } @@ -1851,6 +1861,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true; bool inlineDestructor = true; bool inlineConstructor = true; + bool inlineCopy = true; const Ident* dtorident = pthis->mBase->mIdent->PreMangle("~");; @@ -1904,7 +1915,11 @@ void Parser::AddDefaultConstructors(Declaration* pthis) inlineConstructor = false; } if (bcdec->mBase->mCopyConstructor) + { simpleCopy = false; + if (!(bcdec->mBase->mCopyConstructor->mBase->mFlags & DTF_REQUEST_INLINE)) + inlineCopy = false; + } if (bcdec->mBase->mCopyAssignment) simpleAssignment = false; bcdec = bcdec->mNext; @@ -2061,6 +2076,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + if (inlineCopy) + cdec->mFlags |= DTF_REQUEST_INLINE; cdec->mSection = mCodeSection; @@ -2254,7 +2271,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* thisexp = new Expression(mScanner->mLocation, EX_PREFIX); thisexp->mToken = TK_MUL; - thisexp->mDecType = pthis->mBase; + thisexp->mDecType = pthis->mBase->ToMutableType(); thisexp->mLeft = pthisexp; cdec->mValue = new Expression(mScanner->mLocation, EX_RETURN); @@ -4547,6 +4564,8 @@ Expression* Parser::ParseSimpleExpression(bool lhs) dexp->mDecType = texp->mDecType->mBase; dexp->mLeft = texp; + dexp = dexp->ConstantFold(mErrors); + exp = ParseQualify(dexp); } else @@ -4742,6 +4761,8 @@ Expression* Parser::ParseQualify(Expression* exp) { Declaration* dtype = exp->mDecType; + exp = exp->ConstantFold(mErrors); + if (dtype->mType == DT_TYPE_REFERENCE || dtype->mType == DT_TYPE_RVALUEREF) dtype = dtype->mBase; @@ -6403,7 +6424,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp; + lexp->mLeft = texp->ConstantFold(mErrors); lexp->mRight = nexp->mRight; nexp->mRight = lexp; @@ -6446,7 +6467,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp; + lexp->mLeft = texp->ConstantFold(mErrors); lexp->mRight = nexp->mRight; nexp->mRight = lexp; @@ -6495,7 +6516,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mBase = exp->mLeft->mDecType; texp->mDecType->mSize = 2; - nexp->mRight = texp; + nexp->mRight = texp->ConstantFold(mErrors); nexp = ResolveOverloadCall(nexp); nexp->mDecType = nexp->mLeft->mDecType->mBase; @@ -6544,7 +6565,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp; + lexp->mLeft = texp->ConstantFold(mErrors); lexp->mRight = new Expression(nexp->mLocation, EX_CONSTANT); lexp->mRight->mDecType = TheSignedIntTypeDeclaration; lexp->mRight->mDecValue = new Declaration(nexp->mLocation, DT_CONST_INTEGER); @@ -6660,7 +6681,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp; + lexp->mLeft = texp->ConstantFold(mErrors); lexp->mRight = nexp->mRight; nexp->mRight = lexp; @@ -6719,7 +6740,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; - nexp->mRight = texp; + nexp->mRight = texp->ConstantFold(mErrors); nexp = ResolveOverloadCall(nexp); nexp->mDecType = nexp->mLeft->mDecType->mBase; @@ -6758,7 +6779,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; - nexp->mRight = texp; + nexp->mRight = texp->ConstantFold(mErrors); nexp = ResolveOverloadCall(nexp); nexp->mDecType = nexp->mLeft->mDecType->mBase; @@ -7614,6 +7635,7 @@ void Parser::ParseTemplateDeclaration(void) { bdec->mIdent = mScanner->mTokenIdent; bdec->mQualIdent = mScope->Mangle(mScanner->mTokenIdent); + bdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, bdec->mQualIdent); while (mScanner->mToken != TK_SEMICOLON && mScanner->mToken != TK_OPEN_BRACE) mScanner->NextToken(); From 3a9cd85072bd64bd9442168f710ec1bf6c938b7f Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 18 Aug 2023 13:13:39 +0200 Subject: [PATCH 089/169] Optimize simple const ref to value in functions --- oscar64/Compiler.cpp | 3 ++ oscar64/Declaration.cpp | 4 +- oscar64/Declaration.h | 5 +- oscar64/GlobalAnalyzer.cpp | 44 ++++++++++++++++++ oscar64/GlobalAnalyzer.h | 1 + oscar64/InterCode.cpp | 17 +++++++ oscar64/InterCodeGenerator.cpp | 15 ++++-- oscar64/InterCodeGenerator.h | 2 +- oscar64/Linker.cpp | 81 ++++++++++++++++++++++++++++++++- oscar64/Linker.h | 7 ++- oscar64/NativeCodeGenerator.cpp | 44 +++++++++++++++--- oscar64/Parser.cpp | 5 +- 12 files changed, 210 insertions(+), 18 deletions(-) diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 7bf5ee2..cdda4f9 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -955,6 +955,9 @@ bool Compiler::GenerateCode(void) for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++) mLinker->ReferenceObject(mCompilationUnits->mReferenced[i]->mLinkerObject); + if (mCompilerOptions & COPT_OPTIMIZE_BASIC) + mLinker->CombineSameConst(); + if (mCompilerOptions & COPT_VERBOSE) printf("Link executable\n"); diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 390b5d9..4b00406 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -842,7 +842,7 @@ Declaration::Declaration(const Location& loc, DecType type) mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), mMutable(nullptr), - mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), + mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), mVTable(nullptr), mTemplate(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr), @@ -1311,6 +1311,7 @@ Declaration* Declaration::ToConstType(void) ndec->mDefaultConstructor = mDefaultConstructor; ndec->mCopyConstructor = mCopyConstructor; + ndec->mMoveConstructor = mMoveConstructor; ndec->mVectorConstructor = mVectorConstructor; ndec->mVectorCopyConstructor = mVectorCopyConstructor; ndec->mVTable = mVTable; @@ -1341,6 +1342,7 @@ Declaration* Declaration::ToMutableType(void) ndec->mDefaultConstructor = mDefaultConstructor; ndec->mCopyConstructor = mCopyConstructor; + ndec->mMoveConstructor = mMoveConstructor; ndec->mVectorConstructor = mVectorConstructor; ndec->mVectorCopyConstructor = mVectorCopyConstructor; ndec->mVTable = mVTable; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 12e4d72..0a9adc7 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -106,8 +106,9 @@ 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_FUNC_THIS = (1ULL << 42); +static const uint64 DTF_FUNC_THIS = (1ULL << 43); static const uint64 DTF_VAR_ALIASING = (1ULL << 48); @@ -255,7 +256,7 @@ public: DecType mType; Token mToken; Declaration * mBase, * mParams, * mNext, * mPrev, * mConst, * mMutable; - Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment; + Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment, * mMoveConstructor, * mMoveAssignment; Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; Declaration * mVTable, * mClass, * mTemplate; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 558af40..da869c5 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -497,6 +497,21 @@ bool GlobalAnalyzer::IsStackParam(const Declaration* pdec) const return false; } +void GlobalAnalyzer::UndoParamReference(Expression* exp, Declaration * param) +{ + if (exp) + { + if (exp->mType == EX_VARIABLE) + { + if (exp->mDecValue == param) + exp->mDecType = param->mBase; + } + + UndoParamReference(exp->mLeft, param); + UndoParamReference(exp->mRight, param); + } +} + void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) { dec->mUseCount++; @@ -535,6 +550,22 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) dec->mFlags |= DTF_FUNC_CONSTEXPR; dec->mFlags |= DTF_FUNC_PURE; Analyze(exp, dec, false); + + Declaration* pdec = dec->mBase->mParams; + int vi = 0; + while (pdec) + { + 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)) + { + pdec->mBase = pdec->mBase->mBase; + pdec->mSize = pdec->mBase->mSize; + vi += pdec->mSize - 2; + + UndoParamReference(exp, pdec); + } + pdec = pdec->mNext; + } } else mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent); @@ -672,6 +703,9 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo } else { + if (lhs) + exp->mDecValue->mFlags |= DTF_VAR_ADDRESS; + if (!(exp->mDecValue->mFlags & DTF_ANALYZED)) { procDec->mLocalSize += exp->mDecValue->mSize; @@ -819,6 +853,11 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo if (pdec && pdec->mBase->mType == DT_TYPE_STRUCT && pdec->mBase->mCopyConstructor) { + if (pdec->mBase->mMoveConstructor) + { + AnalyzeProcedure(pdec->mBase->mMoveConstructor->mValue, pdec->mBase->mMoveConstructor); + RegisterCall(procDec, pdec->mBase->mMoveConstructor); + } AnalyzeProcedure(pdec->mBase->mCopyConstructor->mValue, pdec->mBase->mCopyConstructor); RegisterCall(procDec, pdec->mBase->mCopyConstructor); } @@ -846,6 +885,11 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo RegisterProc(Analyze(exp->mLeft, procDec, false)); if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor) { + if (procDec->mBase->mBase->mMoveConstructor) + { + AnalyzeProcedure(procDec->mBase->mBase->mMoveConstructor->mValue, procDec->mBase->mBase->mMoveConstructor); + RegisterCall(procDec, procDec->mBase->mBase->mMoveConstructor); + } AnalyzeProcedure(procDec->mBase->mBase->mCopyConstructor->mValue, procDec->mBase->mBase->mCopyConstructor); RegisterCall(procDec, procDec->mBase->mBase->mCopyConstructor); } diff --git a/oscar64/GlobalAnalyzer.h b/oscar64/GlobalAnalyzer.h index ddcfad7..882d731 100644 --- a/oscar64/GlobalAnalyzer.h +++ b/oscar64/GlobalAnalyzer.h @@ -40,5 +40,6 @@ protected: uint64 GetProcFlags(Declaration* to) const; void RegisterCall(Declaration* from, Declaration* to); void RegisterProc(Declaration* to); + void UndoParamReference(Expression* ex, Declaration* param); }; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index aa32b2c..5d6d5bb 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -3422,6 +3422,22 @@ bool InterInstruction::PropagateConstTemps(const GrowingInstructionPtrArray& cte } } break; + case IC_FREE: + { + if (mSrc[0].mTemp >= 0 && ctemps[mSrc[0].mTemp]) + { + InterInstruction* ains = ctemps[mSrc[0].mTemp]; + + if (ains->mConst.mMemory == IM_ABSOLUTE && ains->mConst.mIntConst == 0) + { + mCode = IC_NONE; + mNumOperands = 0; + return true; + } + } + + } break; + case IC_CONVERSION_OPERATOR: case IC_UNARY_OPERATOR: { @@ -15990,6 +16006,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mID = mModule->mProcedures.Size(); mModule->mProcedures.Push(this); mLinkerObject->mProc = this; + mLinkerObject->mFlags |= LOBJF_CONST; mCallerSavedTemps = BC_REG_TMP_SAVED - BC_REG_TMP; } diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index e4d6c1a..4ada98e 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1172,14 +1172,17 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro return ExValue(TheVoidTypeDeclaration); } -void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper) +void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving) { if (vr.mTemp == vl.mTemp) return; - if (vl.mType->mCopyConstructor) + if (vl.mType->mCopyConstructor || moving && vl.mType->mMoveConstructor) { Declaration* ccdec = vl.mType->mCopyConstructor; + if (moving && vl.mType->mMoveConstructor) + ccdec = vl.mType->mMoveConstructor; + if (!ccdec->mLinkerObject) this->TranslateProcedure(proc->mModule, ccdec->mValue, ccdec); @@ -3250,7 +3253,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vp.mTemp != vr.mTemp) { - CopyStruct(proc, exp, block, vp, vr, inlineMapper); + CopyStruct(proc, exp, block, vp, vr, inlineMapper, false); #if 0 InterInstruction* cins = new InterInstruction(texp->mLocation, IC_COPY); cins->mSrc[0].mType = IT_POINTER; @@ -3627,7 +3630,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (vr.mReference != 1) mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Non addressable object"); - CopyStruct(proc, exp, block, rvr, vr, inlineMapper); + 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, rvr, vr, inlineMapper, moving); #if 0 if (procType->mBase->mCopyConstructor) { @@ -4718,7 +4723,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 1 +#if 0 if (proc->mIdent && !strcmp(proc->mIdent->mString, "dividers")) exp->Dump(0); #endif diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 9c48782..ac637a2 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -85,7 +85,7 @@ protected: ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper); ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp); - void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper); + void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving); void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom, InlineMapper* inlineMapper); void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable); diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index f5f1e94..05d803a 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -28,6 +28,21 @@ void LinkerSection::AddObject(LinkerObject* obj) obj->mSection = this; } +bool LinkerReference::operator==(const LinkerReference& ref) +{ + return + mFlags == ref.mFlags && + mOffset == ref.mOffset && + mRefOffset == ref.mRefOffset && + mObject->mMapID == ref.mObject->mMapID && + mRefObject->mMapID == ref.mRefObject->mMapID; +} + +bool LinkerReference::operator!=(const LinkerReference& ref) +{ + return !(*this == ref); +} + LinkerObject::LinkerObject(void) : mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr) {} @@ -263,7 +278,7 @@ LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, L { LinkerObject* obj = new LinkerObject; obj->mLocation = location; - obj->mID = mObjects.Size(); + obj->mID = obj->mMapID = mObjects.Size(); obj->mType = type; obj->mData = nullptr; obj->mSize = 0; @@ -278,6 +293,70 @@ LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, L return obj; } +void Linker::CombineSameConst(void) +{ + bool changed = true; + while (changed) + { + changed = false; + + for (int i = 0; i < mObjects.Size(); i++) + { + LinkerObject* dobj(mObjects[i]); + while (dobj->mMapID != mObjects[dobj->mMapID]->mMapID) + dobj->mMapID = mObjects[dobj->mMapID]->mMapID; + + if ((dobj->mFlags & LOBJF_REFERENCED) && (dobj->mFlags & LOBJF_CONST) && dobj->mMapID == dobj->mID) + { + for (int j = i + 1; j < mObjects.Size(); j++) + { + LinkerObject* sobj(mObjects[j]); + + if ((sobj->mFlags & LOBJF_REFERENCED) && (sobj->mFlags & LOBJF_CONST) && sobj->mMapID == sobj->mID) + { + if (dobj->mSize == sobj->mSize && dobj->mSection == sobj->mSection && dobj->mReferences.Size() == sobj->mReferences.Size()) + { + int i = 0; + while (i < sobj->mSize && sobj->mData[i] == dobj->mData[i]) + i++; + if (i == sobj->mSize) + { + i = 0; + while (i < sobj->mReferences.Size() && sobj->mReferences[i] == dobj->mReferences[i]) + i++; + if (i == sobj->mReferences.Size()) + { + sobj->mMapID = dobj->mMapID; + changed = true; + if (dobj->mIdent && sobj->mIdent) + { + printf("Match %s : %s\n", dobj->mIdent->mString, sobj->mIdent->mString); + } + } + } + } + } + } + } + } + } + + for (int i = 0; i < mObjects.Size(); i++) + { + LinkerObject* lobj(mObjects[i]); + if (lobj->mFlags & LOBJF_REFERENCED) + { + if (lobj->mMapID != lobj->mID) + lobj->mFlags &= ~LOBJF_REFERENCED; + else + { + for (int j = 0; j < lobj->mReferences.Size(); j++) + lobj->mReferences[j]->mRefObject = mObjects[lobj->mReferences[j]->mRefObject->mMapID]; + } + } + } +} + void Linker::CollectReferences(void) { for (int i = 0; i < mObjects.Size(); i++) diff --git a/oscar64/Linker.h b/oscar64/Linker.h index a230e3f..364c3c8 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -110,6 +110,10 @@ public: LinkerObject* mObject, * mRefObject; int mOffset, mRefOffset; uint32 mFlags; + + bool operator==(const LinkerReference& ref); + bool operator!=(const LinkerReference& ref); + }; static const uint32 LSECF_PACKED = 0x00000001; @@ -175,7 +179,7 @@ public: Location mLocation; const Ident * mIdent; LinkerObjectType mType; - int mID; + int mID, mMapID; int mAddress, mRefAddress; int mSize, mAlignment; LinkerSection * mSection; @@ -281,6 +285,7 @@ public: void ReferenceObject(LinkerObject* obj); void CollectReferences(void); + void CombineSameConst(void); void Link(void); protected: NativeCodeDisassembler mNativeDisassembler; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 9c83f53..498bf74 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -14050,6 +14050,10 @@ bool NativeCodeBasicBlock::CombineSameXtoY(int xpos, int ypos, int end) { ReplaceXRegWithYReg(xpos, ypos); ReplaceXRegWithYReg(ypos + 1, end); + + for (int i = xpos; i < ypos; i++) + mIns[i].mLive |= LIVE_CPU_REG_Y; + if (!(mIns[ypos].mLive & LIVE_CPU_REG_Z)) { mIns[ypos].mType = ASMIT_NOP; @@ -14063,6 +14067,9 @@ bool NativeCodeBasicBlock::CombineSameXtoY(int xpos, int ypos, int end) if (CanCombineSameXtoY(xpos, end)) { ReplaceXRegWithYReg(xpos, end); + for (int i = ypos; i < xpos; i++) + mIns[i].mLive |= LIVE_CPU_REG_Y; + if (!(mIns[xpos].mLive & LIVE_CPU_REG_Z)) { mIns[xpos].mType = ASMIT_NOP; @@ -14085,6 +14092,10 @@ bool NativeCodeBasicBlock::CombineSameYtoX(int xpos, int ypos, int end) { ReplaceYRegWithXReg(ypos, xpos); ReplaceYRegWithXReg(xpos + 1, end); + + for (int i = ypos; i < xpos; i++) + mIns[i].mLive |= LIVE_CPU_REG_X; + if (!(mIns[xpos].mLive & LIVE_CPU_REG_Z)) { mIns[xpos].mType = ASMIT_NOP; @@ -14098,6 +14109,9 @@ bool NativeCodeBasicBlock::CombineSameYtoX(int xpos, int ypos, int end) if (CanCombineSameYtoX(ypos, end)) { ReplaceYRegWithXReg(ypos, end); + for (int i = xpos; i < ypos; i++) + mIns[i].mLive |= LIVE_CPU_REG_X; + if (!(mIns[ypos].mLive & LIVE_CPU_REG_Z)) { mIns[ypos].mType = ASMIT_NOP; @@ -14139,6 +14153,7 @@ bool NativeCodeBasicBlock::CombineSameXY(void) changed = true; yreg = -1; } + CheckLive(); } xreg = -1; @@ -14155,6 +14170,7 @@ bool NativeCodeBasicBlock::CombineSameXY(void) changed = true; xreg = -1; } + CheckLive(); } yreg = -1; @@ -25067,6 +25083,9 @@ bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at) { if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress) { + if (mIns[j].mLive & LIVE_CPU_REG_Y) + return false; + mIns[at + 1].mLive |= mIns[j].mLive; mIns[at + 2].mLive |= mIns[j].mLive; @@ -25079,8 +25098,18 @@ bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at) return true; } - if (mIns[j].ReferencesYReg()) + if (mIns[j].mMode == ASMIM_INDIRECT_Y && mIns[j].mAddress == mIns[at + 2].mAddress) + { + if (j > 0 && mIns[j - 1].mType == ASMIT_LDY && mIns[j - 1].mMode == ASMIM_IMMEDIATE && mIns[j - 1].mAddress != mIns[at + 1].mAddress) + ; + else + return false; + } + else if (mIns[at + 2].MayBeSameAddress(mIns[j])) return false; + else if (mIns[j].mType == ASMIT_JSR) + return false; + if (mIns[j].ChangesZeroPage(mIns[at].mAddress)) return false; if (mIns[j].ChangesZeroPage(mIns[at + 2].mAddress)) @@ -33644,6 +33673,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass bool changed = RemoveNops(); + mIns.Reserve(mIns.Size() * 2 + 32); + mVisited = true; CheckLive(); @@ -33768,7 +33799,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass } } CheckLive(); - #endif #if 1 @@ -35822,6 +35852,10 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass { mIns[i + 0].mType = ASMIT_LDY; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + if (mIns[i + 1].ChangesYReg()) + { + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + } mIns[i + 0].mLive |= LIVE_CPU_REG_Y; mIns[i + 1].mLive |= LIVE_CPU_REG_Y; progress = true; @@ -37951,8 +37985,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass // Flip arguments of ADC if second parameter in accu at entry mIns[i + 3].CopyMode(mIns[i + 2]); - mIns[i + 2].mMode = ASMIM_ZERO_PAGE; - mIns[i + 2].mAddress = mIns[i + 0].mAddress; + mIns[i + 2].CopyMode(mIns[i + 0]); progress = true; } @@ -40784,7 +40817,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "dump>"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "test_pab50"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -42120,7 +42153,6 @@ void NativeCodeProcedure::Optimize(void) } while (changed); - #if 1 ResetVisited(); mEntryBlock->ReduceLocalYPressure(); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index ce6bce8..e6e9f60 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1858,10 +1858,11 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc) void Parser::AddDefaultConstructors(Declaration* pthis) { - bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true; + bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true, simpleMove = true; bool inlineDestructor = true; bool inlineConstructor = true; bool inlineCopy = true; + bool inlineMove = true; const Ident* dtorident = pthis->mBase->mIdent->PreMangle("~");; @@ -1879,6 +1880,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis) pthis->mBase->mDefaultConstructor = cdec; else if (!tparam->mNext && tparam->mBase->mType == DT_TYPE_REFERENCE && pthis->mBase->IsConstSame(tparam->mBase->mBase)) pthis->mBase->mCopyConstructor = cdec; + else if (!tparam->mNext && tparam->mBase->mType == DT_TYPE_RVALUEREF && pthis->mBase->IsConstSame(tparam->mBase->mBase)) + pthis->mBase->mMoveConstructor = cdec; cdec = cdec->mNext; } From 8dc37e9ab2028a945d1b44c90c859359e4b9b4da Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 18 Aug 2023 23:03:15 +0200 Subject: [PATCH 090/169] Mangling function types in template expansion --- include/opp/algorithm.h | 26 ++++ include/opp/bidxlist.h | 207 ++++++++++++++++++++++++++++++++ include/opp/list.h | 86 +++++++------ oscar64/Declaration.cpp | 52 +++++++- oscar64/InterCode.cpp | 78 +++++++++++- oscar64/InterCode.h | 2 + oscar64/InterCodeGenerator.cpp | 4 +- oscar64/NativeCodeGenerator.cpp | 110 ++++++++++++++++- oscar64/Parser.cpp | 68 +++++++++-- oscar64/Parser.h | 4 +- oscar64/Scanner.cpp | 4 + 11 files changed, 582 insertions(+), 59 deletions(-) create mode 100644 include/opp/bidxlist.h diff --git a/include/opp/algorithm.h b/include/opp/algorithm.h index d3d692e..b1d8807 100644 --- a/include/opp/algorithm.h +++ b/include/opp/algorithm.h @@ -35,6 +35,32 @@ void sort(T s, T e) } } +template +void sort(T s, T e, LF lt) +{ + while (s != e) + { + auto p = s; + auto q = s; + + q++; + while (q != e) + { + if (lt(*q, *p)) + { + swap(*q, *p); + p++; + swap(*q, *p); + } + q++; + } + + sort(s, p, lt); + p++; + s = p; + } +} + template OI copy(II first, II last, OI result) { diff --git a/include/opp/bidxlist.h b/include/opp/bidxlist.h new file mode 100644 index 0000000..064f9a4 --- /dev/null +++ b/include/opp/bidxlist.h @@ -0,0 +1,207 @@ +#ifndef OPP_BIDXLIST_H +#ifndef OPP_BIDXLIST_H + +template +class bindexlist +{ +public: + char _free; + char _pred[n], _succ[n]; + T _data[n]; + + class iterator + { + public: + bindexlist * _l; + char _i; + + iterator(void) : _l(nullptr) {} + iterator(bindexlist * l, char i) + : _l(l), _i(i) {} + + iterator(const iterator & li) : _l(li._l), _i(li._i) {} + iterator & operator=(const iterator & li) + { + _l = li._l; + _i = li._i; + return *this; + } + + T & operator*() + { + return _l->_data[_i]; + } + + T * operator->() + { + return _l->_data + _i; + } + + iterator & operator++(void) + { + _i = _l->_succ[_i]; + return *this; + } + + iterator operator++(int) + { + char i = _i; + _i = _l->_succ[_i]; + return bindexlist::iterator(_l, i); + } + + iterator & operator+=(char n) + { + while (n--) + _i = _l->_succ[_i]; + return *this; + } + + iterator & operator--(void) + { + _i = _l->_pred[_i]; + return *this; + } + + iterator operator++(int) + { + char i = _i; + _i = _l->_pred[_i]; + return bindexlist::iterator(_l, i); + } + + iterator & operator-=(char n) + { + while (n--) + _i = _l->_pred[_i]; + return *this; + } + + bool operator==(const iterator & li) + { + return _i == li._i; + } + + bool operator!=(const iterator & li) + { + return _i != li._i; + } + }; + +public: + typedef T element_type; + typedef iterator iterator_type; + + bindexlist(void) + { + _succ[0] = 0; + _pred[0] = 0; + for(char i=1; i -class listnode +class listhead { public: - listnode * succ, * pred; - T data; + listnode * succ, * pred; - listnode() + listhead() { - succ = this; - pred = this; + succ = (listnode *)this; + pred = (listnode *)this; } +}; + +template +class listnode : public listhead +{ +public: + T data; listnode(const T & t) : data(t) {} listnode(T && t) : data(t) {} @@ -41,6 +47,11 @@ public: return node->data; } + T * operator->() + { + return &(node->data); + } + list_iterator & operator++(void) { node = node->succ; @@ -98,7 +109,8 @@ template class list { private: - listnode node; + typedef listnode ln; + listhead head; public: typedef T element_type; typedef list_iterator iterator_type; @@ -108,8 +120,8 @@ public: ~list(void) { - listnode * n = node.succ; - while (n != &node) + listnode * n = head.succ; + while (n != &head) { listnode * m = n->succ; delete n; @@ -119,32 +131,32 @@ public: list_iterator begin(void) { - return list_iterator(node.succ); + return list_iterator(head.succ); } list_iterator end(void) { - return list_iterator(&node); + return list_iterator((listnode *)&head); } T & front(void) { - return node.succ->data; + return head.succ->data; } const T & front(void) const { - return node.succ->data; + return head.succ->data; } T & back(void) { - return node.pred->data; + return head.pred->data; } const T & back(void) const { - return node.pred->data; + return head.pred->data; } list_iterator erase(list_iterator it); @@ -171,18 +183,18 @@ public: template void list::pop_front(void) { - listnode * n = node.succ; - node.succ = n->succ; - n->succ->pred = &node; + listnode * n = head.succ; + head.succ = n->succ; + n->succ->pred = (listnode *)&head; delete n; } template void list::pop_back(void) { - listnode * n = node.pred; - node.pred = n->pred; - n->pred->succ = &node; + listnode * n = head.pred; + head.pred = n->pred; + n->pred->succ = (listnode *)&head; delete n; } @@ -190,40 +202,40 @@ template void list::push_front(const T & t) { listnode * n = new listnode(t); - n->pred = &node; - n->succ = node.succ; - node.succ->pred = n; - node.succ = n; + n->pred = (listnode *)&head; + n->succ = head.succ; + head.succ->pred = n; + head.succ = n; } template void list::push_front(T && t) { listnode * n = new listnode(t); - n->pred = &node; - n->succ = node.succ; - node.succ->pred = n; - node.succ = n; + n->pred = (listnode *)&head; + n->succ = head.succ; + head.succ->pred = n; + head.succ = n; } template void list::push_back(const T & t) { listnode * n = new listnode(t); - n->succ = &node; - n->pred = node.pred; - node.pred->succ = n; - node.pred = n; + n->succ = (listnode *)&head; + n->pred = head.pred; + head.pred->succ = n; + head.pred = n; } template void list::push_back(T && t) { listnode * n = new listnode(t); - n->succ = &node; - n->pred = node.pred; - node.pred->succ = n; - node.pred = n; + n->succ = (listnode *)&head; + n->pred = head.pred; + head.pred->succ = n; + head.pred = n; } diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 4b00406..6a8995b 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -954,6 +954,20 @@ const Ident* Declaration::MangleIdent(void) { mMangleIdent = mQualIdent; } + else if (mType == DT_TYPE_FUNCTION) + { + mMangleIdent = mBase->MangleIdent(); + mMangleIdent = mMangleIdent->Mangle("(*)("); + Declaration* dec = mParams; + while (dec) + { + mMangleIdent = mMangleIdent->Mangle(dec->mBase->MangleIdent()->mString); + dec = dec->mNext; + if (dec) + mMangleIdent = mMangleIdent->Mangle(","); + } + mMangleIdent = mMangleIdent->Mangle(")"); + } else if (mType == DT_TYPE_INTEGER) { char buffer[20]; @@ -964,6 +978,10 @@ const Ident* Declaration::MangleIdent(void) { mMangleIdent = Ident::Unique("float"); } + else if (mType == DT_TYPE_BOOL) + { + mMangleIdent = Ident::Unique("bool"); + } else if (mType == DT_TYPE_REFERENCE) { mMangleIdent = mBase->MangleIdent()->PreMangle("&"); @@ -1172,6 +1190,36 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) return true; } + else if (tdec->mType == DT_TYPE_STRUCT && fdec->mType == DT_TYPE_STRUCT && tdec->mTemplate) + { + Declaration *ftdec = tdec->mTemplate; + while (ftdec) + { + if (ftdec->mBase == fdec) + { + Declaration* fpdec = ftdec->mParams; + Declaration* tpdec = tdec->mTemplate->mParams; + + while (fpdec) + { + if (tpdec->mBase->mType == DT_TYPE_TEMPLATE || tpdec->mBase->mType == DT_CONST_TEMPLATE) + { + Declaration * pdec = mScope->Insert(tpdec->mIdent, fpdec->mBase); + if (pdec && !pdec->IsSame(fpdec->mBase)) + return false; + } + + fpdec = fpdec->mNext; + tpdec = tpdec->mNext; + } + + return true; + } + + ftdec = ftdec->mNext; + } + return false; + } else return tdec->CanAssign(fdec); } @@ -1632,7 +1680,9 @@ bool Declaration::IsSame(const Declaration* dec) const if ((mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)) != (dec->mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE))) return false; - if (mType == DT_TYPE_INTEGER) + if (mType == DT_CONST_INTEGER) + return mInteger == dec->mInteger; + else if (mType == DT_TYPE_INTEGER) return true; else if (mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_VOID) return true; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 5d6d5bb..e38ea70 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4548,6 +4548,10 @@ void InterCodeBasicBlock::Append(InterInstruction * code) assert(code->mConst.mVarIndex < mProc->mModule->mGlobalVars.Size()); assert(mProc->mModule->mGlobalVars[code->mConst.mVarIndex]); } + if (code->mCode == IC_STORE) + { + assert(code->mSrc[1].mOperandSize > 0); + } if (code->mDst.mTemp >= 0) assert(code->mDst.mType != IT_NONE); for (int i = 0; i < code->mNumOperands; i++) @@ -7484,7 +7488,28 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray if (s0 < 0) { mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst); + mTrueValueRange[s1].LimitMinWeak(SignedTypeMin(mInstructions[sz - 2]->mSrc[1].mType)); mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1); + mFalseValueRange[s1].LimitMaxWeak(SignedTypeMax(mInstructions[sz - 2]->mSrc[1].mType)); + } + else if (s1 < 0) + { + mTrueValueRange[s0].LimitMin(mInstructions[sz - 2]->mSrc[1].mIntConst); + mTrueValueRange[s0].LimitMaxWeak(SignedTypeMax(mInstructions[sz - 2]->mSrc[0].mType)); + mFalseValueRange[s0].LimitMax(mInstructions[sz - 2]->mSrc[1].mIntConst - 1); + mFalseValueRange[s0].LimitMinWeak(SignedTypeMin(mInstructions[sz - 2]->mSrc[0].mType)); + } + else + { + if (mLocalValueRange[s0].mMaxState == IntegerValueRange::S_BOUND) + mFalseValueRange[s1].LimitMin(mLocalValueRange[s0].mMinValue + 1); + if (mLocalValueRange[s0].mMinState == IntegerValueRange::S_BOUND) + mTrueValueRange[s1].LimitMax(mLocalValueRange[s0].mMaxValue); + + if (mLocalValueRange[s1].mMaxState == IntegerValueRange::S_BOUND) + mFalseValueRange[s0].LimitMax(mLocalValueRange[s1].mMaxValue - 1); + if (mLocalValueRange[s1].mMinState == IntegerValueRange::S_BOUND) + mTrueValueRange[s0].LimitMin(mLocalValueRange[s1].mMinValue); } break; case IA_CMPGS: @@ -8247,6 +8272,44 @@ bool InterCodeBasicBlock::RemoveUnusedResultInstructions(void) return changed; } +bool InterCodeBasicBlock::RemoveUnusedLocalStoreInstructions(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + if (mInstructions.Size() > 0 && mInstructions.Last()->mCode == IC_RETURN) + { + int i = mInstructions.Size(); + while (i > 0) + { + i--; + InterInstruction* ins = mInstructions[i]; + if (ins->mCode == IC_STORE && ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_LOCAL) + { + ins->mCode = IC_NONE; + ins->mNumOperands = 0; + changed = true; + } + else if (ins->mCode == IC_LOAD) + break; + else if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE) + break; + else if (ins->mCode == IC_COPY || ins->mCode == IC_STRCPY) + break; + } + } + + if (mTrueJump && mTrueJump->RemoveUnusedLocalStoreInstructions()) + changed = true; + if (mFalseJump && mFalseJump->RemoveUnusedLocalStoreInstructions()) + changed = true; + } + + return false; +} + void InterCodeBasicBlock::BuildCallerSaveTempSet(NumberSet& callerSaveTemps) { if (!mVisited) @@ -16371,6 +16434,15 @@ void InterCodeProcedure::RemoveUnusedInstructions(void) } while (mEntryBlock->RemoveUnusedResultInstructions()); } +void InterCodeProcedure::RemoveUnusedLocalStoreInstructions(void) +{ + if (mCompilerOptions & COPT_OPTIMIZE_BASIC) + { + ResetVisited(); + mEntryBlock->RemoveUnusedLocalStoreInstructions(); + } +} + void InterCodeProcedure::RemoveUnusedStoreInstructions(InterMemory paramMemory) { if (mCompilerOptions & COPT_OPTIMIZE_BASIC) @@ -16849,7 +16921,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "opp::sort::iterator,>"); mEntryBlock = mBlocks[0]; @@ -17471,6 +17543,8 @@ void InterCodeProcedure::Close(void) RemoveUnusedInstructions(); #endif + RemoveUnusedLocalStoreInstructions(); + #if 1 ResetVisited(); @@ -18370,7 +18444,7 @@ void InterCodeProcedure::Disassemble(FILE* file) void InterCodeProcedure::Disassemble(const char* name, bool dumpSets) { -#if 0 +#if 1 #ifdef _WIN32 FILE* file; static bool initial = true; diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 0f4b4f8..f2d8026 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -422,6 +422,7 @@ public: void BuildCallerSaveTempSet(NumberSet& callerSaveTemps); void BuildConstTempSets(void); bool PropagateConstOperationsUp(void); + bool RemoveUnusedLocalStoreInstructions(void); void BuildLocalVariableSets(const GrowingVariableArray& localVars, const GrowingVariableArray& params, InterMemory paramMemory); void BuildGlobalProvidedVariableSet(const GrowingVariableArray& localVars, NumberSet fromProvidedVars, const GrowingVariableArray& params, NumberSet fromProvidedParams, InterMemory paramMemory); @@ -659,6 +660,7 @@ protected: void BuildLoopPrefix(void); void SingleAssignmentForwarding(void); void RemoveUnusedStoreInstructions(InterMemory paramMemory); + void RemoveUnusedLocalStoreInstructions(void); void MergeCommonPathInstructions(void); void PushSinglePathResultInstructions(void); void CollectVariables(InterMemory paramMemory); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 4ada98e..3d40258 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -3276,7 +3276,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION) + if (vr.mType->mType == DT_TYPE_ARRAY)// || vr.mType->mType == DT_TYPE_FUNCTION) vr = Dereference(proc, texp, block, vr, 1); else if (pdec && pdec->mBase->mType == DT_TYPE_POINTER && vr.mType->mType == DT_TYPE_INTEGER && texp->mType == EX_CONSTANT && texp->mDecValue->mType == DT_CONST_INTEGER && texp->mDecValue->mInteger == 0) { @@ -3316,7 +3316,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* wins->mSrc[1].mTemp = ains->mDst.mTemp; if (pdec) { - if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) + if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF || pdec->mBase->mType == DT_TYPE_FUNCTION) { wins->mSrc[1].mOperandSize = 2; wins->mSrc[0].mType = IT_POINTER; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 498bf74..7c25e9b 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -13623,6 +13623,7 @@ bool NativeCodeBasicBlock::ForwardAXYReg(void) bool xisa = false, yisa = false; int xoffset = -1, yoffset = -1; + int zpx = -1, zpy = -1, zpa = -1; for (int i = 0; i < mIns.Size(); i++) { @@ -13630,32 +13631,102 @@ bool NativeCodeBasicBlock::ForwardAXYReg(void) { xisa = true; xoffset = i; + zpx = zpa; } else if (mIns[i].mType == ASMIT_TXA) { xisa = true; yisa = false; xoffset = i; + zpa = zpx; } else if (mIns[i].mType == ASMIT_TAY) { yisa = true; yoffset = i; + zpy = zpa; } else if (mIns[i].mType == ASMIT_TYA) { yisa = true; xisa = false; yoffset = i; + zpa = zpy; } - else if (mIns[i].ChangesXReg()) - xisa = false; - else if (mIns[i].ChangesYReg()) - xisa = false; - else if (mIns[i].ChangesAccu()) + else if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE) + { + if (zpx == mIns[i].mAddress) + { + mIns[i].mType = ASMIT_TXA; mIns[i].mMode = ASMIM_IMPLIED; + xisa = true; + yisa = false; + int j = i; + while (j > 0 && !(mIns[j - 1].mLive & LIVE_CPU_REG_X)) + { + mIns[j - 1].mLive |= LIVE_CPU_REG_X; + j--; + } + } + else if (zpy == mIns[i].mAddress) + { + mIns[i].mType = ASMIT_TYA; mIns[i].mMode = ASMIM_IMPLIED; + yisa = true; + xisa = false; + int j = i; + while (j > 0 && !(mIns[j - 1].mLive & LIVE_CPU_REG_Y)) + { + mIns[j - 1].mLive |= LIVE_CPU_REG_Y; + j--; + } + } + else + { + xisa = false; + yisa = false; + } + zpa = mIns[i].mAddress; + } + else if (mIns[i].mType == ASMIT_LDX && mIns[i].mMode == ASMIM_ZERO_PAGE) { xisa = false; + zpx = mIns[i].mAddress; + } + else if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_ZERO_PAGE) + { yisa = false; + zpy = mIns[i].mAddress; + } + else if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE) + { + zpa = mIns[i].mAddress; + if (yisa) + zpy = mIns[i].mAddress; + else if (zpy == mIns[i].mAddress) + zpy = -1; + if (xisa) + zpx = mIns[i].mAddress; + else if (zpx == mIns[i].mAddress) + zpx = -1; + } + else if (mIns[i].mType == ASMIT_STX && mIns[i].mMode == ASMIM_ZERO_PAGE) + { + zpx = mIns[i].mAddress; + if (xisa) + zpa = mIns[i].mAddress; + else if (zpa == mIns[i].mAddress) + zpa = -1; + if (zpy == mIns[i].mAddress) + zpy = -1; + } + else if (mIns[i].mType == ASMIT_STY && mIns[i].mMode == ASMIM_ZERO_PAGE) + { + zpy = mIns[i].mAddress; + if (yisa) + zpa = mIns[i].mAddress; + else if (zpa == mIns[i].mAddress) + zpa = -1; + if (zpx == mIns[i].mAddress) + zpx = -1; } else if (i + 1 < mIns.Size() && mIns[i].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && !(mIns[i + 1].mLive & LIVE_CPU_REG_C)) @@ -13685,6 +13756,33 @@ bool NativeCodeBasicBlock::ForwardAXYReg(void) } } } + else + { + if (mIns[i].ChangesXReg()) + { + xisa = false; + zpx = -1; + } + if (mIns[i].ChangesYReg()) + { + yisa = false; + zpy = -1; + } + if (mIns[i].ChangesAccu()) + { + xisa = false; + yisa = false; + zpa = -1; + } + + if (zpa >= 0 && mIns[i].ChangesZeroPage(zpa)) + zpa = -1; + if (zpx >= 0 && mIns[i].ChangesZeroPage(zpx)) + zpx = -1; + if (zpy >= 0 && mIns[i].ChangesZeroPage(zpy)) + zpy = -1; + } + } if (mTrueJump && mTrueJump->ForwardAXYReg()) @@ -40817,7 +40915,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "test_pab50"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index e6e9f60..d53ff72 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -119,7 +119,7 @@ void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec) dec->mScope->Insert(mdec->mIdent, mdec); } -Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) +Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaration* ptempl) { const Ident* structName = nullptr; @@ -169,6 +169,9 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, dec->mQualIdent); } + if (ptempl) + ptempl->mBase = dec; + if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_COLON) { mScanner->NextToken(); @@ -181,7 +184,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) else if (ConsumeTokenIf(TK_PRIVATE)) pflags |= DTF_PRIVATE | DTF_PROTECTED; - Declaration* pdec = ParseQualIdent(); + Declaration* pdec = ParseBaseTypeDeclaration(0, false); if (pdec) { if (pdec->mType == DT_TYPE_STRUCT) @@ -481,7 +484,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) return dec; } -Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) +Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Declaration* ptempl) { Declaration* dec = nullptr; const Ident* pident = nullptr; @@ -758,13 +761,13 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) break; } case TK_STRUCT: - dec = ParseStructDeclaration(flags, DT_TYPE_STRUCT); + dec = ParseStructDeclaration(flags, DT_TYPE_STRUCT, ptempl); break; case TK_CLASS: - dec = ParseStructDeclaration(flags | DTF_PRIVATE | DTF_PROTECTED, DT_TYPE_STRUCT); + dec = ParseStructDeclaration(flags | DTF_PRIVATE | DTF_PROTECTED, DT_TYPE_STRUCT, ptempl); break; case TK_UNION: - dec = ParseStructDeclaration(flags, DT_TYPE_UNION); + dec = ParseStructDeclaration(flags, DT_TYPE_UNION, ptempl); break; default: mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Declaration starts with invalid token", TokenNames[mScanner->mToken]); @@ -3475,7 +3478,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex return cdec; } - bdec = ParseBaseTypeDeclaration(typeFlags, false); + bdec = ParseBaseTypeDeclaration(typeFlags, false, ptempl); } Declaration* rdec = nullptr, * ldec = nullptr; @@ -4583,7 +4586,31 @@ Expression* Parser::ParseSimpleExpression(bool lhs) if (dec) { if (dec->mTemplate && mScanner->mToken == TK_LESS_THAN) + { dec = ParseTemplateExpansion(dec->mTemplate, nullptr); + while (ConsumeTokenIf(TK_COLCOLON)) + { + if (mScanner->mToken == TK_IDENT) + { + if (dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_STRUCT) + { + Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_USING); + + if (ndec) + dec = ndec; + else + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown identifier", mScanner->mTokenIdent); + } + else + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a class or namespace"); + + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + + mScanner->NextToken(); + } + } if (dec->mType == DT_CONST_INTEGER || dec->mType == DT_CONST_FLOAT || dec->mType == DT_CONST_FUNCTION || dec->mType == DT_CONST_ASSEMBLER || dec->mType == DT_LABEL || dec->mType == DT_LABEL_REF) { @@ -4630,6 +4657,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation); } } + else if (dec->mType == DT_CONST_TEMPLATE) + { + exp = new Expression(mScanner->mLocation, EX_CONSTANT); + exp->mDecValue = dec; + exp->mDecType = TheSignedIntTypeDeclaration; + } else if (dec->mType == DT_ELEMENT) { mErrors->Error(mScanner->mLocation, EERR_NON_STATIC_MEMBER, "Non static member access", mScanner->mTokenIdent); @@ -5617,6 +5650,19 @@ Expression* Parser::ParsePostfixExpression(bool lhs) else if (mScanner->mToken == TK_ARROW) { mScanner->NextToken(); + while (exp->mDecType->mType != DT_TYPE_POINTER) + { + Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX); + dexp->mToken = TK_ARROW; + dexp->mDecType = TheVoidPointerTypeDeclaration; + dexp->mLeft = exp; + + Expression* oexp = CheckOperatorOverload(dexp); + if (oexp == dexp) + break; + exp = oexp; + } + if (exp->mDecType->mType == DT_TYPE_POINTER) { Expression * dexp = new Expression(mScanner->mLocation, EX_PREFIX); @@ -6713,6 +6759,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) case TK_BINARY_NOT: opident = Ident::Unique("operator~"); break; + case TK_ARROW: + opident = Ident::Unique("operator->"); + break; } if (opident) @@ -7447,7 +7496,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp } else { - if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) + if (exp->mType == EX_CONSTANT && (exp->mDecValue->mType == DT_CONST_INTEGER || exp->mDecValue->mType == DT_CONST_TEMPLATE)) epdec->mBase = exp->mDecValue; else mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Const integer parameter expected", pdec->mIdent); @@ -7480,7 +7529,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp else { Declaration* epdec = tdec->mParams; - while (epdec && epdec->mBase->mType != DT_TYPE_TEMPLATE) + while (epdec && epdec->mBase->mType != DT_TYPE_TEMPLATE && epdec->mBase->mType != DT_CONST_TEMPLATE) epdec = epdec->mNext; if (epdec) @@ -7490,6 +7539,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp tdec->mBase = bdec; bdec->mTemplate = tdec; bdec->mBase = tmpld->mBase; + tdec->mNext = tmpld; return bdec; } diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 2eb21bc..7915cc6 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -57,9 +57,9 @@ protected: Expression * AddFunctionCallRefReturned(Expression * exp); Expression* CleanupExpression(Expression* exp); - Declaration* ParseBaseTypeDeclaration(uint64 flags, bool qualified); + 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* ParseStructDeclaration(uint64 flags, DecType dt, Declaration* ptempl = nullptr); Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp); Expression* ParseInitExpression(Declaration* dtype); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 4514311..895438c 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1623,6 +1623,10 @@ void Scanner::NextRawToken(void) mTokenIdent = Ident::Unique("operator[]"); break; + case TK_ARROW: + mTokenIdent = Ident::Unique("operator->"); + break; + default: // dirty little hack to implement token preview, got to fix // this with an infinit preview sequence at one point From bd3c7571c5a5a5e772614844fa3e3231862bf666 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 19 Aug 2023 21:57:44 +0200 Subject: [PATCH 091/169] bump version number --- oscar64/Parser.cpp | 4 - oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 +- oscar64setup/oscar64setup.vdproj | 188 ++++++++++++++++++++++++++++++- 4 files changed, 190 insertions(+), 12 deletions(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index d53ff72..3802253 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -7462,10 +7462,6 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp Declaration* xdec = tmpld->mParams; while (dec) { - if (dec->mBase->mType == DT_TYPE_TEMPLATE) - { - printf("oopsi"); - } tdec->mScope->Insert(xdec->mIdent, dec->mBase); dec = dec->mNext; xdec = xdec->mNext; diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index c006cc7..cff1a16 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.23.215"); + strcpy(strProductVersion, "1.24.216"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index bc8b980..e9c2272 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,23,215,0 - PRODUCTVERSION 1,23,215,0 + FILEVERSION 1,24,216,0 + PRODUCTVERSION 1,24,216,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.23.215.0" + VALUE "FileVersion", "1.24.216.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.23.215.0" + VALUE "ProductVersion", "1.24.216.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 963e16f..34434c4 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -88,6 +88,12 @@ } "Entry" { + "MsmKey" = "8:_0EE9160CA4D44278A3929B0A4E0789F8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_1088B8AF518A4841A419B723AEB6C2BA" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -238,6 +244,12 @@ } "Entry" { + "MsmKey" = "8:_32B099B0E98B47D0892700BA42D0760E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_33E047EAEFFB45778C59472F157161DA" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -586,6 +598,12 @@ } "Entry" { + "MsmKey" = "8:_82C11E2A96FE49E399EEEAC2FEE9DCDC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_85AF458C41734A099F879A01E6CEB35F" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1030,6 +1048,12 @@ } "Entry" { + "MsmKey" = "8:_DBCD7B3D63C34E31A882799F3C82F0E9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_DE1058FFA9E149D1909C819592A12273" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1048,6 +1072,12 @@ } "Entry" { + "MsmKey" = "8:_E11BDCFFB9944A1F893FE4EC86ACCD6C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_E218D776D9014F99BE2B046AEF2D6E8B" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1108,6 +1138,12 @@ } "Entry" { + "MsmKey" = "8:_EC599856E7AE44F4A2F51AA76A4D044C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_ED5FED616EA64689AB793E5D8BD3F13D" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1150,6 +1186,12 @@ } "Entry" { + "MsmKey" = "8:_F472CF5FA6CF43649B4CD8E5F204DA65" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_F715B9FA6E0048388F451AB4670FD1EB" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1511,6 +1553,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0EE9160CA4D44278A3929B0A4E0789F8" + { + "SourcePath" = "8:..\\include\\opp\\vector.h" + "TargetName" = "8:vector.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1088B8AF518A4841A419B723AEB6C2BA" { "SourcePath" = "8:..\\samples\\fractals\\mbmulti3d.c" @@ -2011,6 +2073,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_32B099B0E98B47D0892700BA42D0760E" + { + "SourcePath" = "8:..\\include\\opp\\move.h" + "TargetName" = "8:move.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_33E047EAEFFB45778C59472F157161DA" { "SourcePath" = "8:..\\include\\c64\\iecbus.h" @@ -3171,6 +3253,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_82C11E2A96FE49E399EEEAC2FEE9DCDC" + { + "SourcePath" = "8:..\\include\\opp\\list.h" + "TargetName" = "8:list.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_85AF458C41734A099F879A01E6CEB35F" { "SourcePath" = "8:..\\include\\opp\\ofstream.cpp" @@ -4651,6 +4753,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DBCD7B3D63C34E31A882799F3C82F0E9" + { + "SourcePath" = "8:..\\include\\opp\\iterator.h" + "TargetName" = "8:iterator.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DE1058FFA9E149D1909C819592A12273" { "SourcePath" = "8:..\\samples\\particles\\fireworks_stripe.c" @@ -4711,6 +4833,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E11BDCFFB9944A1F893FE4EC86ACCD6C" + { + "SourcePath" = "8:..\\include\\opp\\algorithm.h" + "TargetName" = "8:algorithm.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E218D776D9014F99BE2B046AEF2D6E8B" { "SourcePath" = "8:..\\include\\stdlib.c" @@ -4911,6 +5053,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EC599856E7AE44F4A2F51AA76A4D044C" + { + "SourcePath" = "8:..\\include\\opp\\bidxlist.h" + "TargetName" = "8:bidxlist.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ED5FED616EA64689AB793E5D8BD3F13D" { "SourcePath" = "8:..\\include\\nes\\mmc3.c" @@ -5051,6 +5213,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F472CF5FA6CF43649B4CD8E5F204DA65" + { + "SourcePath" = "8:..\\include\\opp\\array.h" + "TargetName" = "8:array.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F715B9FA6E0048388F451AB4670FD1EB" { "SourcePath" = "8:..\\samples\\resources\\friendlybear.bin" @@ -5504,15 +5686,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{98D62EE4-5445-436D-BF7B-4353AD7BFEA3}" - "PackageCode" = "8:{90AEC745-AEF0-410C-9324-C5E13121720B}" + "ProductCode" = "8:{9FF44D2B-39DB-423A-9E26-A5243460457E}" + "PackageCode" = "8:{1F4AB6F6-7717-4470-8CBE-1EB04C68D47F}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.23.215" + "ProductVersion" = "8:1.24.216" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 04b10bb04d0701a7a460a4345eaf5209f400d1fa Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 19 Aug 2023 22:01:16 +0200 Subject: [PATCH 092/169] Update readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a020a79..1976bb4 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,8 @@ Supported Features: * virtual member functions * string and iostream classes * default parameters for class members and functions +* templates +* vector, array and list template classes ## Installation and Usage From 6ff2409596e7a5d1589b735069e364b37e77d1cd Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 20 Aug 2023 09:26:26 +0200 Subject: [PATCH 093/169] Fix return register optimization in v table call --- oscar64/InterCode.cpp | 2 +- oscar64/InterCode.h | 1 + oscar64/InterCodeGenerator.cpp | 1 + oscar64/NativeCodeGenerator.cpp | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index e38ea70..a37c0ae 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16064,7 +16064,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), mCheckUnreachable(true), mReturnType(IT_NONE), mCheapInline(false), - mDeclaration(nullptr), mGlobalsChecked(false) + mDeclaration(nullptr), mGlobalsChecked(false), mDispatchedCall(false) { mID = mModule->mProcedures.Size(); mModule->mProcedures.Push(this); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index f2d8026..fbe4d86 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -602,6 +602,7 @@ public: int mTempSize, mCommonFrameSize, mCallerSavedTemps, mFreeCallerSavedTemps, mFastCallBase; bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure; bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack; + bool mDispatchedCall; bool mCheckUnreachable; GrowingInterCodeProcedurePtrArray mCalledFunctions; bool mCheapInline; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 3d40258..16aafc4 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -4266,6 +4266,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* Declaration* dinit = exp->mLeft->mLeft->mDecValue->mValue->mDecValue->mParams; while (dinit) { + proc->mModule->mProcedures[dinit->mValue->mDecValue->mVarIndex]->mDispatchedCall = true; proc->AddCalledFunction(proc->mModule->mProcedures[dinit->mValue->mDecValue->mVarIndex]); dinit = dinit->mNext; } diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 7c25e9b..539d07a 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -40993,7 +40993,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mEntryBlock->mTrueJump = CompileBlock(mInterProc, mInterProc->mBlocks[0]); mEntryBlock->mBranch = ASMIT_JMP; - if (proc->mLeafProcedure && proc->mFastCallProcedure && !proc->mInterrupt && mNoFrame && mStackExpand == 0 && commonFrameSize == 0 && (mGenerator->mCompilerOptions & COPT_NATIVE)) + if (proc->mLeafProcedure && proc->mFastCallProcedure && !proc->mInterrupt && !proc->mDispatchedCall && mNoFrame && mStackExpand == 0 && commonFrameSize == 0 && (mGenerator->mCompilerOptions & COPT_NATIVE)) { #if 1 if (proc->mParamVars.Size() == 1 && proc->mParamVars[0]->mSize == 1) From 07dc6dc4dbcb88890217c43c600fcbb7a11977e1 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 20 Aug 2023 12:02:06 +0200 Subject: [PATCH 094/169] Optimize simple virtual with const return to table lookup --- oscar64/Compiler.cpp | 208 ++++++++++++++++++++++++++++----------- oscar64/Declaration.cpp | 5 + oscar64/Disassembler.cpp | 2 +- 3 files changed, 157 insertions(+), 58 deletions(-) diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index cdda4f9..7a2a995 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -244,6 +244,21 @@ void Compiler::CompleteTemplateExpansion(void) { } +bool IsSimpleConstReturn(Declaration * mdec) +{ + if (mdec->mBase->mBase->IsSimpleType() && mdec->mBase->mParams->mNext == nullptr) + { + Expression* ex = mdec->mValue; + if (ex->mType == EX_SCOPE) + ex = ex->mLeft; + + if (ex->mType == EX_RETURN && ex->mLeft->mType == EX_CONSTANT) + return true; + } + + return false; +} + void Compiler::BuildVTables(void) { // Connect vdecs with parents @@ -279,74 +294,153 @@ void Compiler::BuildVTables(void) { vdec->mScope->Iterate([=](const Ident* mident, Declaration* mdec) { - Declaration* vtabt = new Declaration(mdec->mLocation, DT_TYPE_ARRAY); - vtabt->mBase = mdec->mBase->ToStriped(vdec->mSize); - vtabt->mSize = vdec->mSize * 2; - vtabt->mStride = 1; - vtabt->mStripe = 1; - vtabt->mFlags |= DTF_CONST | DTF_DEFINED; - - Declaration* vtaba = new Declaration(mdec->mLocation, DT_VARIABLE); - vtaba->mFlags = DTF_CONST | DTF_GLOBAL | DTF_DEFINED; - vtaba->mBase = vtabt; - vtaba->mSize = vtabt->mSize; - vtaba->mValue = new Expression(mdec->mLocation, EX_CONSTANT); - vtaba->mValue->mDecType = vtabt; - vtaba->mValue->mDecValue = new Declaration(mdec->mLocation, DT_CONST_STRUCT); - vtaba->mIdent = mdec->mIdent; - vtaba->mQualIdent = mdec->mQualIdent->Mangle("$vtable"); - vtaba->mSection = mdec->mSection; - vtaba->mOffset = - vdec->mVarIndex; - - Declaration* last = nullptr; - + bool simpleConst = vdec->mSize > 0; for (int i = 0; i < vdec->mSize; i++) + if (!IsSimpleConstReturn(mdec->mCalled[i])) + simpleConst = false; + + if (simpleConst) { - Declaration* vmdec = mdec->mCalled[i]; + Declaration* vtabt = new Declaration(mdec->mLocation, DT_TYPE_ARRAY); + vtabt->mBase = mdec->mBase->mBase->ToConstType()->ToStriped(vdec->mSize); + vtabt->mSize = vdec->mSize * mdec->mBase->mBase->mSize; + vtabt->mStride = 1; + vtabt->mStripe = 1; + vtabt->mFlags |= DTF_CONST | DTF_DEFINED; - Expression* texp = new Expression(vmdec->mLocation, EX_CONSTANT); - texp->mDecType = vtabt->mBase; - texp->mDecValue = vmdec; + Declaration* vtaba = new Declaration(mdec->mLocation, DT_VARIABLE); + vtaba->mFlags = DTF_CONST | DTF_GLOBAL | DTF_DEFINED; + vtaba->mBase = vtabt; + vtaba->mSize = vtabt->mSize; + vtaba->mValue = new Expression(mdec->mLocation, EX_CONSTANT); + vtaba->mValue->mDecType = vtabt; + vtaba->mValue->mDecValue = new Declaration(mdec->mLocation, DT_CONST_STRUCT); + vtaba->mIdent = mdec->mIdent; + vtaba->mQualIdent = mdec->mQualIdent->Mangle("$vltable"); + vtaba->mSection = mdec->mSection; + vtaba->mOffset = -vdec->mVarIndex; - Declaration* cdec = new Declaration(vmdec->mLocation, DT_CONST_POINTER); - cdec->mValue = texp; - cdec->mBase = vtabt->mBase; - cdec->mOffset = i; + Declaration* last = nullptr; - if (last) - last->mNext = cdec; - else - vtaba->mValue->mDecValue->mParams = cdec; - last = cdec; + for (int i = 0; i < vdec->mSize; i++) + { + Declaration* vmdec = mdec->mCalled[i]; + + Expression* texp = vmdec->mValue; + if (texp->mType == EX_SCOPE) + texp = texp->mLeft; + texp = texp->mLeft; + + Declaration* cdec = texp->mDecValue->Clone(); + cdec->mOffset = i; + + if (last) + last->mNext = cdec; + else + vtaba->mValue->mDecValue->mParams = cdec; + last = cdec; + } + + Expression* vexp = new Expression(mdec->mLocation, EX_QUALIFY); + vexp->mLeft = new Expression(mdec->mLocation, EX_PREFIX); + vexp->mLeft->mDecType = mdec->mBase->mParams->mBase->mBase; + vexp->mLeft->mToken = TK_MUL; + vexp->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE); + vexp->mLeft->mLeft->mDecType = mdec->mBase->mParams->mBase; + vexp->mLeft->mLeft->mDecValue = mdec->mBase->mParams; + + vexp->mDecValue = new Declaration(mdec->mLocation, DT_ELEMENT); + vexp->mDecValue->mBase = TheCharTypeDeclaration; + vexp->mDecValue->mOffset = vdec->mOffset; + vexp->mDecValue->mSize = 1; + vexp->mDecType = TheCharTypeDeclaration; + + Expression* ecall = new Expression(mdec->mLocation, EX_RETURN); + ecall->mLeft = new Expression(mdec->mLocation, EX_INDEX); + ecall->mLeft->mDecType = mdec->mBase->mBase; + ecall->mDecType = mdec->mBase->mBase; + ecall->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE); + ecall->mLeft->mLeft->mDecType = vtabt; + ecall->mLeft->mLeft->mDecValue = vtaba; + ecall->mLeft->mRight = vexp; + + mdec->mCalled.SetSize(0); + + mdec->mFlags |= DTF_DEFINED; + mdec->mBase->mFlags &= ~DTF_VIRTUAL; + mdec->mValue = ecall; } + else + { + Declaration* vtabt = new Declaration(mdec->mLocation, DT_TYPE_ARRAY); + vtabt->mBase = mdec->mBase->ToStriped(vdec->mSize); + vtabt->mSize = vdec->mSize * 2; + vtabt->mStride = 1; + vtabt->mStripe = 1; + vtabt->mFlags |= DTF_CONST | DTF_DEFINED; -// mCompilationUnits->AddReferenced(vtaba); + Declaration* vtaba = new Declaration(mdec->mLocation, DT_VARIABLE); + vtaba->mFlags = DTF_CONST | DTF_GLOBAL | DTF_DEFINED; + vtaba->mBase = vtabt; + vtaba->mSize = vtabt->mSize; + vtaba->mValue = new Expression(mdec->mLocation, EX_CONSTANT); + vtaba->mValue->mDecType = vtabt; + vtaba->mValue->mDecValue = new Declaration(mdec->mLocation, DT_CONST_STRUCT); + vtaba->mIdent = mdec->mIdent; + vtaba->mQualIdent = mdec->mQualIdent->Mangle("$vtable"); + vtaba->mSection = mdec->mSection; + vtaba->mOffset = -vdec->mVarIndex; - Expression* vexp = new Expression(mdec->mLocation, EX_QUALIFY); - vexp->mLeft = new Expression(mdec->mLocation, EX_PREFIX); - vexp->mLeft->mDecType = mdec->mBase->mParams->mBase->mBase; - vexp->mLeft->mToken = TK_MUL; - vexp->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE); - vexp->mLeft->mLeft->mDecType = mdec->mBase->mParams->mBase; - vexp->mLeft->mLeft->mDecValue = mdec->mBase->mParams; + Declaration* last = nullptr; - vexp->mDecValue = new Declaration(mdec->mLocation, DT_ELEMENT); - vexp->mDecValue->mBase = TheCharTypeDeclaration; - vexp->mDecValue->mOffset = vdec->mOffset; - vexp->mDecValue->mSize = 1; - vexp->mDecType = TheCharTypeDeclaration; + for (int i = 0; i < vdec->mSize; i++) + { + Declaration* vmdec = mdec->mCalled[i]; - Expression* ecall = new Expression(mdec->mLocation, EX_DISPATCH); - ecall->mLeft = new Expression(mdec->mLocation, EX_INDEX); - ecall->mLeft->mDecType = mdec->mBase; - ecall->mDecType = vtabt->mBase; - ecall->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE); - ecall->mLeft->mLeft->mDecType = vtabt; - ecall->mLeft->mLeft->mDecValue = vtaba; - ecall->mLeft->mRight = vexp; + Expression* texp = new Expression(vmdec->mLocation, EX_CONSTANT); + texp->mDecType = vtabt->mBase; + texp->mDecValue = vmdec; - mdec->mFlags |= DTF_DEFINED; - mdec->mValue = ecall; + Declaration* cdec = new Declaration(vmdec->mLocation, DT_CONST_POINTER); + cdec->mValue = texp; + cdec->mBase = vtabt->mBase; + cdec->mOffset = i; + + if (last) + last->mNext = cdec; + else + vtaba->mValue->mDecValue->mParams = cdec; + last = cdec; + } + + // mCompilationUnits->AddReferenced(vtaba); + + Expression* vexp = new Expression(mdec->mLocation, EX_QUALIFY); + vexp->mLeft = new Expression(mdec->mLocation, EX_PREFIX); + vexp->mLeft->mDecType = mdec->mBase->mParams->mBase->mBase; + vexp->mLeft->mToken = TK_MUL; + vexp->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE); + vexp->mLeft->mLeft->mDecType = mdec->mBase->mParams->mBase; + vexp->mLeft->mLeft->mDecValue = mdec->mBase->mParams; + + vexp->mDecValue = new Declaration(mdec->mLocation, DT_ELEMENT); + vexp->mDecValue->mBase = TheCharTypeDeclaration; + vexp->mDecValue->mOffset = vdec->mOffset; + vexp->mDecValue->mSize = 1; + vexp->mDecType = TheCharTypeDeclaration; + + Expression* ecall = new Expression(mdec->mLocation, EX_DISPATCH); + ecall->mLeft = new Expression(mdec->mLocation, EX_INDEX); + ecall->mLeft->mDecType = mdec->mBase; + ecall->mDecType = vtabt->mBase; + ecall->mLeft->mLeft = new Expression(mdec->mLocation, EX_VARIABLE); + ecall->mLeft->mLeft->mDecType = vtabt; + ecall->mLeft->mLeft->mDecValue = vtaba; + ecall->mLeft->mRight = vexp; + + mdec->mFlags |= DTF_DEFINED; + mdec->mValue = ecall; + } }); }); } diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 6a8995b..1341d8a 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1244,6 +1244,11 @@ Declaration* Declaration::Clone(void) ndec->mAlignment = mAlignment; ndec->mSection = mSection; ndec->mVTable = mVTable; + ndec->mInteger = mInteger; + ndec->mNumber = mNumber; + ndec->mMinValue = mMinValue; + ndec->mMaxValue = mMaxValue; + ndec->mCompilerOptions = mCompilerOptions; return ndec; } diff --git a/oscar64/Disassembler.cpp b/oscar64/Disassembler.cpp index 173fa35..10e868b 100644 --- a/oscar64/Disassembler.cpp +++ b/oscar64/Disassembler.cpp @@ -801,7 +801,7 @@ const char* NativeCodeDisassembler::AddrName(int bank, int addr, char* buffer, I int i = 0; while (i < obj->mRanges.Size() && (addr - obj->mAddress < obj->mRanges[i].mOffset || addr - obj->mAddress - obj->mRanges[i].mOffset >= obj->mRanges[i].mSize)) i++; - if (i < obj->mRanges.Size()) + if (i < obj->mRanges.Size() && obj->mRanges[i].mIdent) sprintf_s(buffer, 160, "; (%s.%s + %d)", obj->mIdent->mString, obj->mRanges[i].mIdent->mString, addr - obj->mAddress - obj->mRanges[i].mOffset); else sprintf_s(buffer, 160, "; (%s + %d)", obj->mIdent->mString, addr - obj->mAddress); From 4732f76bd58a15ba2fe6b15b68f79c71c4efa13e Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 20 Aug 2023 14:17:40 +0200 Subject: [PATCH 095/169] Add static member variables --- oscar64/Parser.cpp | 69 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 3802253..79c4997 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -309,30 +309,48 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio break; } - mdec->mType = DT_ELEMENT; - mdec->mOffset = offset; - - offset += mdec->mBase->mSize; - if (offset > dec->mSize) - dec->mSize = offset; - - if (dec->mScope->Insert(mdec->mIdent, mdec)) - mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); - - if (dec->mConst) + if (mdec->mFlags & DTF_STATIC) { - Declaration* cmdec = mdec->Clone(); - cmdec->mBase = mdec->mBase->ToConstType(); + mdec->mFlags |= DTF_GLOBAL; + mdec->mVarIndex = -1; + mdec->mQualIdent = mScope->Mangle(mdec->mIdent); - dec->mConst->mScope->Insert(cmdec->mIdent, cmdec); - dec->mConst->mSize = dec->mSize; + Declaration * pdec = mCompilationUnits->mScope->Insert(mdec->mQualIdent, mdec); + + if (pdec) + mdec = pdec; + + if (dec->mScope->Insert(mdec->mIdent, mdec)) + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + } + else + { + mdec->mType = DT_ELEMENT; + mdec->mOffset = offset; + + offset += mdec->mBase->mSize; + if (offset > dec->mSize) + dec->mSize = offset; + + if (dec->mScope->Insert(mdec->mIdent, mdec)) + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + + if (dec->mConst) + { + Declaration* cmdec = mdec->Clone(); + cmdec->mBase = mdec->mBase->ToConstType(); + + dec->mConst->mScope->Insert(cmdec->mIdent, cmdec); + dec->mConst->mSize = dec->mSize; + } + + if (mlast) + mlast->mNext = mdec; + else + dec->mParams = mdec; + mlast = mdec; } - if (mlast) - mlast->mNext = mdec; - else - dec->mParams = mdec; - mlast = mdec; mdec = mdec->mNext; } @@ -3986,6 +4004,10 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex else ndec->mVarIndex = mLocalIndex++; } + else if (pthis) + { + ndec->mFlags |= storageFlags & DTF_STATIC; + } ndec->mOffset = 0; @@ -4863,6 +4885,13 @@ Expression* Parser::ParseQualify(Expression* exp) exp = nexp->ConstantFold(mErrors); } + else if (mdec->mType == DT_VARIABLE) + { + nexp = new Expression(mScanner->mLocation, EX_VARIABLE); + nexp->mDecValue = mdec; + nexp->mDecType = mdec->mBase; + exp = nexp->ConstantFold(mErrors); + } else if (mdec->mType == DT_CONST_FUNCTION) { ConsumeToken(TK_OPEN_PARENTHESIS); From 54296bdd71b75fd5cbf35e9adbcb5948ebdaf96c Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 20 Aug 2023 15:06:51 +0200 Subject: [PATCH 096/169] Add friend classes --- include/opp/iostream.cpp | 2 +- oscar64/Parser.cpp | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp index 1faabed..b53d408 100644 --- a/include/opp/iostream.cpp +++ b/include/opp/iostream.cpp @@ -13,7 +13,7 @@ inline ios::~ios(void) } -char ios::fill(void) +char ios::fill(void) const { return mFill; } diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 79c4997..1318abb 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -256,6 +256,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio { mScope = oscope; Declaration* fdec = ParseDeclaration(nullptr, true, false); + if (fdec->mType == DT_ANON) + fdec = fdec->mBase; dec->mFriends.Push(fdec); mScope = dec->mScope; } @@ -268,8 +270,6 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis); if (mdec) { - mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED); - mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent); int offset = dec->mSize; @@ -278,6 +278,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio if (mdec->mBase->mType == DT_TYPE_FUNCTION) { + mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED); + if (mdec->mBase->mFlags & DTF_VIRTUAL) needVTable = true; @@ -293,6 +295,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio } else if ((mCompilerOptions & COPT_CPLUSPLUS) && mdec->mType == DT_ANON) { + mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED); + ConsumeToken(TK_SEMICOLON); // anon element } @@ -300,6 +304,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio { while (mdec) { + mdec->mFlags |= flags & (DTF_PRIVATE | DTF_PROTECTED); + if (!(mdec->mBase->mFlags & DTF_DEFINED)) mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); @@ -3915,7 +3921,12 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } if (!pdec) + { + if (!pthis && (ndec->mBase->mFlags & DTF_FUNC_THIS)) + mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function declaration differs", ndec->mIdent); + pcdec->mNext = ndec; + } } if (pdec) @@ -4870,6 +4881,8 @@ Expression* Parser::ParseQualify(Expression* exp) { if (dtype->mFriends.Contains(mFunction)) ; + else if (mThisPointer && mThisPointer->mBase && mThisPointer->mBase->mBase && dtype->mFriends.Contains(mThisPointer->mBase->mBase->ToMutableType())) + ; else mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", ident); } From 5b4e5b545d7b419ba9b0e439e84db9754fbe9467 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 20 Aug 2023 19:06:24 +0200 Subject: [PATCH 097/169] Add or/and/shift to inline assembler --- oscar64/Assembler.cpp | 2 +- oscar64/Parser.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++- oscar64/Parser.h | 3 +++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/oscar64/Assembler.cpp b/oscar64/Assembler.cpp index f103ab6..2b9fc21 100644 --- a/oscar64/Assembler.cpp +++ b/oscar64/Assembler.cpp @@ -333,7 +333,7 @@ void InitAssembler(void) int AsmInsSize(AsmInsType type, AsmInsMode mode) { - if (type < ASMIT_INV) + if (type < ASMIT_INV && mode >= ASMIM_IMPLIED && mode < NUM_ASM_INS_MODES) return AsmInsModeSize[mode]; else return 1; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 1318abb..5d4f30d 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -8045,6 +8045,53 @@ Expression* Parser::ParseAssemblerAddOperand(Declaration* pcasm, int pcoffset) return exp; } +Expression* Parser::ParseAssemblerShiftOperand(Declaration* pcasm, int pcoffset) +{ + Expression* exp = ParseAssemblerAddOperand(pcasm, pcoffset); + while (mScanner->mToken == TK_LEFT_SHIFT || mScanner->mToken == TK_RIGHT_SHIFT) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_BINARY); + nexp->mToken = mScanner->mToken; + nexp->mLeft = exp; + mScanner->NextToken(); + nexp->mRight = ParseAssemblerAddOperand(pcasm, pcoffset); + exp = nexp->ConstantFold(mErrors); + } + return exp; +} + + +Expression* Parser::ParseAssemblerAndOperand(Declaration* pcasm, int pcoffset) +{ + Expression* exp = ParseAssemblerShiftOperand(pcasm, pcoffset); + while (mScanner->mToken == TK_BINARY_AND) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_BINARY); + nexp->mToken = mScanner->mToken; + nexp->mLeft = exp; + mScanner->NextToken(); + nexp->mRight = ParseAssemblerShiftOperand(pcasm, pcoffset); + exp = nexp->ConstantFold(mErrors); + } + return exp; +} + +Expression* Parser::ParseAssemblerOrOperand(Declaration* pcasm, int pcoffset) +{ + Expression* exp = ParseAssemblerAndOperand(pcasm, pcoffset); + while (mScanner->mToken == TK_BINARY_OR) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_BINARY); + nexp->mToken = mScanner->mToken; + nexp->mLeft = exp; + mScanner->NextToken(); + nexp->mRight = ParseAssemblerAndOperand(pcasm, pcoffset); + exp = nexp->ConstantFold(mErrors); + } + return exp; +} + + Expression* Parser::ParseAssemblerOperand(Declaration* pcasm, int pcoffset) { if (mScanner->mToken == TK_LESS_THAN) @@ -8188,7 +8235,7 @@ Expression* Parser::ParseAssemblerOperand(Declaration* pcasm, int pcoffset) return exp; } else - return ParseAssemblerAddOperand(pcasm, pcoffset); + return ParseAssemblerOrOperand(pcasm, pcoffset); } void Parser::AddAssemblerRegister(const Ident* ident, int value) diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 7915cc6..bf3faad 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -74,6 +74,9 @@ protected: Expression* ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset); Expression* ParseAssemblerMulOperand(Declaration* pcasm, int pcoffset); Expression* ParseAssemblerAddOperand(Declaration* pcasm, int pcoffset); + Expression* ParseAssemblerShiftOperand(Declaration* pcasm, int pcoffset); + Expression* ParseAssemblerAndOperand(Declaration* pcasm, int pcoffset); + Expression* ParseAssemblerOrOperand(Declaration* pcasm, int pcoffset); Expression* ParseAssemblerOperand(Declaration * pcasm, int pcoffset); Expression* CheckOperatorOverload(Expression* exp); From 7bf5ce7581fa5388a485e48dd91a03a4a370c19a Mon Sep 17 00:00:00 2001 From: drmortalwombat Date: Fri, 25 Aug 2023 11:03:49 +0200 Subject: [PATCH 098/169] Add debug file docu to readme --- README.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/README.md b/README.md index 1976bb4..99c82ea 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,80 @@ Creates vice monitor commands to define all static labels. One can load the label file in the monitor using the load_labels (ll) command or provide it on the command line for vice with the "-moncommands" command line argument. +#### Complete debug information ".dbj" + +This is a JSON file that contains detailed debug information. + +it has four top sections: + +* memory : complete memory map with lables and source location +* variables : list of all global/static variables with address and type index +* functions : list of all functions with local variables, line numbers and addresses +* types : list of all types + +##### Debug memory information + +The memory partitioning is described using a list of + +* name : name of the memory object +* start : start address (inclusive) +* end : end address (exclusive) +* type : linkage type of memory object +* source : source file that declared this memory object +* line : source line that declared this memory object + +##### Debug type information + +Every defined type has a unique numeric typeid that is used to reference it from the variable sections or from composite types. + +Each type has up to five attributes: + +* name : a string, present for all named types +* typeid : the unique numeric ID for this type +* size : size of a variable of this type in bytes +* type : base type or composition method for this type + * int : signed Integer + * unit : unsigned integer + * bool : boolean value + * enum : enumeration + * ptr : pointer to + * ref : reference + * struct : struct/class + * union +* members : list of members of a composite type or enum +* eid : typeid for pointer or reference targets + +##### Debug variables information + +Global variables have a name, a memory range and a typeid + +* name : a string, present for named variables +* start : start address (inclusive) +* end : end address (exclusive) +* typeid : the type id for this variable + +##### Debug function information + +* name : a string, present for named functions +* start : start address (inclusive) +* end : end address (exclusive) +* source : source file that declared this function +* line : source line that declared this function +* lines : list of all source lines for this function + * start : start address (inclusive) + * end : end address (exclusive) + * source : source file that declared this function + * line : source line that declared this function +* variables : list of all local variables for this function + * name : a string, present for named variables + * start : start address (inclusive) + * end : end address (exclusive) + * enter : first line where the vaiable becomes visible + * leave : last line where the variable is visible + * typeid : the type id for this variable + * base : zero page register pair for (sp/fp) for stack based variables + + ### Creating a d64 disk file The compiler can create a .d64 disk file, that includes the compiled .prg file as the first file in the directory and a series of additional resource files. The name of the disk file is provided with the -d64 command line options, additional files with the -f or -fz option. From fa19e466de338c3a0a6969d260523f35bd12940d Mon Sep 17 00:00:00 2001 From: drmortalwombat Date: Mon, 28 Aug 2023 18:52:14 +0200 Subject: [PATCH 099/169] Fix opp string append char --- include/opp/string.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/opp/string.cpp b/include/opp/string.cpp index e9de1c7..b5732a4 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -211,7 +211,7 @@ string & string::operator+=(char c) p[l] = c; p[l + 1] = 0; free(cstr); - cstr = c; + cstr = p; } else { @@ -220,6 +220,7 @@ string & string::operator+=(char c) cstr[1] = c; cstr[2] = 0; } + return *this; } From da9b8f2a42f43e13260e3e4fb9b09da5b820eca3 Mon Sep 17 00:00:00 2001 From: drmortalwombat Date: Thu, 31 Aug 2023 14:13:43 +0200 Subject: [PATCH 100/169] Fix return of const array as pointer --- oscar64/InterCodeGenerator.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 16aafc4..2622fd3 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -3733,7 +3733,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - vr = Dereference(proc, exp, block, vr); + if (procType->mBase->mType == DT_TYPE_POINTER && (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION)) + { + vr = Dereference(proc, exp, block, vr, 1); + vr.mReference = 0; + vr.mType = procType->mBase; + } + else + vr = Dereference(proc, exp, block, vr); if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID) mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Function has void return type"); @@ -4725,7 +4732,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, "dividers")) + if (proc->mIdent && !strcmp(proc->mIdent->mString, "test")) exp->Dump(0); #endif #if 0 From e9afd5e28404cd433cad30f3c1a137b6ec242100 Mon Sep 17 00:00:00 2001 From: drmortalwombat Date: Thu, 31 Aug 2023 20:17:39 +0200 Subject: [PATCH 101/169] Fix template function included multiple ways --- oscar64/Declaration.cpp | 16 ++++++++++++++++ oscar64/Declaration.h | 1 + oscar64/InterCodeGenerator.cpp | 2 ++ oscar64/Parser.cpp | 14 ++++++++++++-- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 1341d8a..73ed7fd 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1407,6 +1407,18 @@ Declaration* Declaration::ToMutableType(void) return mMutable; } +bool Declaration::IsSameTemplate(const Declaration* dec) const +{ + if (this == dec) + return true; + if (this->mType != mType) + return false; + + if (mType == DT_CONST_FUNCTION) + return mBase->IsSame(dec->mBase); + + return false; +} bool Declaration::IsSubType(const Declaration* dec) const { @@ -1731,6 +1743,10 @@ bool Declaration::IsSame(const Declaration* dec) const return true; } + else if (mType == DT_TYPE_TEMPLATE) + { + return mIdent == dec->mIdent; + } return false; } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 0a9adc7..d01e043 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -287,6 +287,7 @@ public: bool IsTemplateSame(const Declaration* dec, const Declaration* tdec) const; bool IsTemplateSameParams(const Declaration* dec, const Declaration* tdec) const; + bool IsSameTemplate(const Declaration* dec) const; bool IsIntegerType(void) const; bool IsNumericType(void) const; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 2622fd3..9d9e70c 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1297,6 +1297,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I InterInstruction* psins = new InterInstruction(exp->mLocation, IC_CONSTANT); psins->mDst.mType = IT_POINTER; psins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + psins->mDst.mOperandSize = 2; psins->mConst.mType = IT_POINTER; psins->mConst.mVarIndex = 0; psins->mConst.mIntConst = 0; @@ -1321,6 +1322,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I InterInstruction* plins = new InterInstruction(exp->mLocation, IC_CONSTANT); plins->mDst.mType = IT_POINTER; plins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + plins->mDst.mOperandSize = 2; plins->mConst.mType = IT_POINTER; plins->mConst.mVarIndex = 2; plins->mConst.mIntConst = 0; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 5d4f30d..d4f18e3 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -7812,8 +7812,18 @@ void Parser::ParseTemplateDeclaration(void) Declaration* pdec = mCompilationUnits->mScope->Insert(tdec->mQualIdent, tdec->mBase); if (pdec) { - tdec->mBase->mNext = pdec->mNext; - pdec->mNext = tdec->mBase; + Declaration* ppdec = pdec; + while (pdec && !pdec->IsSameTemplate(tdec->mBase)) + { + ppdec = pdec; + pdec = pdec->mNext; + } + + if (!pdec) + { + ppdec->mNext = tdec->mBase; + tdec->mBase->mNext = nullptr; + } } } From cb352fcc7cea2fdd6dd6e70ae217272a06fe8aab Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 4 Sep 2023 22:23:00 +0200 Subject: [PATCH 102/169] Bump version number --- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index cff1a16..55b6271 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.24.216"); + strcpy(strProductVersion, "1.24.217"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index e9c2272..a49c3fd 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,24,216,0 - PRODUCTVERSION 1,24,216,0 + FILEVERSION 1,24,217,0 + PRODUCTVERSION 1,24,217,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.24.216.0" + VALUE "FileVersion", "1.24.217.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.24.216.0" + VALUE "ProductVersion", "1.24.217.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 34434c4..db7ea13 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5686,15 +5686,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{9FF44D2B-39DB-423A-9E26-A5243460457E}" - "PackageCode" = "8:{1F4AB6F6-7717-4470-8CBE-1EB04C68D47F}" + "ProductCode" = "8:{DC3B50CD-E9C6-4F59-9E59-986778C41793}" + "PackageCode" = "8:{DB830FCB-0CA0-4992-9D69-E76D9CA18459}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.24.216" + "ProductVersion" = "8:1.24.217" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" 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 103/169] 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 + From 4dd3cd967ae577879738f0e2fc62663ebff8f227 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 8 Sep 2023 21:03:18 +0200 Subject: [PATCH 104/169] Add switch, break and continue to constexpr --- oscar64/Constexpr.cpp | 212 +++++++++++++++++++++++++++--------------- oscar64/Constexpr.h | 10 ++ oscar64/Parser.cpp | 2 +- 3 files changed, 148 insertions(+), 76 deletions(-) diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index 91b90fe..48a5b3a 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -542,7 +542,7 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp) return exp; } - Eval(exp->mLeft->mDecValue->mValue); + Execute(exp->mLeft->mDecValue->mValue); return mResult.ToExpression(mDataSection); } @@ -882,7 +882,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname); } else - Eval(exp->mLeft->mDecValue->mValue); + Execute(exp->mLeft->mDecValue->mValue); return mResult; } @@ -920,9 +920,6 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) { 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: @@ -998,15 +995,6 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) 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: { @@ -1019,16 +1007,6 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) 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); @@ -1044,55 +1022,6 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) 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); @@ -1108,12 +1037,12 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) if (v.mDecType->mType == DT_TYPE_ARRAY) { if (v.mBaseValue) - return Value(v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * vi.GetInt()); + return Value(v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * int(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()); + return Value(p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt())); } } @@ -1127,6 +1056,139 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) return exp; } +ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) +{ + for (;;) + { + switch (exp->mType) + { + case EX_SCOPE: + return Execute(exp->mLeft); + case EX_RETURN: + mResult = EvalCoerce(exp, Eval(exp->mLeft), mProcType->mBase); + return FLOW_RETURN; + case EX_CONSTANT: + case EX_VARIABLE: + case EX_BINARY: + case EX_RELATIONAL: + case EX_PREFIX: + case EX_TYPECAST: + case EX_CALL: + case EX_LIST: + case EX_CONDITIONAL: + case EX_LOGICAL_AND: + case EX_LOGICAL_OR: + case EX_LOGICAL_NOT: + case EX_INITIALIZATION: + case EX_ASSIGNMENT: + case EX_POSTINCDEC: + case EX_PREINCDEC: + case EX_QUALIFY: + case EX_INDEX: + Eval(exp); + return FLOW_NEXT; + + case EX_SEQUENCE: + if (exp->mRight) + { + Flow f = Execute(exp->mLeft); + if (f == FLOW_NEXT) + return Execute(exp->mRight); + return f; + } + else + return Execute(exp->mLeft); + + case EX_BREAK: + return FLOW_BREAK; + + case EX_CONTINUE: + return FLOW_CONTINUE; + + case EX_IF: + if (REval(exp->mLeft).GetInt()) + return Execute(exp->mRight->mLeft); + else if (exp->mRight->mRight) + return Execute(exp->mRight->mRight); + else + return FLOW_NEXT; + + case EX_SWITCH: + { + int64 v = REval(exp->mLeft).GetInt(); + + bool found = false; + Expression* sexp = exp->mRight; + while (sexp) + { + Expression* cexp = sexp->mLeft; + if (found || cexp->mType == EX_DEFAULT || v == REval(cexp->mLeft).GetInt()) + { + found = true; + if (cexp->mRight) + { + Flow f = Execute(cexp->mRight); + if (f == FLOW_BREAK) + return FLOW_NEXT; + else if (f != FLOW_NEXT) + return f; + } + } + sexp = sexp->mRight; + } + + return FLOW_NEXT; + } + + case EX_WHILE: + while (REval(exp->mLeft).GetInt()) + { + Flow f = Execute(exp->mRight); + if (f == FLOW_RETURN) + return FLOW_RETURN; + else if (f == FLOW_BREAK) + break; + } + return FLOW_NEXT; + + case EX_DO: + do { + Flow f = Execute(exp->mRight); + if (f == FLOW_RETURN) + return FLOW_RETURN; + else if (f == FLOW_BREAK) + break; + + } while (REval(exp->mLeft).GetInt()); + return FLOW_NEXT; + + case EX_FOR: + if (exp->mLeft->mRight) + Eval(exp->mLeft->mRight); + + while (!exp->mLeft->mLeft->mLeft || REval(exp->mLeft->mLeft->mLeft).GetInt()) + { + Flow f = Execute(exp->mRight); + if (f == FLOW_RETURN) + return FLOW_RETURN; + else if (f == FLOW_BREAK) + break; + + if (exp->mLeft->mLeft->mRight) + Eval(exp->mLeft->mLeft->mRight); + } + + return FLOW_NEXT; + + case EX_VOID: + return FLOW_NEXT; + + default: + mErrors->Error(exp->mLocation, EERR_INVALID_CONSTEXPR, "Invalid constexpr"); + } + } +} + ConstexprInterpreter::ValueItem::ValueItem(void) : mByte(0), mBaseValue(nullptr) { diff --git a/oscar64/Constexpr.h b/oscar64/Constexpr.h index b675cba..8bb65b7 100644 --- a/oscar64/Constexpr.h +++ b/oscar64/Constexpr.h @@ -80,6 +80,16 @@ protected: Value REval(Expression* exp); Value Eval(Expression* exp); + enum Flow + { + FLOW_NEXT, + FLOW_CONTINUE, + FLOW_BREAK, + FLOW_RETURN + }; + + Flow Execute(Expression* exp); + Declaration* mProcType; Location mLocation; LinkerSection* mDataSection; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 86ab51d..e6d845c 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -5695,7 +5695,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) nexp->mType = EX_VCALL; } - exp = nexp; + exp = nexp->ConstantFold(mErrors, mDataSection); } } else if (mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC) From bd37877c8cef6c128ef511650547aa5499cd9a5d Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 9 Sep 2023 12:09:05 +0200 Subject: [PATCH 105/169] Add heap support to constexpr --- oscar64/Constexpr.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++- oscar64/Constexpr.h | 9 ++++ oscar64/Errors.h | 2 + 3 files changed, 107 insertions(+), 2 deletions(-) diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index 48a5b3a..c4237aa 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -61,6 +61,18 @@ ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec) mData = new ValueItem[mDataSize]; } +ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec, int size) + : mLocation(location), + mDecType(dec), + mBaseValue(nullptr), mOffset(0), + mDataSize(size) +{ + if (mDataSize <= 4) + mData = mShortData; + else + mData = new ValueItem[mDataSize]; +} + ConstexprInterpreter::Value::Value(const Value& value) : mLocation(value.mLocation), mDecType(value.mDecType), @@ -403,6 +415,9 @@ void ConstexprInterpreter::Value::Assign(const Value& v) case DT_TYPE_ARRAY: memcpy(GetAddr(), v.GetAddr(), mDecType->mSize); break; + case DT_TYPE_POINTER: + PutPtr(v.GetPtr()); + break; } } @@ -489,7 +504,7 @@ Expression* ConstexprInterpreter::Value::ToExpression(LinkerSection* dataSection ConstexprInterpreter::ConstexprInterpreter(const Location & location, Errors* err, LinkerSection* dataSection) - : mLocation(location), mErrors(err), mDataSection(dataSection), mParams(Value()), mLocals(Value()) + : mLocation(location), mErrors(err), mDataSection(dataSection), mParams(Value()), mLocals(Value()), mHeap(nullptr) { } @@ -499,6 +514,25 @@ ConstexprInterpreter::~ConstexprInterpreter(void) } +ConstexprInterpreter::Value* ConstexprInterpreter::NewValue(Expression* exp, Declaration* type, int size) +{ + Value* v = new Value(exp->mLocation, type, size); + mHeap->Push(v); + return v; +} + +void ConstexprInterpreter::DeleteValue(Value* v) +{ + int i = mHeap->IndexOf(v); + if (i >= 0) + { + delete v; + mHeap->Remove(i); + } + else + mErrors->Error(v->mLocation, EERR_DOUBLE_FREE, "Freeing not allocated memory"); +} + Expression* ConstexprInterpreter::EvalCall(Expression* exp) { mProcType = exp->mLeft->mDecType; @@ -542,8 +576,14 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp) return exp; } + mHeap = new ExpandingArray(); + Execute(exp->mLeft->mDecValue->mValue); + if (mHeap->Size() > 0) + mErrors->Error(exp->mLocation, EERR_UNBALANCED_HEAP_USE, "Unbalanced heap use in constexpr"); + delete mHeap; + return mResult.ToExpression(mDataSection); } @@ -798,6 +838,12 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalUnary(Expression* exp, con break; case TK_MUL: return vl.GetPtr(); + case TK_NEW: + v.PutPtr(Value(NewValue(exp, exp->mDecType->mBase, vl.GetInt()))); + break; + case TK_DELETE: + DeleteValue(vl.GetPtr().mBaseValue); + break; default: mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); } @@ -825,6 +871,8 @@ ConstexprInterpreter::Value ConstexprInterpreter::REval(Expression* exp) ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, ConstexprInterpreter* caller) { + mHeap = caller->mHeap; + mProcType = exp->mLeft->mDecType; Expression* pex = exp->mRight; @@ -882,7 +930,10 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname); } else + { Execute(exp->mLeft->mDecValue->mValue); + UnwindDestructStack(0); + } return mResult; } @@ -1063,7 +1114,14 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) switch (exp->mType) { case EX_SCOPE: - return Execute(exp->mLeft); + { + int ds = mDestructStack.Size(); + Flow f = Execute(exp->mLeft); + UnwindDestructStack(ds); + + return f; + } + case EX_RETURN: mResult = EvalCoerce(exp, Eval(exp->mLeft), mProcType->mBase); return FLOW_RETURN; @@ -1141,34 +1199,53 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) } case EX_WHILE: + { + int ds = mDestructStack.Size(); while (REval(exp->mLeft).GetInt()) { + int ls = mDestructStack.Size(); Flow f = Execute(exp->mRight); + UnwindDestructStack(ls); + if (f == FLOW_RETURN) return FLOW_RETURN; else if (f == FLOW_BREAK) break; } + UnwindDestructStack(ds); return FLOW_NEXT; + } case EX_DO: + { + int ds = mDestructStack.Size(); do { + int ls = mDestructStack.Size(); Flow f = Execute(exp->mRight); + UnwindDestructStack(ls); + if (f == FLOW_RETURN) return FLOW_RETURN; else if (f == FLOW_BREAK) break; } while (REval(exp->mLeft).GetInt()); + UnwindDestructStack(ds); return FLOW_NEXT; + } case EX_FOR: + { + int ds = mDestructStack.Size(); if (exp->mLeft->mRight) Eval(exp->mLeft->mRight); while (!exp->mLeft->mLeft->mLeft || REval(exp->mLeft->mLeft->mLeft).GetInt()) { + int ls = mDestructStack.Size(); Flow f = Execute(exp->mRight); + UnwindDestructStack(ls); + if (f == FLOW_RETURN) return FLOW_RETURN; else if (f == FLOW_BREAK) @@ -1177,8 +1254,19 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) if (exp->mLeft->mLeft->mRight) Eval(exp->mLeft->mLeft->mRight); } + UnwindDestructStack(ds); return FLOW_NEXT; + } + + case EX_CONSTRUCT: + if (exp->mLeft->mLeft) + Eval(exp->mLeft->mLeft); + + if (exp->mLeft->mRight) + mDestructStack.Push(exp->mLeft->mRight); + + return Execute(exp->mRight); case EX_VOID: return FLOW_NEXT; @@ -1189,6 +1277,12 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) } } +void ConstexprInterpreter::UnwindDestructStack(int level) +{ + while (mDestructStack.Size() > level) + Eval(mDestructStack.Pop()); +} + ConstexprInterpreter::ValueItem::ValueItem(void) : mByte(0), mBaseValue(nullptr) { diff --git a/oscar64/Constexpr.h b/oscar64/Constexpr.h index 8bb65b7..88f24e8 100644 --- a/oscar64/Constexpr.h +++ b/oscar64/Constexpr.h @@ -26,6 +26,7 @@ protected: Value(const Location& location); Value(Expression * exp); Value(const Location& location, Declaration * dec); + Value(const Location& location, Declaration* dec, int count); Value(const Value& value); Value(Value&& value); Value(Value * value, Declaration * type, int offset); @@ -70,6 +71,9 @@ protected: Declaration* GetConst(int offset, Declaration* type, LinkerSection* dataSection) const; }; + Value * NewValue(Expression* exp, Declaration* type, int size); + void DeleteValue(Value* v); + Value EvalCall(Expression* exp, ConstexprInterpreter* caller); Value EvalBinary(Expression* exp, const Value& vl, const Value& vr); Value EvalUnary(Expression* exp, const Value& vl); @@ -89,11 +93,16 @@ protected: }; Flow Execute(Expression* exp); + void UnwindDestructStack(int level); Declaration* mProcType; Location mLocation; LinkerSection* mDataSection; GrowingArray mParams, mLocals; + ExpandingArray mDestructStack; + ExpandingArray * mHeap; + Errors * mErrors; Value mResult; + }; \ No newline at end of file diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 672710b..5864598 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -85,6 +85,8 @@ enum ErrorID EERR_FUNCTION_TEMPLATE, EERR_INVALID_CONSTEXPR, + EERR_DOUBLE_FREE, + EERR_UNBALANCED_HEAP_USE, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, From 3374544ced805919c1811e9d95e3ebad46ffd225 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 10 Sep 2023 10:28:25 +0200 Subject: [PATCH 106/169] Fix base type compare in template check --- oscar64/Declaration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index d5ee14d..f20327a 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1453,7 +1453,7 @@ bool Declaration::IsSameTemplate(const Declaration* dec) const { if (this == dec) return true; - if (this->mType != mType) + if (this->mType != dec->mType) return false; if (mType == DT_CONST_FUNCTION) From c1ecf1c2811a3dd50756cfd674766bd2ef7c6f06 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 11 Sep 2023 08:04:09 +0200 Subject: [PATCH 107/169] Added bitfields --- autotest/autotest.bat | 3 + autotest/bitfields.cpp | 248 ++++++++++++++++++++++++++++ oscar64/ByteCodeGenerator.cpp | 13 +- oscar64/Compiler.cpp | 6 +- oscar64/Compiler.h | 2 +- oscar64/Declaration.cpp | 9 +- oscar64/Declaration.h | 4 +- oscar64/Emulator.cpp | 2 +- oscar64/Errors.h | 1 + oscar64/InterCode.cpp | 182 +++++++++++++++++++-- oscar64/InterCode.h | 1 + oscar64/InterCodeGenerator.cpp | 275 +++++++++++++++++++++++++++++--- oscar64/InterCodeGenerator.h | 6 +- oscar64/NativeCodeGenerator.cpp | 272 +++++++++++++++++++++++++++++-- oscar64/NativeCodeGenerator.h | 4 + oscar64/Parser.cpp | 116 +++++++++++++- oscar64/oscar64.cpp | 7 +- 17 files changed, 1083 insertions(+), 68 deletions(-) create mode 100644 autotest/bitfields.cpp diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 9d5a926..b5ed668 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -1,5 +1,8 @@ rem @echo off +@call :test bitfields.cpp +@if %errorlevel% neq 0 goto :error + @call :test opp_string.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/bitfields.cpp b/autotest/bitfields.cpp new file mode 100644 index 0000000..3e7cd44 --- /dev/null +++ b/autotest/bitfields.cpp @@ -0,0 +1,248 @@ +#include + +struct A +{ + char x : 4; + char y : 1; + char z : 3; +}; + +A a = {7, 1, 2}; + +void test_char_fit(void) +{ + assert(a.x == 7); + assert(a.y == 1); + assert(a.z == 2); + assert(sizeof(A) == 1); + + for(int i=0; i<16; i++) + { + a.x = i; + a.y = 0; + a.z = 3; + assert(a.x == i); + assert(a.y == 0); + assert(a.z == 3); + } +} + +struct B +{ + char x : 6; + char y : 6; + char z : 6; + char w : 6; +}; + +B b = {11, 22, 33, 44}; + +void test_char_cross(void) +{ + assert(b.x == 11); + assert(b.y == 22); + assert(b.z == 33); + assert(b.w == 44); + assert(sizeof(B) == 3); + + for(int i=0; i<64; i++) + { + b.x = i * 1; + b.y = i * 3; + b.z = i * 5; + b.w = i * 7; + assert(b.x == ((i * 1) & 0x3f)); + assert(b.y == ((i * 3) & 0x3f)); + assert(b.z == ((i * 5) & 0x3f)); + assert(b.w == ((i * 7) & 0x3f)); + } +} + +struct C +{ + unsigned x : 4; + unsigned y : 1; + unsigned z : 3; +}; + +C c = {7, 1, 2}; + +void test_word_fit(void) +{ + assert(c.x == 7); + assert(c.y == 1); + assert(c.z == 2); + assert(sizeof(C) == 1); + + for(int i=0; i<16; i++) + { + c.x = i; + c.y = 0; + c.z = 3; + assert(c.x == i); + assert(c.y == 0); + assert(c.z == 3); + } +} + +struct D +{ + unsigned x : 10; + unsigned y : 10; + unsigned z : 10; + unsigned w : 10; +}; + +D d = {111, 222, 333, 444}; + +void test_word_cross(void) +{ + assert(d.x == 111); + assert(d.y == 222); + assert(d.z == 333); + assert(d.w == 444); + assert(sizeof(D) == 5); + + for(int i=0; i<1024; i++) + { + d.x = i * 1; + d.y = i * 3; + d.z = i * 5; + d.w = i * 7; + assert(d.x == ((i * 1) & 0x3ff)); + assert(d.y == ((i * 3) & 0x3ff)); + assert(d.z == ((i * 5) & 0x3ff)); + assert(d.w == ((i * 7) & 0x3ff)); + } +} + +struct E +{ + unsigned long x : 4; + unsigned long y : 1; + unsigned long z : 3; +}; + +E e = {7, 1, 2}; + +void test_dword_fit(void) +{ + assert(e.x == 7); + assert(e.y == 1); + assert(e.z == 2); + assert(sizeof(E) == 1); + + for(int i=0; i<16; i++) + { + e.x = i; + e.y = 0; + e.z = 3; + assert(e.x == i); + assert(e.y == 0); + assert(e.z == 3); + } +} + +struct F +{ + unsigned long x : 20; + unsigned long y : 20; + unsigned long z : 20; + unsigned long w : 20; +}; + +F f = {111111UL, 222222UL, 333333UL, 444444UL}; + +void test_dword_cross(void) +{ + assert(f.x == 111111UL); + assert(f.y == 222222UL); + assert(f.z == 333333UL); + assert(f.w == 444444UL); + assert(sizeof(F) == 10); + + for(int i=0; i<1024; i++) + { + f.x = i * 11UL; + f.y = i * 33UL; + f.z = i * 55UL; + f.w = i * 77UL; + assert(f.x == ((i * 11UL) & 0xfffffUL)); + assert(f.y == ((i * 33UL) & 0xfffffUL)); + assert(f.z == ((i * 55UL) & 0xfffffUL)); + assert(f.w == ((i * 77UL) & 0xfffffUL)); + } +} + +struct G +{ + signed char x : 1; + signed char y : 5; + signed char z : 2; +}; + +G g = {0, -1, -2}; + +void test_char_signed(void) +{ + assert(g.x == 0); + assert(g.y == -1); + assert(g.z == -2); + assert(sizeof(G) == 1); + + for(int i=-16; i<16; i++) + { + g.x = -1; + g.y = i; + g.z = 1; + assert(g.x == -1); + assert(g.y == i); + assert(g.z == 1); + } +} + +struct H +{ + int x : 10; + int y : 10; + int z : 10; + int w : 10; +}; + +H h = {111, -222, -333, 444}; + +void test_word_signed(void) +{ + assert(h.x == 111); + assert(h.y == -222); + assert(h.z == -333); + assert(h.w == 444); + assert(sizeof(H) == 5); + + for(int i=-32; i<32; i++) + { + h.x = i * 1; + h.y = i * 3; + h.z = i * 5; + h.w = i * 7; + assert(h.x == i * 1); + assert(h.y == i * 3); + assert(h.z == i * 5); + assert(h.w == i * 7); + } +} + + +int main(void) +{ + test_char_fit(); + test_char_cross(); + test_word_fit(); + test_word_cross(); + test_dword_fit(); + test_dword_cross(); + test_char_signed(); + test_word_signed(); + + return 0; +} diff --git a/oscar64/ByteCodeGenerator.cpp b/oscar64/ByteCodeGenerator.cpp index 5707d8a..c3c9b03 100644 --- a/oscar64/ByteCodeGenerator.cpp +++ b/oscar64/ByteCodeGenerator.cpp @@ -4246,8 +4246,8 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns case IA_SAR: { ByteCode rbc = ByteCodeBinRegOperator(ins); - ByteCode ibc = ByteCodeBinImmOperator(ins); + if (ins->mSrc[1].mTemp < 0) { IntConstToAccu(ins->mSrc[1].mIntConst); @@ -4259,18 +4259,25 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns } else if (ins->mSrc[0].mTemp < 0) { - ByteCodeInstruction lins(BC_LOAD_REG_16); + ByteCodeInstruction lins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; lins.mRegisterFinal = ins->mSrc[1].mFinal; mIns.Push(lins); + if (ins->mOperator == IA_SAR && InterTypeSize[ins->mSrc[1].mType] == 1) + { + ByteCodeInstruction xins(BC_CONV_I8_I16); + xins.mRegister = BC_REG_ACCU; + mIns.Push(xins); + } + ByteCodeInstruction bins(ibc); bins.mValue = int(ins->mSrc[0].mIntConst); mIns.Push(bins); } else { - ByteCodeInstruction lins(BC_LOAD_REG_16); + ByteCodeInstruction lins(InterTypeSize[ins->mSrc[1].mType] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16); lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; lins.mRegisterFinal = ins->mSrc[1].mFinal && (ins->mSrc[1].mTemp != ins->mSrc[0].mTemp);; mIns.Push(lins); diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 7a2a995..518da0d 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -1236,7 +1236,7 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64) return true; } -int Compiler::ExecuteCode(bool profile, bool trace) +int Compiler::ExecuteCode(bool profile, int trace) { Location loc; @@ -1249,12 +1249,12 @@ int Compiler::ExecuteCode(bool profile, bool trace) memcpy(emu->mMemory + mLinker->mProgramStart, mLinker->mMemory + mLinker->mProgramStart, mLinker->mProgramEnd - mLinker->mProgramStart); emu->mMemory[0x2d] = mLinker->mProgramEnd & 0xff; emu->mMemory[0x2e] = mLinker->mProgramEnd >> 8; - ecode = emu->Emulate(2061, trace ? 2 : 0); + ecode = emu->Emulate(2061, trace); } else if (mCompilerOptions & COPT_TARGET_CRT) { memcpy(emu->mMemory + 0x8000, mLinker->mMemory + 0x0800, 0x4000); - ecode = emu->Emulate(0x8009, trace ? 2 : 0); + ecode = emu->Emulate(0x8009, trace); } printf("Emulation result %d\n", ecode); diff --git a/oscar64/Compiler.h b/oscar64/Compiler.h index 67964b7..632b1fb 100644 --- a/oscar64/Compiler.h +++ b/oscar64/Compiler.h @@ -44,7 +44,7 @@ public: bool ParseSource(void); bool GenerateCode(void); bool WriteOutputFile(const char* targetPath, DiskImage * d64); - int ExecuteCode(bool profile, bool trace); + int ExecuteCode(bool profile, int trace); void AddDefine(const Ident* ident, const char* value); diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index f20327a..fa28538 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -819,6 +819,8 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio dec->mBase = mLeft->mDecValue; dec->mOffset = mDecValue->mOffset; dec->mSize = mDecValue->mSize; + dec->mBits = mDecValue->mBits; + dec->mShift = mDecValue->mShift; ex->mDecValue = dec; ex->mDecType = mDecType; return ex; @@ -831,6 +833,8 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio dec->mBase = mLeft->mDecValue->mBase; dec->mOffset = mLeft->mDecValue->mOffset + mDecValue->mOffset; dec->mSize = mDecValue->mSize; + dec->mBits = mDecValue->mBits; + dec->mShift = mDecValue->mShift; ex->mDecValue = dec; ex->mDecType = mDecType; return ex; @@ -880,14 +884,15 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), - mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), + mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), mMutable(nullptr), mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), mVTable(nullptr), mTemplate(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), - mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr) + mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr), + mShift(0), mBits(0) {} Declaration::~Declaration(void) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index e98a54d..4b5e7bb 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -29,9 +29,6 @@ enum DecType DT_TYPE_ASSEMBLER, DT_TYPE_AUTO, - DT_TYPE_CONST, - DT_TYPE_VOLATILE, - DT_CONST_INTEGER, DT_CONST_FLOAT, DT_CONST_FUNCTION, @@ -264,6 +261,7 @@ public: Expression* mValue; DeclarationScope* mScope; int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe; + uint8 mShift, mBits; int64 mInteger, mMinValue, mMaxValue; double mNumber; uint64 mFlags, mCompilerOptions; diff --git a/oscar64/Emulator.cpp b/oscar64/Emulator.cpp index 7bc4421..3f32dc2 100644 --- a/oscar64/Emulator.cpp +++ b/oscar64/Emulator.cpp @@ -649,7 +649,7 @@ int Emulator::Emulate(int startIP, int trace) break; } - if ((trace & 1) && ip == 0x0855) + if ((trace & 1) && ip == 0x0862) { unsigned accu = mMemory[BC_REG_ACCU] + (mMemory[BC_REG_ACCU + 1] << 8) + (mMemory[BC_REG_ACCU + 2] << 16) + (mMemory[BC_REG_ACCU + 3] << 24); int ptr = mMemory[BC_REG_ADDR] + 256 * mMemory[BC_REG_ADDR + 1]; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 5864598..c66d7c4 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -83,6 +83,7 @@ enum ErrorID EERR_NON_STATIC_MEMBER, EERR_TEMPLATE_PARAMS, EERR_FUNCTION_TEMPLATE, + EERR_INVALID_BITFIELD, EERR_INVALID_CONSTEXPR, EERR_DOUBLE_FREE, diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 0ba2108..ae5f7bb 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -643,6 +643,16 @@ static bool SameMem(const InterOperand& op, const InterInstruction* ins) return false; } +static bool SameMemAndSize(const InterOperand& op, const InterInstruction* ins) +{ + if (ins->mCode == IC_LOAD) + return SameMemAndSize(op, ins->mSrc[0]); + else if (ins->mCode == IC_STORE) + return SameMemAndSize(op, ins->mSrc[1]); + else + return false; +} + static bool SameInstruction(const InterInstruction* ins1, const InterInstruction* ins2) { if (ins1->mCode == ins2->mCode && ins1->mNumOperands == ins2->mNumOperands) @@ -7252,11 +7262,36 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray case IA_SHL: if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp >= 0) { - if (vr.mMinState == IntegerValueRange::S_BOUND) - ins->mSrc[1].mRange.LimitMin(vr.mMinValue >> ins->mSrc[0].mIntConst); - if (vr.mMaxState == IntegerValueRange::S_BOUND) - ins->mSrc[1].mRange.LimitMax(vr.mMaxValue >> ins->mSrc[0].mIntConst); - mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange); + if (ins->mDst.mType == IT_INT16) + { + if (vr.mMinState == IntegerValueRange::S_BOUND && vr.mMinValue >= -0x4000 && + vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMaxValue < 0x4000) + { + ins->mSrc[1].mRange.LimitMin(vr.mMinValue >> ins->mSrc[0].mIntConst); + ins->mSrc[1].mRange.LimitMax(vr.mMaxValue >> ins->mSrc[0].mIntConst); + mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange); + } + } + else if (ins->mDst.mType == IT_INT8) + { + if (vr.mMinState == IntegerValueRange::S_BOUND && vr.mMinValue >= -0x40 && + vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMaxValue < 0x40) + { + ins->mSrc[1].mRange.LimitMin(vr.mMinValue >> ins->mSrc[0].mIntConst); + ins->mSrc[1].mRange.LimitMax(vr.mMaxValue >> ins->mSrc[0].mIntConst); + mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange); + } + } + else if (ins->mDst.mType == IT_INT32) + { + if (vr.mMinState == IntegerValueRange::S_BOUND && vr.mMinValue >= -0x40000000 && + vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMaxValue < 0x40000000) + { + ins->mSrc[1].mRange.LimitMin(vr.mMinValue >> ins->mSrc[0].mIntConst); + ins->mSrc[1].mRange.LimitMax(vr.mMaxValue >> ins->mSrc[0].mIntConst); + mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange); + } + } } break; case IA_SUB: @@ -8559,6 +8594,72 @@ bool InterCodeBasicBlock::RemoveUnusedStoreInstructions(const GrowingVariableArr } +bool InterCodeBasicBlock::RemoveUnusedIndirectStoreInstructions(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + ExpandingArray stores; + + for (int i = mInstructions.Size() - 1; i >= 0; i--) + { + InterInstruction* ins = mInstructions[i]; + + if (ins->mCode == IC_STORE) + { + int j = 0; + while (j < stores.Size() && !SameMemAndSize(ins->mSrc[1], stores[j]->mSrc[1])) + j++; + + if (j < stores.Size()) + { + if (ins->mVolatile) + stores[j] = ins; + else + { + ins->mCode = IC_NONE; + ins->mNumOperands = 0; + } + } + else + { + j = 0; + while (j < stores.Size()) + { + if (CollidingMem(ins, stores[j])) + stores.Remove(j); + else + j++; + } + stores.Push(ins); + } + } + else + { + int j = 0; + while (j < stores.Size()) + { + if (CollidingMem(ins, stores[j]) || ins->mDst.mTemp >= 0 && ins->mDst.mTemp == stores[j]->mSrc[1].mTemp) + stores.Remove(j); + else + j++; + } + } + } + + if (mTrueJump && mTrueJump->RemoveUnusedIndirectStoreInstructions()) + changed = true; + if (mFalseJump && mFalseJump->RemoveUnusedIndirectStoreInstructions()) + changed = true; + } + + return changed; +} + + bool InterCodeBasicBlock::EliminateAliasValues(const GrowingInstructionPtrArray& tvalue, const GrowingInstructionPtrArray& avalue) { bool changed = false; @@ -9867,7 +9968,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& if (ins->mCode == IC_LOAD) { j = 0; - while (j < tvalue.Size() && !SameMem(ins->mSrc[0], tvalue[j])) + while (j < tvalue.Size() && !SameMemAndSize(ins->mSrc[0], tvalue[j])) j++; if (j < tvalue.Size()) { @@ -9880,7 +9981,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& else if (ins->mCode == IC_STORE) { j = 0; - while (j < tvalue.Size() && !SameMem(ins->mSrc[1], tvalue[j])) + while (j < tvalue.Size() && !SameMemAndSize(ins->mSrc[1], tvalue[j])) j++; if (j < tvalue.Size()) { @@ -9945,7 +10046,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& if (!ins->mVolatile) { int j = 0; - while (j < mLoadStoreInstructions.Size() && !SameMem(ins->mSrc[0], mLoadStoreInstructions[j])) + while (j < mLoadStoreInstructions.Size() && !SameMemAndSize(ins->mSrc[0], mLoadStoreInstructions[j])) j++; if (j < mLoadStoreInstructions.Size()) { @@ -9986,7 +10087,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& { int j = 0, k = 0; - while (j < mLoadStoreInstructions.Size() && !SameMem(ins->mSrc[1], mLoadStoreInstructions[j])) + while (j < mLoadStoreInstructions.Size() && !SameMemAndSize(ins->mSrc[1], mLoadStoreInstructions[j])) j++; if (!ins->mVolatile && j < mLoadStoreInstructions.Size() && mLoadStoreInstructions[j]->mCode == IC_LOAD && ins->mSrc[0].mTemp == mLoadStoreInstructions[j]->mDst.mTemp) @@ -14541,7 +14642,6 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray int64 mshift = mInstructions[i + 1]->mSrc[0].mIntConst; mInstructions[i + 0]->mOperator = IA_AND; - mInstructions[i + 0]->mSrc[0].mType = IT_INT16; mInstructions[i + 0]->mSrc[0].mType = mInstructions[i + 1]->mSrc[0].mType; switch (mInstructions[i + 0]->mSrc[1].mType) @@ -14584,6 +14684,61 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray } } #endif +#if 1 + else if ( + mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_SHL && mInstructions[i + 0]->mSrc[0].mTemp < 0 && + mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 1]->mOperator == IA_SHR && mInstructions[i + 1]->mSrc[0].mTemp < 0 && + mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal) + { + + int64 shift = mInstructions[i + 0]->mSrc[0].mIntConst; + if (shift & 7) + { + int64 mshift = mInstructions[i + 1]->mSrc[0].mIntConst; + + mInstructions[i + 0]->mOperator = IA_AND; + mInstructions[i + 0]->mSrc[0].mType = mInstructions[i + 1]->mSrc[0].mType; + + switch (mInstructions[i + 0]->mSrc[1].mType) + { + case IT_INT8: + mInstructions[i + 0]->mSrc[0].mIntConst = 0xffu >> shift; + break; + case IT_INT16: + mInstructions[i + 0]->mSrc[0].mIntConst = 0xffffu >> shift; + break; + case IT_INT32: + mInstructions[i + 0]->mSrc[0].mIntConst = 0xffffffffu >> shift; + break; + } + + if (shift > mshift && mInstructions[i + 0]->mDst.mType > mInstructions[i + 1]->mSrc[1].mType) + { + mInstructions[i + 1]->mSrc[1].mType = mInstructions[i + 0]->mDst.mType; + mInstructions[i + 1]->mDst.mType = mInstructions[i + 0]->mDst.mType; + } + + if (shift > mshift) + { + mInstructions[i + 1]->mOperator = IA_SHL; + mInstructions[i + 1]->mSrc[0].mIntConst = shift - mshift; + } + else if (shift < mshift) + { + mInstructions[i + 1]->mOperator = IA_SHR; + mInstructions[i + 1]->mSrc[0].mIntConst = mshift - shift; + } + else + { + mInstructions[i + 0]->mDst = mInstructions[i + 1]->mDst; + mInstructions[i + 1]->mCode = IC_NONE; + mInstructions[i + 1]->mNumOperands = 0; + } + + changed = true; + } + } +#endif #if 1 else if ( mInstructions[i + 0]->mCode == IC_LOAD_TEMPORARY && @@ -16507,6 +16662,11 @@ void InterCodeProcedure::RemoveUnusedStoreInstructions(InterMemory paramMemory) DisassembleDebug("removed unused static stores"); } + + // Remove unused indirect stores + + ResetVisited(); + mEntryBlock->RemoveUnusedIndirectStoreInstructions(); } } @@ -16921,7 +17081,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "test"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index fbe4d86..c8435f1 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -428,6 +428,7 @@ public: void BuildGlobalProvidedVariableSet(const GrowingVariableArray& localVars, NumberSet fromProvidedVars, const GrowingVariableArray& params, NumberSet fromProvidedParams, InterMemory paramMemory); bool BuildGlobalRequiredVariableSet(const GrowingVariableArray& localVars, NumberSet& fromRequiredVars, const GrowingVariableArray& params, NumberSet& fromRequiredParams, InterMemory paramMemory); bool RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars, const GrowingVariableArray& params, InterMemory paramMemory); + bool RemoveUnusedIndirectStoreInstructions(void); void BuildStaticVariableSet(const GrowingVariableArray& staticVars); void BuildGlobalProvidedStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet fromProvidedVars); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index e683d77..cfaceda 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -68,16 +68,220 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* ins->mDst.mRange.LimitMin(v.mType->mMinValue); ins->mDst.mRange.LimitMax(v.mType->mMaxValue); } + if (v.mType->mFlags & DTF_VOLATILE) ins->mVolatile = true; block->Append(ins); - v = ExValue(v.mType, ins->mDst.mTemp, v.mReference - 1); + if (v.mReference == 1 && v.mBits) + { + if (v.mBits + v.mShift <= 8) + ins->mDst.mType = IT_INT8; + else if (v.mBits + v.mShift <= 16) + ins->mDst.mType = IT_INT16; + else + ins->mDst.mType = IT_INT32; + + ins->mSrc[0].mOperandSize = InterTypeSize[ins->mDst.mType]; + int nbits = ins->mSrc[0].mOperandSize * 8; + + InterInstruction* clsins = new InterInstruction(exp->mLocation, IC_CONSTANT); + clsins->mDst.mType = IT_INT8; + clsins->mDst.mTemp = proc->AddTemporary(clsins->mDst.mType); + clsins->mConst.mType = IT_INT8; + clsins->mConst.mIntConst = nbits - v.mShift - v.mBits; + clsins->mNumOperands = 0; + block->Append(clsins); + + InterInstruction* crsins = new InterInstruction(exp->mLocation, IC_CONSTANT); + crsins->mDst.mType = IT_INT8; + crsins->mDst.mTemp = proc->AddTemporary(crsins->mDst.mType); + crsins->mConst.mType = IT_INT8; + crsins->mConst.mIntConst = nbits - v.mBits; + crsins->mNumOperands = 0; + block->Append(crsins); + + InterInstruction* slins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + slins->mOperator = IA_SHL; + slins->mDst.mType = ins->mDst.mType; + slins->mDst.mTemp = proc->AddTemporary(slins->mDst.mType); + slins->mSrc[1] = ins->mDst; + slins->mSrc[0] = clsins->mDst; + slins->mNumOperands = 2; + block->Append(slins); + + InterInstruction* srins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + srins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_SAR : IA_SHR; + srins->mDst.mType = ins->mDst.mType; + srins->mDst.mTemp = proc->AddTemporary(slins->mDst.mType); + srins->mSrc[1] = slins->mDst; + srins->mSrc[0] = crsins->mDst; + srins->mNumOperands = 2; + block->Append(srins); + + if (InterTypeSize[ins->mDst.mType] < v.mType->mSize) + { + InterInstruction* crins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + crins->mDst.mType = InterTypeOf(v.mType); + crins->mDst.mTemp = proc->AddTemporary(crins->mDst.mType); + crins->mSrc[0] = srins->mDst; + crins->mNumOperands = 1; + if (ins->mDst.mType == IT_INT16) + crins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_EXT16TO32S : IA_EXT16TO32U; + else if (v.mType->mSize == 2) + crins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_EXT8TO16S : IA_EXT8TO16U; + else + crins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_EXT8TO32S : IA_EXT8TO32U; + block->Append(crins); + v = ExValue(v.mType, crins->mDst.mTemp, v.mReference - 1); + } + else + v = ExValue(v.mType, srins->mDst.mTemp, v.mReference - 1); + } + else + v = ExValue(v.mType, ins->mDst.mTemp, v.mReference - 1, v.mBits, v.mShift); } return v; } +void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr) +{ + // Bitfield assignment + if (vl.mBits) + { + InterType itype; + + if (vl.mBits + vl.mShift <= 8) + itype = IT_INT8; + else if (vl.mBits + vl.mShift <= 16) + itype = IT_INT16; + else + itype = IT_INT32; + + int nbits = InterTypeSize[itype] * 8; + + InterInstruction* lins = new InterInstruction(exp->mLocation, IC_LOAD); + lins->mDst.mType = itype; + lins->mDst.mTemp = proc->AddTemporary(lins->mDst.mType); + lins->mSrc[0].mMemory = IM_INDIRECT; + lins->mSrc[0].mType = IT_POINTER; + lins->mSrc[0].mTemp = vl.mTemp; + lins->mSrc[0].mOperandSize = InterTypeSize[itype]; + lins->mVolatile = vl.mType->mFlags & DTF_VOLATILE; + lins->mNumOperands = 1; + block->Append(lins); + + InterInstruction* csins = new InterInstruction(exp->mLocation, IC_CONSTANT); + csins->mDst.mType = IT_INT8; + csins->mDst.mTemp = proc->AddTemporary(csins->mDst.mType); + csins->mConst.mType = IT_INT8; + csins->mConst.mIntConst = vl.mShift; + csins->mNumOperands = 0; + block->Append(csins); + + InterInstruction* cmsins = new InterInstruction(exp->mLocation, IC_CONSTANT); + cmsins->mDst.mType = itype; + cmsins->mDst.mTemp = proc->AddTemporary(cmsins->mDst.mType); + cmsins->mConst.mType = itype; + cmsins->mConst.mIntConst = ((1 << vl.mBits) - 1) << vl.mShift; + cmsins->mNumOperands = 0; + block->Append(cmsins); + + InterInstruction* cmlins = new InterInstruction(exp->mLocation, IC_CONSTANT); + cmlins->mDst.mType = itype; + cmlins->mDst.mTemp = proc->AddTemporary(cmlins->mDst.mType); + cmlins->mConst.mType = itype; + cmlins->mConst.mIntConst = ~cmsins->mConst.mIntConst; + cmlins->mNumOperands = 0; + block->Append(cmlins); + + int rtemp = vr.mTemp; + + if (InterTypeSize[itype] > vr.mType->mSize) + { + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + + if (InterTypeSize[itype] == 2) + cins->mOperator = IA_EXT8TO16U; + else if (vr.mType->mSize == 1) + cins->mOperator = IA_EXT8TO32U; + else + cins->mOperator = IA_EXT8TO16U; + + cins->mDst.mType = itype; + cins->mDst.mTemp = proc->AddTemporary(itype); + cins->mSrc[0].mTemp = rtemp; + cins->mSrc[0].mType = InterTypeOf(vr.mType); + block->Append(cins); + + rtemp = cins->mDst.mTemp; + } + + InterInstruction* sins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + sins->mOperator = IA_SHL; + sins->mDst.mType = itype; + sins->mDst.mTemp = proc->AddTemporary(sins->mDst.mType); + sins->mSrc[1].mTemp = rtemp; + sins->mSrc[1].mType = itype; + sins->mSrc[0] = csins->mDst; + sins->mNumOperands = 2; + block->Append(sins); + + InterInstruction* msins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + msins->mOperator = IA_AND; + msins->mDst.mType = itype; + msins->mDst.mTemp = proc->AddTemporary(msins->mDst.mType); + msins->mSrc[0] = sins->mDst; + msins->mSrc[1] = cmsins->mDst; + msins->mNumOperands = 2; + block->Append(msins); + + InterInstruction* mlins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + mlins->mOperator = IA_AND; + mlins->mDst.mType = itype; + mlins->mDst.mTemp = proc->AddTemporary(mlins->mDst.mType); + mlins->mSrc[0] = lins->mDst; + mlins->mSrc[1] = cmlins->mDst; + mlins->mNumOperands = 2; + block->Append(mlins); + + InterInstruction* oins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + oins->mOperator = IA_OR; + oins->mDst.mType = itype; + oins->mDst.mTemp = proc->AddTemporary(oins->mDst.mType); + oins->mSrc[0] = msins->mDst; + oins->mSrc[1] = mlins->mDst; + oins->mNumOperands = 2; + block->Append(oins); + + InterInstruction* ins = new InterInstruction(exp->mLocation, IC_STORE); + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mSrc[0] = oins->mDst; + ins->mSrc[1].mType = IT_POINTER; + ins->mSrc[1].mTemp = vl.mTemp; + ins->mSrc[1].mOperandSize = InterTypeSize[itype]; + ins->mVolatile = vl.mType->mFlags & DTF_VOLATILE; + ins->mNumOperands = 2; + block->Append(ins); + } + else + { + InterInstruction* ins = new InterInstruction(exp->mLocation, IC_STORE); + + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mSrc[0].mType = InterTypeOf(vr.mType); + ins->mSrc[0].mTemp = vr.mTemp; + ins->mSrc[1].mType = IT_POINTER; + ins->mSrc[1].mTemp = vl.mTemp; + ins->mSrc[1].mOperandSize = vl.mType->mSize; + ins->mSrc[1].mStride = vl.mType->mStripe; + ins->mVolatile = vl.mType->mFlags & DTF_VOLATILE; + ins->mNumOperands = 2; + block->Append(ins); + } +} + InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration* type, bool checkTrunc) { int stemp = v.mTemp; @@ -1713,6 +1917,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mConst.mOperandSize = dec->mSize; ins->mConst.mIntConst = dec->mOffset; + int lbits = dec->mBits, lshift = dec->mShift; + if (dec->mType == DT_VARIABLE_REF) dec = dec->mBase; @@ -1779,13 +1985,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (exp->mDecType->IsReference()) return ExValue(exp->mDecType->mBase, ins->mDst.mTemp, ref + 1); else - return ExValue(exp->mDecType, ins->mDst.mTemp, ref); + return ExValue(exp->mDecType, ins->mDst.mTemp, ref, lbits, lshift); } case EX_ASSIGNMENT: case EX_INITIALIZATION: - { + { if (exp->mLeft->mDecType && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT) { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); @@ -1902,8 +2108,6 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mReference != 1) mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not a left hand expression"); - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_STORE); - if (exp->mToken != TK_ASSIGN) { ExValue vll = Dereference(proc, exp, block, vl); @@ -2043,17 +2247,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = CoerceType(proc, exp, block, vr, vl.mType); } - ins->mCode = IC_STORE; - ins->mSrc[1].mMemory = IM_INDIRECT; - ins->mSrc[0].mType = InterTypeOf(vr.mType); - ins->mSrc[0].mTemp = vr.mTemp; - ins->mSrc[1].mType = IT_POINTER; - ins->mSrc[1].mTemp = vl.mTemp; - ins->mSrc[1].mOperandSize = vl.mType->mSize; - ins->mSrc[1].mStride = vl.mType->mStripe; - ins->mVolatile = vl.mType->mFlags & DTF_VOLATILE; - ins->mNumOperands = 2; - block->Append(ins); + StoreValue(proc, exp, block, vl, vr); } } @@ -2151,7 +2345,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); block->Append(ains); - return ExValue(exp->mDecValue->mBase, ains->mDst.mTemp, 1); + return ExValue(exp->mDecValue->mBase, ains->mDst.mTemp, 1, exp->mDecValue->mBits, exp->mDecValue->mShift); } case EX_BINARY: @@ -2483,7 +2677,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mType->mFlags & DTF_CONST) mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot change const value"); - InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT), * ains = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR), * sins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONSTANT), * ains = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);// , * sins = new InterInstruction(exp->mLocation, IC_STORE); ExValue vdl = Dereference(proc, exp, block, vl); @@ -2524,6 +2718,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); block->Append(ains); + StoreValue(proc, exp, block, vl, ExValue(vl.mType, ains->mDst.mTemp)); +#if 0 sins->mSrc[1].mMemory = IM_INDIRECT; sins->mSrc[0].mType = ains->mDst.mType; sins->mSrc[0].mTemp = ains->mDst.mTemp; @@ -2532,6 +2728,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* sins->mSrc[1].mOperandSize = vl.mType->mSize; sins->mVolatile = vl.mType->mFlags & DTF_VOLATILE; block->Append(sins); +#endif // Return reference to value return ExValue(vl.mType, vl.mTemp, 1); @@ -2550,7 +2747,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mType->mFlags & DTF_CONST) mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot change const value"); - InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT), * ains = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR), * sins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONSTANT), * ains = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);// , * sins = new InterInstruction(exp->mLocation, IC_STORE); ExValue vdl = Dereference(proc, exp, block, vl); @@ -2590,6 +2787,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ains->mDst.mTemp = proc->AddTemporary(ttype); block->Append(ains); + StoreValue(proc, exp, block, vl, ExValue(vl.mType, ains->mDst.mTemp)); +#if 0 sins->mSrc[1].mMemory = IM_INDIRECT; sins->mSrc[0].mType = ains->mDst.mType; sins->mSrc[0].mTemp = ains->mDst.mTemp; @@ -2598,7 +2797,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* sins->mSrc[1].mOperandSize = vl.mType->mSize; sins->mVolatile = vl.mType->mFlags & DTF_VOLATILE; block->Append(sins); - +#endif return ExValue(vdl.mType, vdl.mTemp); } break; @@ -2642,7 +2841,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* return ExValue(vl.mType->mBase, vl.mTemp, vl.mReference + 1); case TK_BINARY_AND: { - if (vl.mReference < 1) + if (vl.mReference < 1 || vl.mBits) mErrors->Error(exp->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable value"); Declaration* dec = new Declaration(exp->mLocation, DT_TYPE_POINTER); @@ -4582,10 +4781,38 @@ void InterCodeGenerator::BuildInitializer(InterCodeModule * mod, uint8* dp, int else if (data->mType == DT_CONST_INTEGER) { int64 t = data->mInteger; - for (int i = 0; i < data->mBase->mSize; i++) + if (data->mBits) { - dp[offset + i * data->mBase->mStripe] = uint8(t & 0xff); - t >>= 8; + if (data->mBits + data->mShift <= 8) + { + uint8 mask = uint8(((1 << data->mBits) - 1) << data->mShift); + dp[offset] = (dp[offset] & ~mask) | (uint8(t << data->mShift) & mask); + } + else if (data->mBits + data->mShift <= 16) + { + uint16 mask = uint16(((1 << data->mBits) - 1) << data->mShift); + + dp[offset + 0] = (dp[offset + 0] & ~(mask & 0xff)) | (uint8(t << data->mShift) & (mask & 0xff)); + dp[offset + 1] = (dp[offset + 1] & ~(mask >> 8)) | (uint8(t >> (8 - data->mShift)) & (mask >> 8)); + } + else + { + uint32 mask = uint32(((1 << data->mBits) - 1) << data->mShift); + t = (t << data->mShift) & mask; + + dp[offset + 0] = (dp[offset + 0] & ~(mask & 0xff)) | (uint8(t )); + dp[offset + 1] = (dp[offset + 1] & ~(mask >> 8)) | (uint8(t >> 8)); + dp[offset + 2] = (dp[offset + 2] & ~(mask >> 16)) | (uint8(t >> 16)); + dp[offset + 3] = (dp[offset + 3] & ~(mask >> 24)) | (uint8(t >> 24)); + } + } + else + { + for (int i = 0; i < data->mBase->mSize; i++) + { + dp[offset + i * data->mBase->mStripe] = uint8(t & 0xff); + t >>= 8; + } } } else if (data->mType == DT_CONST_ADDRESS) diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index ac637a2..79f9bb0 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -21,9 +21,10 @@ public: { Declaration* mType; int mTemp, mReference; + int mBits, mShift; - ExValue(Declaration* type = nullptr, int temp = -1, int reference = 0) - : mType(type), mTemp(temp), mReference(reference) + ExValue(Declaration* type = nullptr, int temp = -1, int reference = 0, int bits = 0, int shift = 0) + : mType(type), mTemp(temp), mReference(reference), mBits(bits), mShift(shift) {} }; @@ -86,6 +87,7 @@ protected: void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper); ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp); void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving); + void StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr); void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom, InlineMapper* inlineMapper); void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 539d07a..4b11ac5 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -9788,7 +9788,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; int shift = ins->mSrc[0].mIntConst & 15; - if (ins->mDst.IsUByte()) + if (ins->mDst.IsUByte() || InterTypeSize[ins->mDst.mType] == 1) { if (shift == 0) { @@ -9834,8 +9834,11 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg)); } - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (InterTypeSize[ins->mDst.mType] > 1) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } } else { @@ -10045,7 +10048,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p { int shift = ins->mSrc[0].mIntConst & 15; #if 1 - if (ins->mSrc[1].IsUByte()) + if (ins->mSrc[1].IsUByte() || InterTypeSize[ins->mSrc[1].mType] == 1) { if (shift == 0) { @@ -10053,8 +10056,11 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p { mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (InterTypeSize[ins->mDst.mType] > 1) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } } } else if (shift == 7) @@ -10062,7 +10068,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (InterTypeSize[ins->mDst.mType] > 1) + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); } @@ -10074,14 +10081,18 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ins, ASMIT_AND, ASMIM_IMMEDIATE, 3)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (InterTypeSize[ins->mDst.mType] > 1) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } } else if (shift >= 8) { mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (InterTypeSize[ins->mDst.mType] > 1) + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } else { @@ -10089,8 +10100,11 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p for (int i = 0; i < shift; i++) mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + if (InterTypeSize[ins->mDst.mType] > 1) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); + } } } else @@ -10377,6 +10391,33 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1)); } } + else if (InterTypeSize[ins->mDst.mType] == 1) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + + if (shift > 5) + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED)); + for (int i = shift; i < 8; i++) + mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_AND, ASMIM_IMMEDIATE, 0xff >> shift)); + + mIns.Push(NativeCodeInstruction(ins, ASMIT_EOR, ASMIM_IMMEDIATE, 0x80 >> shift)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_SEC, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_SBC, ASMIM_IMMEDIATE, 0x80 >> shift)); + } + else if (shift > 0) + { + for (int i = 0; i < shift; i++) + mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED)); + + mIns.Push(NativeCodeInstruction(ins, ASMIT_EOR, ASMIM_IMMEDIATE, 0x80 >> shift)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_SEC, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_SBC, ASMIM_IMMEDIATE, 0x80 >> shift)); + } + + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0)); + } else if (ins->mSrc[1].IsSByte() && shift != 0 && shift < 5) { mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); @@ -18939,6 +18980,148 @@ bool NativeCodeBasicBlock::ShortcutPointerAddForward(void) return changed; } +bool NativeCodeBasicBlock::MoveIndirectLoadZeroStoreDown(int at) +{ + int yval = mIns[at].mAddress; + + for (int i = at + 3; i < mIns.Size(); i++) + { + if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[at + 2].mAddress) + { + if (mIns[i].mLive & LIVE_CPU_REG_Y) + return false; + mIns.Insert(i, mIns[at]); + mIns.Insert(i + 1, mIns[at + 1]); + mIns[i + 2].mType = ASMIT_STA; + mIns[i].mLive |= mIns[i + 2].mLive; + mIns[i + 1].mLive |= mIns[i + 2].mLive; + mIns.Remove(at + 1, 2); + return true; + } + + if (mIns[i].ChangesZeroPage(mIns[at + 1].mAddress) || mIns[i].ChangesZeroPage(mIns[at + 1].mAddress + 1) || mIns[i].ReferencesZeroPage(mIns[at + 2].mAddress)) + return false; + + if (mIns[i].mType == ASMIT_JSR) + return false; + + if (mIns[i].ChangesAddress()) + { + if (mIns[i].mMode == ASMIM_INDIRECT_Y && mIns[i].mAddress == mIns[at + 1].mAddress) + { + if (yval == -1 || yval == mIns[at].mAddress) + return false; + } + else if (mIns[at + 1].MayBeChangedOnAddress(mIns[i])) + return false; + } + + if (mIns[i].ChangesYReg()) + { + if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_IMMEDIATE) + yval = mIns[i].mAddress; + else if (mIns[i].mType == ASMIT_INY && yval >= 0) + yval = (yval + 1) & 255; + else if (mIns[i].mType == ASMIT_DEY && yval >= 0) + yval = (yval - 1) & 255; + else + yval = -1; + } + + } + + return false; +} + +bool NativeCodeBasicBlock::MoveLoadZeroStoreIndirectUp(int at) +{ + int i = at - 1; + while (i >= 0 && !(mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == mIns[at].mAddress)) + i--; + + if (i >= 0 && mIns[i].mType == ASMIT_STA && !(mIns[i].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_Y))) + { + int yval = -1; + for (int j = i + 1; j < at; j++) + { + if (mIns[j].mType == ASMIT_JSR) + return false; + if (mIns[j].ChangesZeroPage(mIns[at + 2].mAddress) || mIns[j].ChangesZeroPage(mIns[at + 2].mAddress + 1)) + return false; + + if (mIns[j].mMode == ASMIM_INDIRECT_Y && mIns[j].mAddress == mIns[at + 2].mAddress) + { + if (yval == -1 || yval == mIns[at].mAddress) + return false; + } + else if (mIns[j].MayBeSameAddress(mIns[at + 2])) + return false; + + if (mIns[j].ChangesYReg()) + { + if (mIns[j].mType == ASMIT_LDY && mIns[j].mMode == ASMIM_IMMEDIATE) + yval = mIns[j].mAddress; + else if (mIns[j].mType == ASMIT_INY && yval >= 0) + yval = (yval + 1) & 255; + else if (mIns[j].mType == ASMIT_DEY && yval >= 0) + yval = (yval - 1) & 255; + else + yval = -1; + } + } + + NativeCodeInstruction i0 = mIns[at + 1], i1 = mIns[at + 2]; + mIns.Remove(at + 1, 2); + + mIns.Insert(i + 1, i0); + mIns.Insert(i + 2, i1); + mIns[i].mLive |= LIVE_CPU_REG_A; + mIns[i + 1].mLive |= mIns[i].mLive; + mIns[i + 2].mLive |= mIns[i].mLive; + + return true; + } + + return false; +} + + +bool NativeCodeBasicBlock::ShortcutIndirectLoadStore(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i + 2 < mIns.Size(); i++) + { + if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_INDIRECT_Y && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) && + mIns[i + 2].mAddress != mIns[i + 1].mAddress && mIns[i + 2].mAddress != mIns[i + 1].mAddress + 1) + { + if (MoveIndirectLoadZeroStoreDown(i)) + changed = true; + } + else if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_LDY && mIns[i + 1].mMode == ASMIM_IMMEDIATE && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))) + { + if (MoveLoadZeroStoreIndirectUp(i)) + changed = true; + } + } + + if (mTrueJump && mTrueJump->ShortcutIndirectLoadStore()) + changed = true; + if (mFalseJump && mFalseJump->ShortcutIndirectLoadStore()) + changed = true; + } + + return changed; +} + #if 0 static int NativeCodeExpressionID; @@ -34683,6 +34866,39 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #endif +#if 1 + for (int i = 0; i + 1 < mIns.Size(); i++) + { + if (mIns[i + 0].mType == ASMIT_ASL && mIns[i + 0].mMode == ASMIM_IMPLIED && + mIns[i + 1].mType == ASMIT_LSR && mIns[i + 1].mMode == ASMIM_IMPLIED && !(mIns[i + 1].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_C))) + { + int j = 1; + while (i >= j && i + j + 1 < mIns.Size() && + mIns[i - j].mType == ASMIT_ASL && mIns[i - j].mMode == ASMIM_IMPLIED && + mIns[i + 1 + j].mType == ASMIT_LSR && mIns[i + 1 + j].mMode == ASMIM_IMPLIED && !(mIns[i + 1 + j].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_C))) + j++; + mIns[i + 1 - j].mType = ASMIT_AND; + mIns[i + 1 - j].mMode = ASMIM_IMMEDIATE; + mIns[i + 1 - j].mAddress = 0xff >> j; + + while (j > 1) + { + mIns[i + j].mType = ASMIT_NOP; + mIns[i + j].mMode = ASMIM_IMPLIED; + j--; + mIns[i + 1 - j].mType = ASMIT_NOP; + mIns[i + 1 - j].mMode = ASMIM_IMPLIED; + } + mIns[i + 1].mType = ASMIT_NOP; + mIns[i + 1].mMode = ASMIM_IMPLIED; + changed = true; + } + } + + CheckLive(); + +#endif + #if 1 bool progress = false; do { @@ -36740,6 +36956,19 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; progress = true; } +#endif +#if 1 + else if ( + mIns[i + 0].mType == ASMIT_LSR && mIns[i + 0].mMode == ASMIM_IMPLIED && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 && + mIns[i + 2].mType == ASMIT_ROL && mIns[i + 2].mMode == ASMIM_IMPLIED && !(mIns[i + 2].mLive & LIVE_CPU_REG_C)) + { + mIns[i + 1].mType = ASMIT_AND; mIns[i + 1].mAddress = 1; + mIns[i + 0].mAddress &= (mIns[i + 2].mAddress << 1) | 1; + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + progress = true; + } #endif else if ( mIns[i + 0].IsShift() && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && @@ -36984,6 +37213,15 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns.Remove(i + 2); progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_LDA && + mIns[i + 1].mType == ASMIT_STA && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].SameEffectiveAddress(mIns[i + 0]) && + !(mIns[i + 0].mMode == ASMIM_INDIRECT_Y && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && (mIns[i + 1].mAddress == mIns[i + 0].mAddress || mIns[i + 1].mAddress + 1 == mIns[i + 0].mAddress))) + { + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + progress = true; + } if ( mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress <= 1 && @@ -40915,7 +41153,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "test"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41688,6 +41926,14 @@ void NativeCodeProcedure::Optimize(void) changed = true; #endif + + if (step == 2) + { + ResetVisited(); + if (mEntryBlock->ShortcutIndirectLoadStore()) + changed = true; + } + #if 1 if (step >= 3) { diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 044061b..9f2b280 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -604,6 +604,10 @@ public: bool CheckShortcutPointerAddForward(int at); bool ShortcutPointerAddForward(void); + bool ShortcutIndirectLoadStore(void); + bool MoveIndirectLoadZeroStoreDown(int at); + bool MoveLoadZeroStoreIndirectUp(int at); + bool CommonSubExpressionElimination(void); bool CheckPatchFailReg(const NativeCodeBasicBlock* block, int reg); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index e6d845c..6c9a421 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -231,6 +231,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio } else { + int bitsleft = 0; + Declaration* mlast = nullptr; for (;;) { @@ -334,7 +336,103 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio mdec->mType = DT_ELEMENT; mdec->mOffset = offset; - offset += mdec->mBase->mSize; + if (mdec->mBits) + { + if (mdec->mBits <= 8) + { + if (bitsleft == 0) + { + bitsleft = 8 - mdec->mBits; + offset++; + } + else if (bitsleft >= mdec->mBits) + { + mdec->mOffset--; + mdec->mShift = 8 - bitsleft; + bitsleft -= mdec->mBits; + } + else + { + mdec->mOffset--; + mdec->mShift = 8 - bitsleft; + bitsleft = 8 + bitsleft - mdec->mBits; + offset++; + } + } + else if (mdec->mBits <= 16) + { + if (bitsleft == 0) + { + bitsleft = 16 - mdec->mBits; + offset += 2; + } + else if (bitsleft + 8 >= mdec->mBits) + { + mdec->mOffset--; + mdec->mShift = 8 - bitsleft; + bitsleft = bitsleft + 8 - mdec->mBits; + offset++; + } + else + { + mdec->mOffset -= 3; + mdec->mShift = 24 - bitsleft; + bitsleft = bitsleft + 16 - mdec->mBits; + offset += 2; + } + } + else if (mdec->mBits <= 24) + { + if (bitsleft == 0) + { + bitsleft = 24 - mdec->mBits; + offset += 3; + } + else if (bitsleft + 16 >= mdec->mBits) + { + mdec->mOffset -= 2; + mdec->mShift = 16 - bitsleft; + bitsleft = bitsleft + 16 - mdec->mBits; + offset += 2; + } + else + { + mdec->mOffset -= 1; + mdec->mShift = 8 - bitsleft; + bitsleft = bitsleft + 24 - mdec->mBits; + offset += 3; + } + } + else + { + if (bitsleft == 0) + { + bitsleft = 32 - mdec->mBits; + offset += 4; + } + else if (bitsleft + 24 >= mdec->mBits) + { + mdec->mOffset--; + mdec->mShift = 8 - bitsleft; + bitsleft = bitsleft + 24 - mdec->mBits; + offset+=2; + } + else + { + bitsleft = 32 - mdec->mBits; + offset += mdec->mBase->mSize; + } + } + + if (mdec->mShift == 0 && mdec->mBits == 8 * mdec->mSize) + mdec->mBits = 0; + } + else + { + bitsleft = 0; + offset += mdec->mBase->mSize; + } + if (offset > dec->mSize) dec->mSize = offset; @@ -1409,6 +1507,8 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) Expression* texp = ParseInitExpression(mdec->mBase); Declaration* cdec = CopyConstantInitializer(mdec->mOffset, mdec->mBase, texp); + cdec->mBits = mdec->mBits; + cdec->mShift = mdec->mShift; if (last) last->mNext = cdec; @@ -4043,9 +4143,19 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex ldec = ndec; // ndec->mNext = nullptr; - if (mScanner->mToken == TK_ASSIGN) + if (ConsumeTokenIf(TK_COLON)) + { + Expression* exp = ParseRExpression(); + if (!ndec->mBase->IsIntegerType()) + mErrors->Error(exp->mLocation, EERR_INVALID_BITFIELD, "Invalid bitfíeld for non integer type"); + else if (exp->mType == EX_CONSTANT && exp->mDecType->IsIntegerType() && exp->mDecValue->mType == DT_CONST_INTEGER) + ndec->mBits = uint8(exp->mDecValue->mInteger); + else + mErrors->Error(exp->mLocation, EERR_CONSTANT_TYPE, "Constant integer expression expected"); + } + + if (ConsumeTokenIf(TK_ASSIGN)) { - mScanner->NextToken(); ndec->mValue = ParseInitExpression(ndec->mBase); if (ndec->mBase->mType == DT_TYPE_AUTO) { diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 55b6271..53d3af2 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -116,7 +116,8 @@ int main2(int argc, const char** argv) strcpy_s(crtPath, includePath); strcat_s(crtPath, "crt.c"); - bool emulate = false, profile = false, trace = false; + bool emulate = false, profile = false; + int trace = 0; targetPath[0] = 0; diskPath[0] = 0; @@ -211,7 +212,9 @@ int main2(int argc, const char** argv) if (arg[2] == 'p') profile = true; else if (arg[2] == 't') - trace = true; + trace = 2; + else if (arg[2] == 'b') + trace = 1; } else if (arg[1] == 'd') { From 1b50baf8521b5d8e00729d3c4102cec0a5ae2a21 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 11 Sep 2023 13:03:07 +0200 Subject: [PATCH 108/169] Fix wrong unicode character in error message --- oscar64/Parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 6c9a421..4781396 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -4147,7 +4147,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { Expression* exp = ParseRExpression(); if (!ndec->mBase->IsIntegerType()) - mErrors->Error(exp->mLocation, EERR_INVALID_BITFIELD, "Invalid bitfíeld for non integer type"); + mErrors->Error(exp->mLocation, EERR_INVALID_BITFIELD, "Invalid bitfield for non integer type"); else if (exp->mType == EX_CONSTANT && exp->mDecType->IsIntegerType() && exp->mDecValue->mType == DT_CONST_INTEGER) ndec->mBits = uint8(exp->mDecValue->mInteger); else From ab49281b0df3ba932107735c00d0703f2a1e564c Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 11 Sep 2023 16:19:11 +0200 Subject: [PATCH 109/169] Implement operator() --- oscar64/Parser.cpp | 67 ++++++++++++++++++++++++++++++++++++++------- oscar64/Scanner.cpp | 7 +++++ 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 4781396..bede094 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -5744,6 +5744,8 @@ Expression* Parser::ParsePostfixExpression(bool lhs) } else { + Expression* thisExp = nullptr; + if (exp->mDecType->mType == DT_TYPE_POINTER && exp->mDecType->mBase->mType == DT_TYPE_FUNCTION) { } @@ -5752,8 +5754,38 @@ Expression* Parser::ParsePostfixExpression(bool lhs) } else { - mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Function expected for call"); - exp->mDecType = TheVoidFunctionTypeDeclaration; + Declaration* tdec = exp->mDecType; + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) + tdec = tdec->mBase; + + if (tdec->mType == DT_TYPE_STRUCT && tdec->mScope) + { + const Ident* opident = Ident::Unique("operator()"); + + Declaration* mdec = tdec->mScope->Lookup(opident); + if (mdec) + { + thisExp = new Expression(exp->mLocation, EX_PREFIX); + thisExp->mToken = TK_BINARY_AND; + thisExp->mLeft = exp; + thisExp->mDecType = exp->mDecType->BuildPointer(exp->mLocation); + + exp = new Expression(exp->mLocation, EX_CONSTANT); + exp->mDecValue = mdec; + exp->mDecType = mdec->mBase; + } + else + { + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Function expected for call"); + exp->mDecType = TheVoidFunctionTypeDeclaration; + } + } + else + { + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Function expected for call"); + exp->mDecType = TheVoidFunctionTypeDeclaration; + } + } mScanner->NextToken(); @@ -5775,23 +5807,38 @@ Expression* Parser::ParsePostfixExpression(bool lhs) } bool parentCall = false; - if ((exp->mDecType->mFlags & DTF_FUNC_THIS) && mThisPointer && mThisPointer->mType == DT_ARGUMENT) + if (thisExp) { - Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE); - texp->mDecType = mThisPointer->mBase; - texp->mDecValue = mThisPointer; - if (nexp->mRight) { Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp; + lexp->mLeft = thisExp; lexp->mRight = nexp->mRight; nexp->mRight = lexp; } else - nexp->mRight = texp; + nexp->mRight = thisExp; + } + else + { + if ((exp->mDecType->mFlags & DTF_FUNC_THIS) && mThisPointer && mThisPointer->mType == DT_ARGUMENT) + { + Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE); + texp->mDecType = mThisPointer->mBase; + texp->mDecValue = mThisPointer; - parentCall = true; + if (nexp->mRight) + { + Expression* lexp = new Expression(nexp->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = nexp->mRight; + nexp->mRight = lexp; + } + else + nexp->mRight = texp; + + parentCall = true; + } } nexp = ResolveOverloadCall(nexp); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 39e8efb..516228c 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1626,6 +1626,13 @@ void Scanner::NextRawToken(void) mTokenIdent = Ident::Unique("operator[]"); break; + case TK_OPEN_PARENTHESIS: + NextRawToken(); + if (mToken != TK_CLOSE_PARENTHESIS) + mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "')' expected"); + mTokenIdent = Ident::Unique("operator()"); + break; + case TK_ARROW: mTokenIdent = Ident::Unique("operator->"); break; From c926456560b851325195cadaf20cc04bb2ee57db Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 11 Sep 2023 17:49:04 +0200 Subject: [PATCH 110/169] Add simple return type deduction --- oscar64/BitVector.h | 4 ++-- oscar64/Compiler.cpp | 10 ++++++++-- oscar64/Declaration.cpp | 2 +- oscar64/DiskImage.cpp | 5 ++++- oscar64/InterCode.h | 2 +- oscar64/NativeCodeGenerator.cpp | 4 ++-- oscar64/NumberSet.cpp | 8 ++++++++ oscar64/Parser.cpp | 15 +++++++++++---- oscar64/Parser.h | 2 +- oscar64/Scanner.cpp | 3 +++ 10 files changed, 41 insertions(+), 14 deletions(-) diff --git a/oscar64/BitVector.h b/oscar64/BitVector.h index ebe5300..e3c1fcf 100644 --- a/oscar64/BitVector.h +++ b/oscar64/BitVector.h @@ -71,7 +71,7 @@ inline BitVector::BitVector(int size, unsigned char * data) else bits = nullptr; - if (size) + if (size > 0) { memcpy(bits, data, (size + 7) / 8); } @@ -93,7 +93,7 @@ inline BitVector::BitVector(int size, bool set) else bits = NULL; - if (size) + if (size > 0) { if (set) { diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 518da0d..a0d9cb7 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -1067,7 +1067,7 @@ bool Compiler::BuildLZO(const char* targetPath) CompilationUnit* cunit; - char data[65536]; + char * data = new char[65536]; int n = 0; while (mErrors->mErrorCount == 0 && (cunit = mCompilationUnits->PendingUnit())) @@ -1110,14 +1110,20 @@ bool Compiler::BuildLZO(const char* targetPath) { int done = fwrite(data, 1, n, file); fclose(file); + delete[] data; return done == n; } else + { + delete[] data; return false; + } } else + { + delete[] data; return false; - + } } bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index fa28538..9e111b1 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -882,7 +882,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio } Declaration::Declaration(const Location& loc, DecType type) - : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), + : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mMangleIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), mMutable(nullptr), diff --git a/oscar64/DiskImage.cpp b/oscar64/DiskImage.cpp index 13b1020..5b5be37 100644 --- a/oscar64/DiskImage.cpp +++ b/oscar64/DiskImage.cpp @@ -250,7 +250,7 @@ bool DiskImage::WriteFile(const char* fname, bool compressed) if (OpenFile(dname)) { - uint8 buffer[65536], cbuffer[65536]; + uint8 * buffer = new uint8[65536], * cbuffer = new uint8[65536]; int size = fread(buffer, 1, 65536, file); int csize = 0; @@ -311,6 +311,9 @@ bool DiskImage::WriteFile(const char* fname, bool compressed) else WriteBytes(buffer, size); CloseFile(); + + delete[] buffer; + delete[] cbuffer; } fclose(file); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index c8435f1..1c8e973 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -245,7 +245,7 @@ class InterVariable { public: bool mUsed, mAliased, mTemp; - int mIndex, mSize, mOffset, mAddr, mTempIndex; + int mIndex, mSize, mOffset, mTempIndex; int mNumReferences; const Ident * mIdent; LinkerObject * mLinkerObject; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 4b11ac5..44470aa 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -22386,8 +22386,8 @@ bool NativeCodeBasicBlock::PatchCrossBlock16BitFlood(const NativeCodeBasicBlock* mPatchExit = true; - mExitRequiredRegs |= sreg; - mExitRequiredRegs |= sreg + 1; + mExitRequiredRegs += sreg; + mExitRequiredRegs += sreg + 1; if (mTrueJump && mTrueJump->PatchCrossBlock16BitFlood(block, sreg, dreg, 0)) changed = true; diff --git a/oscar64/NumberSet.cpp b/oscar64/NumberSet.cpp index 5fa614b..c3f857b 100644 --- a/oscar64/NumberSet.cpp +++ b/oscar64/NumberSet.cpp @@ -120,6 +120,8 @@ NumberSet& NumberSet::operator=(const NumberSet& set) NumberSet& NumberSet::operator&=(const NumberSet& set) { + assert(dwsize == set.dwsize); + int size = dwsize; const uint32* sbits = set.bits; uint32* dbits = bits; @@ -132,6 +134,8 @@ NumberSet& NumberSet::operator&=(const NumberSet& set) NumberSet& NumberSet::operator|=(const NumberSet& set) { + assert(dwsize == set.dwsize); + int size = dwsize; const uint32* sbits = set.bits; uint32* dbits = bits; @@ -144,6 +148,8 @@ NumberSet& NumberSet::operator|=(const NumberSet& set) NumberSet& NumberSet::operator-=(const NumberSet& set) { + assert(dwsize == set.dwsize); + int i; for (i = 0; i < dwsize; i++) @@ -154,6 +160,8 @@ NumberSet& NumberSet::operator-=(const NumberSet& set) bool NumberSet::operator<=(const NumberSet& set) const { + assert(dwsize == set.dwsize); + int i; for (i = 0; i < dwsize; i++) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index bede094..d5f5601 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -20,6 +20,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn mCompilerOptionSP = 0; mThisPointer = nullptr; mFunction = nullptr; + mFunctionType = nullptr; for (int i = 0; i < 256; i++) mCharMap[i] = i; @@ -7110,7 +7111,7 @@ Expression* Parser::ParseFunction(Declaration * dec) if (dec->mFlags & DTF_FUNC_THIS) mThisPointer = dec->mParams; - mReturnType = dec->mBase; + mFunctionType = dec; DeclarationScope* oscope = mScope; while (mScope->mLevel == SLEVEL_CLASS) @@ -7508,10 +7509,16 @@ Expression* Parser::ParseStatement(void) if (mScanner->mToken != TK_SEMICOLON) { exp->mLeft = ParseRExpression(); - if (mReturnType) - exp->mLeft = CoerceExpression(exp->mLeft, mReturnType); + if (mFunctionType && mFunctionType->mBase) + { + if (mFunctionType->mBase->mType == DT_TYPE_AUTO) + { + mFunctionType->mBase = exp->mLeft->mDecType; + } + exp->mLeft = CoerceExpression(exp->mLeft, mFunctionType->mBase); + } exp->mLeft = CleanupExpression(exp->mLeft); - if (exp->mLeft->mType == EX_CONSTRUCT && mReturnType && mReturnType->mType == DT_TYPE_STRUCT) + if (exp->mLeft->mType == EX_CONSTRUCT && mFunctionType && mFunctionType->mBase && mFunctionType->mBase->mType == DT_TYPE_STRUCT) { Expression* cexp = exp->mLeft->mLeft->mLeft; diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 064be45..150113a 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -15,7 +15,7 @@ public: DeclarationScope * mGlobals, * mScope, * mTemplateScope; int mLocalIndex; CompilationUnits * mCompilationUnits; - Declaration * mThisPointer, * mReturnType, * mFunction; + Declaration * mThisPointer, * mFunctionType, * mFunction; LinkerSection * mCodeSection, * mDataSection, * mBSSection; diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 516228c..5b23920 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1277,6 +1277,7 @@ void Scanner::NextRawToken(void) { int n = 0; char tkprep[128]; + tkprep[0] = 0; while (NextChar() && IsAlpha(mTokenChar)) { @@ -1371,6 +1372,8 @@ void Scanner::NextRawToken(void) { int n = 0; char tkident[256]; + tkident[0] = 0; + for (;;) { if (IsIdentChar(mTokenChar)) From 2b51f20b1c4b3cbd7177b33b5d24e8212b040794 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 12 Sep 2023 15:36:24 +0200 Subject: [PATCH 111/169] Add lambda --- oscar64/CompilationUnits.cpp | 10 +- oscar64/CompilationUnits.h | 4 + oscar64/Constexpr.cpp | 6 +- oscar64/Errors.h | 1 + oscar64/GlobalAnalyzer.cpp | 4 +- oscar64/Ident.cpp | 7 + oscar64/Ident.h | 1 + oscar64/InterCode.cpp | 2 +- oscar64/InterCodeGenerator.cpp | 8 +- oscar64/Parser.cpp | 337 ++++++++++++++++++++++++++++++++- oscar64/Parser.h | 6 +- 11 files changed, 376 insertions(+), 10 deletions(-) diff --git a/oscar64/CompilationUnits.cpp b/oscar64/CompilationUnits.cpp index 9db05f7..a8cf2e2 100644 --- a/oscar64/CompilationUnits.cpp +++ b/oscar64/CompilationUnits.cpp @@ -7,8 +7,8 @@ #include #include -CompilationUnits::CompilationUnits(Errors * errors) - : mErrors(errors), mReferenced(nullptr) +CompilationUnits::CompilationUnits(Errors* errors) + : mErrors(errors), mReferenced(nullptr), mUniqueID(0) { mCompilationUnits = nullptr; mPendingUnits = nullptr; @@ -27,6 +27,12 @@ CompilationUnits::~CompilationUnits(void) } +int CompilationUnits::UniqueID(void) +{ + return mUniqueID++; +} + + void CompilationUnits::AddReferenced(Declaration* ref) { mReferenced.Push(ref); diff --git a/oscar64/CompilationUnits.h b/oscar64/CompilationUnits.h index 47d829d..2891f25 100644 --- a/oscar64/CompilationUnits.h +++ b/oscar64/CompilationUnits.h @@ -31,6 +31,10 @@ public: LinkerSection* mSectionCode, * mSectionData, * mSectionBSS, * mSectionHeap, * mSectionStack, * mSectionZeroPage, * mSectionLowCode, * mSectionBoot; Linker* mLinker; + int mUniqueID; + + int UniqueID(void); + bool AddUnit(Location & location, const char* name, const char * from); CompilationUnit* PendingUnit(void); diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index c4237aa..134e477 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -839,7 +839,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalUnary(Expression* exp, con case TK_MUL: return vl.GetPtr(); case TK_NEW: - v.PutPtr(Value(NewValue(exp, exp->mDecType->mBase, vl.GetInt()))); + v.PutPtr(Value(NewValue(exp, exp->mDecType->mBase, int(vl.GetInt())))); break; case TK_DELETE: DeleteValue(vl.GetPtr().mBaseValue); @@ -1266,7 +1266,9 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) if (exp->mLeft->mRight) mDestructStack.Push(exp->mLeft->mRight); - return Execute(exp->mRight); + if (exp->mRight) + return Execute(exp->mRight); + return FLOW_NEXT; case EX_VOID: return FLOW_NEXT; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index c66d7c4..c2d4b5c 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -84,6 +84,7 @@ enum ErrorID EERR_TEMPLATE_PARAMS, EERR_FUNCTION_TEMPLATE, EERR_INVALID_BITFIELD, + EERR_INVALID_CAPTURE, EERR_INVALID_CONSTEXPR, EERR_DOUBLE_FREE, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index da869c5..64d910e 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -919,7 +919,9 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo Analyze(exp->mLeft->mLeft, procDec, false); if (exp->mLeft->mRight) Analyze(exp->mLeft->mRight, procDec, false); - return Analyze(exp->mRight, procDec, false); + if (exp->mRight) + return Analyze(exp->mRight, procDec, false); + break; case EX_CLEANUP: Analyze(exp->mRight, procDec, false); diff --git a/oscar64/Ident.cpp b/oscar64/Ident.cpp index 9bd9e5c..e0c0305 100644 --- a/oscar64/Ident.cpp +++ b/oscar64/Ident.cpp @@ -53,6 +53,13 @@ const Ident* Ident::PreMangle(const char* str) const return Unique(buffer); } +const Ident* Ident::Unique(const char* str, int id) +{ + char buffer[200]; + sprintf_s(buffer, "%s#%d", str, id); + return Unique(buffer); +} + const Ident* Ident::Mangle(const char* str) const { char buffer[200]; diff --git a/oscar64/Ident.h b/oscar64/Ident.h index de44870..93d1470 100644 --- a/oscar64/Ident.h +++ b/oscar64/Ident.h @@ -9,6 +9,7 @@ public: unsigned int mHash; static const Ident* Unique(const char* str); + static const Ident* Unique(const char* str, int id); const Ident* Mangle(const char* str) const; const Ident* PreMangle(const char* str) const; protected: diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index ae5f7bb..1189841 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -17081,7 +17081,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "test"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index cfaceda..256d784 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1635,6 +1635,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } exp = exp->mRight; + if (!exp) + return ExValue(TheVoidTypeDeclaration); } break; @@ -2054,6 +2056,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mSrc[1].mMemory = IM_INDIRECT; ins->mSrc[1].mOperandSize = 2; ins->mSrc[1].mStride = vl.mType->mStripe; + ins->mNumOperands = 2; block->Append(ins); } @@ -2345,7 +2348,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); block->Append(ains); - return ExValue(exp->mDecValue->mBase, ains->mDst.mTemp, 1, exp->mDecValue->mBits, exp->mDecValue->mShift); + if (exp->mDecType->IsReference()) + return ExValue(exp->mDecValue->mBase->mBase, ains->mDst.mTemp, 2); + else + return ExValue(exp->mDecValue->mBase, ains->mDst.mTemp, 1, exp->mDecValue->mBits, exp->mDecValue->mShift); } case EX_BINARY: diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index d5f5601..bdc857b 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -21,6 +21,8 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn mThisPointer = nullptr; mFunction = nullptr; mFunctionType = nullptr; + mLambda = nullptr; + mCaptureScope = nullptr; for (int i = 0; i < 256; i++) mCharMap[i] = i; @@ -4514,6 +4516,280 @@ Declaration* Parser::ParseQualIdent(void) return dec; } +Expression* Parser::ParseLambdaExpression(void) +{ + Declaration* cdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT); + cdec->mIdent = Ident::Unique("lambda", mCompilationUnits->UniqueID()); + cdec->mQualIdent = mScope->Mangle(cdec->mIdent); + cdec->mFlags |= DTF_DEFINED; + + cdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, cdec->mIdent); + + Declaration* olambda = mLambda; + mLambda = cdec; + + Token octoken = mCaptureToken; + mCaptureToken = TK_NONE; + + Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); + + Declaration* cpdec = cdec->BuildConstPointer(mScanner->mLocation); + + Declaration* fdec = new Declaration(mScanner->mLocation, DT_CONST_FUNCTION); + fdec->mIdent = Ident::Unique("operator()"); + fdec->mQualIdent = cdec->mScope->Mangle(fdec->mIdent); + cdec->mScope->Insert(fdec->mIdent, fdec); + + Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + pdec->mBase = cpdec; + pdec->mSize = 2; + + Expression* einit = nullptr; + + ConsumeToken(TK_OPEN_BRACKET); + if (!ConsumeTokenIf(TK_CLOSE_BRACKET)) + { + // Parse capture list list + do { + bool reference = false; + + if (ConsumeTokenIf(TK_BINARY_AND)) + { + if (mScanner->mToken == TK_IDENT) + reference = true; + else + mCaptureToken = TK_BINARY_AND; + } + + if (ConsumeTokenIf(TK_ASSIGN)) + mCaptureToken = TK_ASSIGN; + else if (ConsumeTokenIf(TK_THIS)) + { + Declaration* mdec = new Declaration(mScanner->mLocation, DT_ELEMENT); + mdec->mIdent = Ident::Unique("this"); + mdec->mQualIdent = cdec->mScope->Mangle(mdec->mIdent); + if (cdec->mScope->Insert(mdec->mIdent, mdec)) + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate lambda capture", mdec->mIdent); + + if (mThisPointer) + { + Expression* iexp = new Expression(mScanner->mLocation, EX_VARIABLE); + iexp->mDecType = mThisPointer->mBase; + iexp->mDecValue = mThisPointer; + + mdec->mBase = iexp->mDecType; + mdec->mValue = iexp; + mdec->mNext = cdec->mParams; + cdec->mParams = mdec; + } + else + mErrors->Error(mScanner->mLocation, ERRO_THIS_OUTSIDE_OF_METHOD, "Use of this outside of method"); + + mdec->mOffset = cdec->mSize; + mdec->mSize = mdec->mBase->mSize; + cdec->mSize += mdec->mSize; + } + else if (mScanner->mToken == TK_IDENT) + { + Declaration* mdec = new Declaration(mScanner->mLocation, DT_ELEMENT); + mdec->mIdent = mScanner->mTokenIdent; + mdec->mQualIdent = cdec->mScope->Mangle(mdec->mIdent); + if (cdec->mScope->Insert(mdec->mIdent, mdec)) + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate lambda capture", mdec->mIdent); + + Expression* iexp = nullptr; + + mScanner->NextToken(); + if (ConsumeTokenIf(TK_ASSIGN)) + iexp = ParseExpression(false); + else + { + Declaration* mvdec = mScope->Lookup(mdec->mIdent); + if (mvdec && mvdec->mType == DT_VARIABLE) + { + iexp = new Expression(mdec->mLocation, EX_VARIABLE); + iexp->mDecType = mvdec->mBase; + iexp->mDecValue = mvdec; + } + else + mErrors->Error(mdec->mLocation, EERR_INVALID_CAPTURE, "Invalid variable capture", mdec->mIdent); + } + + if (iexp) + { + if (reference) + mdec->mBase = iexp->mDecType->BuildReference(mdec->mLocation); + else + mdec->mBase = iexp->mDecType; + mdec->mValue = iexp; + mdec->mNext = cdec->mParams; + cdec->mParams = mdec; + } + + mdec->mOffset = cdec->mSize; + mdec->mSize = mdec->mBase->mSize; + cdec->mSize += mdec->mSize; + } + + } while (ConsumeTokenIf(TK_COMMA)); + + ConsumeToken(TK_CLOSE_BRACKET); + } + + Declaration* rtype = new Declaration(mScanner->mLocation, DT_TYPE_AUTO); + + if (mScanner->mToken == TK_OPEN_PARENTHESIS) + { + fdec->mBase = ParseFunctionDeclaration(rtype); + } + else + { + ConsumeToken(TK_OPEN_PARENTHESIS); + fdec->mBase = TheConstVoidTypeDeclaration; + } + + PrependThisArgument(fdec->mBase, cpdec); + + fdec->mFlags |= fdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + + fdec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + fdec->mFlags |= DTF_NATIVE; + + fdec->mCompilerOptions = mCompilerOptions; + fdec->mBase->mCompilerOptions = mCompilerOptions; + + fdec->mVarIndex = -1; + + int li = mLocalIndex; + + DeclarationScope * oscope = mCaptureScope; + mCaptureScope = mScope; + + while (mScope->mLevel >= SLEVEL_NAMESPACE) + mScope = mScope->mParent; + + fdec->mValue = ParseFunction(fdec->mBase); + + mScope = mCaptureScope; + mLambda = olambda; + mCaptureScope = oscope; + mCaptureToken = octoken; + + Declaration* pmdec = cdec->mParams; + while (pmdec) + { + Declaration* fcons = pmdec->mBase->mType == DT_TYPE_STRUCT && pmdec->mBase->mScope ? pmdec->mBase->mScope->Lookup(pmdec->mBase->mIdent->PreMangle("+"), SLEVEL_CLASS) : nullptr; + + Expression* ciexp; + + if (fcons) + { + Expression* vexp = new Expression(pmdec->mLocation, EX_QUALIFY); + vexp->mLeft = new Expression(pmdec->mLocation, EX_VARIABLE); + vexp->mLeft->mDecType = cdec; + vexp->mLeft->mDecValue = vdec; + vexp->mDecValue = pmdec; + vexp->mDecType = pmdec->mBase; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = fcons; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = pmdec->mValue; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = pmdec->mBase->BuildPointer(mScanner->mLocation); + + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = fexp->mRight; + fexp->mRight = lexp; + + fexp = ResolveOverloadCall(fexp); + + Expression* dexp = nullptr; + if (pmdec->mBase->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = pmdec->mBase->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + ciexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + ciexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + ciexp->mLeft->mLeft = fexp; + ciexp->mLeft->mRight = dexp; + } + else + { + ciexp = new Expression(pmdec->mLocation, EX_INITIALIZATION); + ciexp->mToken = TK_ASSIGN; + ciexp->mDecType = pmdec->mValue->mDecType; + ciexp->mRight = pmdec->mValue; + ciexp->mLeft = new Expression(pmdec->mLocation, EX_QUALIFY); + ciexp->mLeft->mLeft = new Expression(pmdec->mLocation, EX_VARIABLE); + ciexp->mLeft->mLeft->mDecType = cdec; + ciexp->mLeft->mLeft->mDecValue = vdec; + ciexp->mLeft->mDecValue = pmdec; + ciexp->mLeft->mDecType = pmdec->mBase; + } + + if (einit) + { + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = einit; + lexp->mRight = ciexp; + einit = lexp; + } + else + einit = ciexp; + + pmdec = pmdec->mNext; + } + + fdec->mFlags |= DTF_DEFINED | DTF_REQUEST_INLINE; + fdec->mNumVars = mLocalIndex; + + mLocalIndex = li; + + vdec->mBase = cdec; + vdec->mVarIndex = mLocalIndex++; + vdec->mSize = cdec->mSize; + vdec->mFlags |= DTF_DEFINED; + vdec->mIdent = cdec->mIdent; + + Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); + vexp->mDecType = vdec->mBase; + vexp->mDecValue = vdec; + + + if (einit) + { + Expression* conex = new Expression(mScanner->mLocation, EX_CONSTRUCT); + conex->mRight = vexp; + conex->mDecType = vexp->mDecType; + + conex->mLeft = new Expression(mScanner->mLocation, EX_LIST); + conex->mLeft->mLeft = einit; + conex->mLeft->mRight = nullptr; + + return conex; + } + else + return vexp; +} + Expression* Parser::ParseSimpleExpression(bool lhs) { Declaration* dec = nullptr; @@ -4701,7 +4977,31 @@ Expression* Parser::ParseSimpleExpression(bool lhs) mScanner->NextToken(); break; case TK_THIS: - if (mThisPointer) + if (mLambda) + { + dec = mLambda->mScope->Lookup(Ident::Unique("this"), SLEVEL_CLASS); + if (dec) + { + Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE); + texp->mDecType = mThisPointer->mBase; + texp->mDecValue = mThisPointer; + + Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX); + dexp->mToken = TK_MUL; + dexp->mDecType = texp->mDecType->mBase; + dexp->mLeft = texp; + + dexp = dexp->ConstantFold(mErrors, mDataSection); + + exp = new Expression(mScanner->mLocation, EX_QUALIFY); + exp->mLeft = dexp; + exp->mDecType = dec->mBase; + exp->mDecValue = dec; + } + else + mErrors->Error(mScanner->mLocation, ERRO_THIS_OUTSIDE_OF_METHOD, "Use of this outside of method"); + } + else if (mThisPointer) { exp = new Expression(mScanner->mLocation, EX_VARIABLE); exp->mDecType = mThisPointer->mBase; @@ -4713,6 +5013,35 @@ Expression* Parser::ParseSimpleExpression(bool lhs) mScanner->NextToken(); break; case TK_IDENT: + if (mLambda && mCaptureToken != TK_NONE && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS) && !mLambda->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS)) + { + Declaration * mvdec = mCaptureScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS); + if (mvdec && mvdec->mType == DT_VARIABLE) + { + Declaration* mdec = new Declaration(mScanner->mLocation, DT_ELEMENT); + mdec->mIdent = mScanner->mTokenIdent; + mdec->mQualIdent = mLambda->mScope->Mangle(mdec->mIdent); + if (mLambda->mScope->Insert(mdec->mIdent, mdec)) + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate lambda capture", mdec->mIdent); + + Expression* iexp = new Expression(mdec->mLocation, EX_VARIABLE); + iexp->mDecType = mvdec->mBase; + iexp->mDecValue = mvdec; + + if (mCaptureToken == TK_BINARY_AND) + mdec->mBase = iexp->mDecType->BuildReference(mdec->mLocation); + else + mdec->mBase = iexp->mDecType; + mdec->mValue = iexp; + mdec->mNext = mLambda->mParams; + mLambda->mParams = mdec; + + mdec->mOffset = mLambda->mSize; + mdec->mSize = mdec->mBase->mSize; + mLambda->mSize += mdec->mSize; + } + } + if (mThisPointer && mThisPointer->mType == DT_ARGUMENT && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION)) { int offset; @@ -4883,6 +5212,9 @@ Expression* Parser::ParseSimpleExpression(bool lhs) } } break; + case TK_OPEN_BRACKET: + exp = ParseLambdaExpression(); + break; case TK_ASM: mScanner->NextToken(); if (mScanner->mToken == TK_OPEN_BRACE) @@ -7108,6 +7440,8 @@ Expression* Parser::ParseListExpression(bool lhs) Expression* Parser::ParseFunction(Declaration * dec) { Declaration* othis = mThisPointer; + Declaration* ofunc = mFunctionType; + if (dec->mFlags & DTF_FUNC_THIS) mThisPointer = dec->mParams; @@ -7182,6 +7516,7 @@ Expression* Parser::ParseFunction(Declaration * dec) mScope = oscope; mThisPointer = othis; + mFunctionType = ofunc; return exp; } diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 150113a..e60ddbd 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -12,10 +12,11 @@ public: Parser* Clone(void); - DeclarationScope * mGlobals, * mScope, * mTemplateScope; + DeclarationScope * mGlobals, * mScope, * mTemplateScope, * mCaptureScope; int mLocalIndex; CompilationUnits * mCompilationUnits; - Declaration * mThisPointer, * mFunctionType, * mFunction; + Declaration * mThisPointer, * mFunctionType, * mFunction, * mLambda; + Token mCaptureToken; LinkerSection * mCodeSection, * mDataSection, * mBSSection; @@ -105,6 +106,7 @@ protected: void CompleteTemplateExpansion(Declaration* tmpld); Expression* ParseNewOperator(void); + Expression* ParseLambdaExpression(void); Expression* ParseSimpleExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs); From d94d52b852e3d371963918f982043fba41f2ed43 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 12 Sep 2023 15:44:16 +0200 Subject: [PATCH 112/169] fix assert in linux autotest --- oscar64/NumberSet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oscar64/NumberSet.cpp b/oscar64/NumberSet.cpp index c3f857b..9f269b0 100644 --- a/oscar64/NumberSet.cpp +++ b/oscar64/NumberSet.cpp @@ -134,9 +134,9 @@ NumberSet& NumberSet::operator&=(const NumberSet& set) NumberSet& NumberSet::operator|=(const NumberSet& set) { - assert(dwsize == set.dwsize); + assert(dwsize >= set.dwsize); - int size = dwsize; + int size = dwsize < set.dwsize ? dwsize : set.dwsize; const uint32* sbits = set.bits; uint32* dbits = bits; From eccb2787dc99fe331d4eb0598daffd9ab8a7f5d4 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 12 Sep 2023 21:33:59 +0200 Subject: [PATCH 113/169] Add simple range for loop --- oscar64/Declaration.cpp | 8 ++ oscar64/Declaration.h | 1 + oscar64/GlobalAnalyzer.cpp | 43 +++++- oscar64/InterCode.cpp | 21 +++ oscar64/Parser.cpp | 274 ++++++++++++++++++++++++++++++++----- 5 files changed, 306 insertions(+), 41 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 9e111b1..8fb23a2 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -956,6 +956,14 @@ Declaration* Declaration::BuildRValueRef(const Location& loc) return pdec; } +Declaration* Declaration::NonRefBase(void) +{ + if (IsReference()) + return mBase; + else + return this; +} + Declaration* Declaration::BuildConstRValueRef(const Location& loc) { Declaration* pdec = new Declaration(loc, DT_TYPE_RVALUEREF); diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 4b5e7bb..a4d1b70 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -309,6 +309,7 @@ public: Declaration* BuildConstReference(const Location& loc); Declaration* BuildRValueRef(const Location& loc); Declaration* BuildConstRValueRef(const Location& loc); + Declaration* NonRefBase(void); DecType ValueType(void) const; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 64d910e..609826b 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -155,12 +155,14 @@ void GlobalAnalyzer::AutoInline(void) Declaration* dec = f->mBase->mParams; while (dec) { - nparams++; + nparams += dec->mSize; dec = dec->mNext; } int cost = (f->mComplexity - 20 * nparams); +// printf("CHEK INLINING %s %d * (%d - 1)\n", f->mIdent->mString, cost, f->mCallers.Size()); + bool doinline = false; if ((f->mCompilerOptions & COPT_OPTIMIZE_INLINE) && (f->mFlags & DTF_REQUEST_INLINE)) doinline = true; @@ -171,9 +173,8 @@ void GlobalAnalyzer::AutoInline(void) if (doinline) { -#if 0 - printf("INLINING %s %d * (%d - 1)\n", f->mIdent->mString, cost, f->mCallers.Size()); -#endif +// printf("INLINING %s %d * (%d - 1)\n", f->mIdent->mString, cost, f->mCallers.Size()); + f->mFlags |= DTF_INLINE; for (int j = 0; j < f->mCallers.Size(); j++) { @@ -655,8 +656,6 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo { Declaration* ldec, * rdec; - procDec->mComplexity += 10; - switch (exp->mType) { case EX_ERROR: @@ -715,6 +714,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo return exp->mDecValue; case EX_INITIALIZATION: case EX_ASSIGNMENT: + procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; + ldec = Analyze(exp->mLeft, procDec, true); rdec = Analyze(exp->mRight, procDec, false); if (exp->mLeft->mType == EX_VARIABLE && exp->mRight->mType == EX_CALL && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT) @@ -723,16 +724,22 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo return ldec; case EX_BINARY: + procDec->mComplexity += 10 * exp->mDecType->mSize; + ldec = Analyze(exp->mLeft, procDec, lhs); rdec = Analyze(exp->mRight, procDec, lhs); return ldec; case EX_RELATIONAL: + procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; + ldec = Analyze(exp->mLeft, procDec, false); rdec = Analyze(exp->mRight, procDec, false); return TheBoolTypeDeclaration; case EX_PREINCDEC: + procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; + return Analyze(exp->mLeft, procDec, true); case EX_PREFIX: if (exp->mToken == TK_BINARY_AND) @@ -751,13 +758,21 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo return exp->mDecType; } else + { + procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; return Analyze(exp->mLeft, procDec, false); + } break; case EX_POSTFIX: + procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; break; case EX_POSTINCDEC: + procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; + return Analyze(exp->mLeft, procDec, true); case EX_INDEX: + procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; + ldec = Analyze(exp->mLeft, procDec, lhs); if (ldec->mType == DT_VARIABLE || ldec->mType == DT_ARGUMENT) { @@ -786,6 +801,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo // intentional fall through case EX_CALL: case EX_INLINE: + procDec->mComplexity += 10; + ldec = Analyze(exp->mLeft, procDec, false); if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue) { @@ -813,6 +830,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo { Expression* pex = rex->mType == EX_LIST ? rex->mLeft : rex; + procDec->mComplexity += 5 * pex->mDecType->mSize; + if (pdec && !(ldec->mBase->mFlags & DTF_VARIADIC) && !(ldec->mFlags & (DTF_INTRINSIC | DTF_FUNC_ASSEMBLER))) { #if 1 @@ -930,10 +949,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo case EX_WHILE: procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; + procDec->mComplexity += 20; + ldec = Analyze(exp->mLeft, procDec, false); rdec = Analyze(exp->mRight, procDec, false); break; case EX_IF: + procDec->mComplexity += 20; + ldec = Analyze(exp->mLeft, procDec, false); rdec = Analyze(exp->mRight->mLeft, procDec, false); if (exp->mRight->mRight) @@ -944,6 +967,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo case EX_FOR: procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; + procDec->mComplexity += 30; + if (exp->mLeft->mRight) ldec = Analyze(exp->mLeft->mRight, procDec, false); if (exp->mLeft->mLeft->mLeft) @@ -953,6 +978,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, false); break; case EX_DO: + procDec->mComplexity += 20; + ldec = Analyze(exp->mLeft, procDec, false); rdec = Analyze(exp->mRight, procDec, false); break; @@ -989,6 +1016,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo exp = exp->mRight; while (exp) { + procDec->mComplexity += 10; + if (exp->mLeft->mRight) rdec = Analyze(exp->mLeft->mRight, procDec, false); exp = exp->mRight; @@ -999,6 +1028,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo case EX_DEFAULT: break; case EX_CONDITIONAL: + procDec->mComplexity += exp->mDecType->mSize * 10; + ldec = Analyze(exp->mLeft, procDec, false); RegisterProc(Analyze(exp->mRight->mLeft, procDec, false)); RegisterProc(Analyze(exp->mRight->mRight, procDec, false)); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 1189841..28be3a2 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -3425,11 +3425,32 @@ bool InterInstruction::PropagateConstTemps(const GrowingInstructionPtrArray& cte } } + if (!changed) + { + if (mSrc[0].mType == IT_POINTER && mSrc[1].mType == IT_POINTER && + mSrc[0].mTemp >= 0 && mSrc[1].mTemp >= 0 && + ctemps[mSrc[0].mTemp] && ctemps[mSrc[1].mTemp]) + { + InterInstruction* si0 = ctemps[mSrc[0].mTemp]; + InterInstruction* si1 = ctemps[mSrc[1].mTemp]; + + if (si0->mConst.mMemory != IM_INDIRECT && si1->mConst.mMemory != IM_INDIRECT) + { + mCode = IC_CONSTANT; + mConst.mIntConst = ::ConstantRelationalPointerFolding(mOperator, si1->mConst, si0->mConst); + mConst.mType = IT_BOOL; + mNumOperands = 0; + return true; + } + } + } + if (changed) { this->ConstantFolding(); return true; } + } break; case IC_FREE: diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index bdc857b..5629a23 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2588,6 +2588,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); iexp->mToken = TK_INC; iexp->mLeft = pexp; + iexp->mDecType = pexp->mDecType; Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); fexp->mDecValue = pthis->mBase->mDefaultConstructor; @@ -2664,6 +2665,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); iexp->mToken = TK_INC; iexp->mLeft = pexp; + iexp->mDecType = pexp->mDecType; Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); fexp->mDecValue = pthis->mBase->mDestructor; @@ -2753,10 +2755,12 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); iexp->mToken = TK_INC; iexp->mLeft = pexp; + iexp->mDecType = pexp->mDecType; Expression* isexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); isexp->mToken = TK_INC; isexp->mLeft = psexp; + isexp->mDecType = psexp->mDecType; Expression* disexp = new Expression(mScanner->mLocation, EX_PREFIX); disexp->mToken = TK_MUL; @@ -2766,6 +2770,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); dexp->mToken = TK_DEC; dexp->mLeft = aexp; + dexp->mDecType = aexp->mDecType; Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); fexp->mDecValue = pthis->mBase->mCopyConstructor; @@ -2854,10 +2859,12 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); iexp->mToken = TK_INC; iexp->mLeft = pexp; + iexp->mDecType = pexp->mDecType; Expression* isexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); isexp->mToken = TK_INC; isexp->mLeft = psexp; + isexp->mDecType = psexp->mDecType; Expression* disexp = new Expression(mScanner->mLocation, EX_PREFIX); disexp->mToken = TK_MUL; @@ -2867,6 +2874,7 @@ void Parser::AddDefaultConstructors(Declaration* pthis) Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC); dexp->mToken = TK_DEC; dexp->mLeft = aexp; + dexp->mDecValue = aexp->mDecType; Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT); fexp->mDecValue = pthis->mBase->mCopyAssignment; @@ -4146,7 +4154,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex ldec = ndec; // ndec->mNext = nullptr; - if (ConsumeTokenIf(TK_COLON)) + if (!mFunctionType && ConsumeTokenIf(TK_COLON)) { Expression* exp = ParseRExpression(); if (!ndec->mBase->IsIntegerType()) @@ -4361,10 +4369,10 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) { while (dec) { + Expression* nexp; + if (dec->mValue && !(dec->mFlags & DTF_GLOBAL)) { - Expression* nexp; - if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mValue->mType == EX_CONSTRUCT) { nexp = dec->mValue; @@ -4446,21 +4454,27 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) nexp->mRight = dec->mValue; } + } + else + { + nexp = new Expression(dec->mLocation, EX_VARIABLE); + nexp->mDecValue = dec; + nexp->mDecType = dec->mBase; + } - if (!exp) - exp = nexp; - else + if (!exp) + exp = nexp; + else + { + if (!rexp) { - if (!rexp) - { - rexp = new Expression(nexp->mLocation, EX_SEQUENCE); - rexp->mLeft = exp; - exp = rexp; - } - rexp->mRight = new Expression(nexp->mLocation, EX_SEQUENCE); - rexp = rexp->mRight; - rexp->mLeft = nexp; + rexp = new Expression(nexp->mLocation, EX_SEQUENCE); + rexp->mLeft = exp; + exp = rexp; } + rexp->mRight = new Expression(nexp->mLocation, EX_SEQUENCE); + rexp = rexp->mRight; + rexp->mLeft = nexp; } dec = dec->mNext; @@ -5213,7 +5227,13 @@ Expression* Parser::ParseSimpleExpression(bool lhs) } break; case TK_OPEN_BRACKET: - exp = ParseLambdaExpression(); + if (mCompilerOptions & COPT_CPLUSPLUS) + exp = ParseLambdaExpression(); + else + { + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Term starts with invalid token", TokenNames[mScanner->mToken]); + mScanner->NextToken(); + } break; case TK_ASM: mScanner->NextToken(); @@ -7646,32 +7666,216 @@ Expression* Parser::ParseStatement(void) Expression* initExp = nullptr, * iterateExp = nullptr, * conditionExp = nullptr, * bodyExp = nullptr, * finalExp = nullptr; - // Assignment if (mScanner->mToken != TK_SEMICOLON) initExp = CleanupExpression(ParseExpression(true)); - if (mScanner->mToken == TK_SEMICOLON) - mScanner->NextToken(); - else - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); - // Condition - if (mScanner->mToken != TK_SEMICOLON) - conditionExp = CoerceExpression(CleanupExpression(ParseExpression(false)), TheBoolTypeDeclaration); + if ((mCompilerOptions & COPT_CPLUSPLUS) && ConsumeTokenIf(TK_COLON)) + { + Expression* containerExp = ParseExpression(false); + if (initExp->mType == EX_VARIABLE) + { + if (containerExp->mDecType->mType == DT_TYPE_ARRAY) + { + Declaration* iterVarDec = new Declaration(mScanner->mLocation, DT_VARIABLE); + iterVarDec->mBase = containerExp->mDecType->mBase->BuildPointer(mScanner->mLocation); + iterVarDec->mVarIndex = mLocalIndex++; + iterVarDec->mSize = iterVarDec->mBase->mSize; + iterVarDec->mFlags |= DTF_DEFINED; - if (mScanner->mToken == TK_SEMICOLON) - mScanner->NextToken(); - else - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); + Declaration* endVarDec = new Declaration(mScanner->mLocation, DT_VARIABLE); + endVarDec->mBase = iterVarDec->mBase; + endVarDec->mVarIndex = mLocalIndex++; + endVarDec->mSize = endVarDec->mBase->mSize; + endVarDec->mFlags |= DTF_DEFINED; - // Iteration - if (mScanner->mToken != TK_CLOSE_PARENTHESIS) - iterateExp = CleanupExpression(ParseExpression(false)); - if (mScanner->mToken == TK_CLOSE_PARENTHESIS) - mScanner->NextToken(); + Declaration* valueVarDec = initExp->mDecValue; + if (valueVarDec->mBase->mType == DT_TYPE_AUTO) + valueVarDec->mBase = containerExp->mDecType->mBase; + + initExp = new Expression(mScanner->mLocation, EX_LIST); + initExp->mLeft = new Expression(mScanner->mLocation, EX_INITIALIZATION); + initExp->mLeft->mToken = TK_ASSIGN; + initExp->mLeft->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + initExp->mLeft->mLeft->mDecType = iterVarDec->mBase; + initExp->mLeft->mLeft->mDecValue = iterVarDec; + initExp->mLeft->mRight = containerExp; + + initExp->mRight = new Expression(mScanner->mLocation, EX_INITIALIZATION); + initExp->mRight->mToken = TK_ASSIGN; + initExp->mRight->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + initExp->mRight->mLeft->mDecType = endVarDec->mBase; + initExp->mRight->mLeft->mDecValue = endVarDec; + initExp->mRight->mRight = new Expression(mScanner->mLocation, EX_BINARY); + initExp->mRight->mRight->mToken = TK_ADD; + initExp->mRight->mRight->mDecType = iterVarDec->mBase; + initExp->mRight->mRight->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + initExp->mRight->mRight->mLeft->mDecType = iterVarDec->mBase; + initExp->mRight->mRight->mLeft->mDecValue = iterVarDec; + initExp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); + initExp->mRight->mRight->mRight->mDecType = TheSignedIntTypeDeclaration; + initExp->mRight->mRight->mRight->mDecValue = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); + initExp->mRight->mRight->mRight->mDecValue->mBase = TheSignedIntTypeDeclaration; + initExp->mRight->mRight->mRight->mDecValue->mSize = 2; + initExp->mRight->mRight->mRight->mDecValue->mInteger = containerExp->mDecType->mSize; + + iterateExp = new Expression(mScanner->mLocation, EX_PREINCDEC); + iterateExp->mToken = TK_INC; + iterateExp->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + iterateExp->mLeft->mDecType = iterVarDec->mBase; + iterateExp->mLeft->mDecValue = iterVarDec; + + conditionExp = new Expression(mScanner->mLocation, EX_RELATIONAL); + conditionExp->mToken = TK_NOT_EQUAL; + conditionExp->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + conditionExp->mLeft->mDecType = iterVarDec->mBase; + conditionExp->mLeft->mDecValue = iterVarDec; + conditionExp->mRight = new Expression(mScanner->mLocation, EX_VARIABLE); + conditionExp->mRight->mDecType = endVarDec->mBase; + conditionExp->mRight->mDecValue = endVarDec; + + bodyExp = new Expression(mScanner->mLocation, EX_ASSIGNMENT); + bodyExp->mToken = TK_ASSIGN; + bodyExp->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + bodyExp->mLeft->mDecType = valueVarDec->mBase; + bodyExp->mLeft->mDecValue = valueVarDec; + bodyExp->mRight = new Expression(mScanner->mLocation, EX_PREFIX); + bodyExp->mRight->mToken = TK_MUL; + bodyExp->mRight->mDecType = containerExp->mDecType->mBase; + bodyExp->mRight->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + bodyExp->mRight->mLeft->mDecType = iterVarDec->mBase; + bodyExp->mRight->mLeft->mDecValue = iterVarDec; + } + else if (containerExp->mDecType->mType == DT_TYPE_STRUCT) + { + Declaration* fbegin = containerExp->mDecType->mScope->Lookup(Ident::Unique("begin")); + Declaration* fend = containerExp->mDecType->mScope->Lookup(Ident::Unique("end")); + + if (fbegin && fend) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_PREFIX); + cexp->mToken = TK_BINARY_AND; + cexp->mDecType = containerExp->mDecType->BuildPointer(mScanner->mLocation); + cexp->mLeft = containerExp; + + Declaration* iterVarDec = new Declaration(mScanner->mLocation, DT_VARIABLE); + iterVarDec->mBase = fbegin->mBase->mBase->NonRefBase(); + iterVarDec->mVarIndex = mLocalIndex++; + iterVarDec->mSize = iterVarDec->mBase->mSize; + iterVarDec->mFlags |= DTF_DEFINED; + + Declaration* endVarDec = new Declaration(mScanner->mLocation, DT_VARIABLE); + endVarDec->mBase = fend->mBase->mBase->NonRefBase(); + endVarDec->mVarIndex = mLocalIndex++; + endVarDec->mSize = endVarDec->mBase->mSize; + endVarDec->mFlags |= DTF_DEFINED; + + Declaration* valueVarDec = initExp->mDecValue; + + initExp = new Expression(mScanner->mLocation, EX_LIST); + initExp->mLeft = new Expression(mScanner->mLocation, EX_INITIALIZATION); + initExp->mLeft->mToken = TK_ASSIGN; + initExp->mLeft->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + initExp->mLeft->mLeft->mDecType = iterVarDec->mBase; + initExp->mLeft->mLeft->mDecValue = iterVarDec; + initExp->mLeft->mRight = new Expression(mScanner->mLocation, EX_CALL); + initExp->mLeft->mRight->mDecType = fbegin->mBase->mBase; + initExp->mLeft->mRight->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + initExp->mLeft->mRight->mLeft->mDecType = fbegin->mBase; + initExp->mLeft->mRight->mLeft->mDecValue = fbegin; + initExp->mLeft->mRight->mRight = cexp; + + initExp->mRight = new Expression(mScanner->mLocation, EX_INITIALIZATION); + initExp->mRight->mToken = TK_ASSIGN; + initExp->mRight->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + initExp->mRight->mLeft->mDecType = endVarDec->mBase; + initExp->mRight->mLeft->mDecValue = endVarDec; + initExp->mRight->mRight = new Expression(mScanner->mLocation, EX_CALL); + initExp->mRight->mRight->mDecType = fend->mBase->mBase; + initExp->mRight->mRight->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + initExp->mRight->mRight->mLeft->mDecType = fend->mBase; + initExp->mRight->mRight->mLeft->mDecValue = fend; + initExp->mRight->mRight->mRight = cexp; + + iterateExp = new Expression(mScanner->mLocation, EX_PREINCDEC); + iterateExp->mToken = TK_INC; + iterateExp->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + iterateExp->mLeft->mDecType = iterVarDec->mBase; + iterateExp->mLeft->mDecValue = iterVarDec; + iterateExp = CheckOperatorOverload(iterateExp); + + conditionExp = new Expression(mScanner->mLocation, EX_RELATIONAL); + conditionExp->mToken = TK_NOT_EQUAL; + conditionExp->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + conditionExp->mLeft->mDecType = iterVarDec->mBase; + conditionExp->mLeft->mDecValue = iterVarDec; + conditionExp->mRight = new Expression(mScanner->mLocation, EX_VARIABLE); + conditionExp->mRight->mDecType = endVarDec->mBase; + conditionExp->mRight->mDecValue = endVarDec; + conditionExp = CheckOperatorOverload(conditionExp); + + bodyExp = new Expression(mScanner->mLocation, EX_ASSIGNMENT); + bodyExp->mToken = TK_ASSIGN; + bodyExp->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + + bodyExp->mRight = new Expression(mScanner->mLocation, EX_PREFIX); + bodyExp->mRight->mToken = TK_MUL; + bodyExp->mRight->mDecType = valueVarDec->mBase; + bodyExp->mRight->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); + bodyExp->mRight->mLeft->mDecType = iterVarDec->mBase; + bodyExp->mRight->mLeft->mDecValue = iterVarDec; + bodyExp->mRight = CheckOperatorOverload(bodyExp->mRight); + + if (valueVarDec->mBase->mType == DT_TYPE_AUTO) + valueVarDec->mBase = bodyExp->mRight->mDecType->NonRefBase(); + + bodyExp->mLeft->mDecType = valueVarDec->mBase; + bodyExp->mLeft->mDecValue = valueVarDec; + bodyExp = CheckOperatorOverload(bodyExp); + } + else + mErrors->Error(containerExp->mLocation, EERR_INCOMPATIBLE_TYPES, "Array or container expected"); + } + else + mErrors->Error(containerExp->mLocation, EERR_INCOMPATIBLE_TYPES, "Array or container expected"); + } + else + mErrors->Error(initExp->mLocation, EERR_INCOMPATIBLE_TYPES, "Variable expected"); + } else - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "')' expected"); - bodyExp = ParseStatement(); + { + if (mScanner->mToken == TK_SEMICOLON) + mScanner->NextToken(); + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); + + // Condition + if (mScanner->mToken != TK_SEMICOLON) + conditionExp = CoerceExpression(CleanupExpression(ParseExpression(false)), TheBoolTypeDeclaration); + + if (mScanner->mToken == TK_SEMICOLON) + mScanner->NextToken(); + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); + + // Iteration + if (mScanner->mToken != TK_CLOSE_PARENTHESIS) + iterateExp = CleanupExpression(ParseExpression(false)); + } + + ConsumeToken(TK_CLOSE_PARENTHESIS); + + Expression * innerExp = ParseStatement(); + if (bodyExp) + { + Expression* exp = new Expression(bodyExp->mLocation, EX_SEQUENCE); + exp->mLeft = bodyExp; + exp->mRight = innerExp; + bodyExp = exp; + } + else + bodyExp = innerExp; + mScope->End(mScanner->mLocation); exp->mLeft = new Expression(mScanner->mLocation, EX_SEQUENCE); From 532bf517184f987abaeb57c637904d88b4206f94 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 13 Sep 2023 17:24:38 +0200 Subject: [PATCH 114/169] Range for loop with reference iteration --- oscar64/Declaration.cpp | 24 +++++++++ oscar64/Declaration.h | 1 + oscar64/InterCode.cpp | 2 +- oscar64/InterCodeGenerator.cpp | 12 +++-- oscar64/Parser.cpp | 90 +++++++++++++++++++++++++++------- 5 files changed, 106 insertions(+), 23 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 8fb23a2..1597fc8 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -964,6 +964,30 @@ Declaration* Declaration::NonRefBase(void) return this; } +Declaration* Declaration::DeduceAuto(Declaration * dec) +{ + if (mType == DT_TYPE_AUTO || IsReference() && mBase->mType == DT_TYPE_AUTO) + { + dec = dec->NonRefBase(); + + if (dec->mType == DT_TYPE_ARRAY) + dec = dec->mBase->BuildPointer(mLocation); + + if (mFlags & DTF_CONST) + dec = dec->ToConstType(); + else + dec = dec->ToMutableType(); + + if (IsReference()) + dec = dec->BuildReference(mLocation); + + return dec; + } + else + return this; +} + + Declaration* Declaration::BuildConstRValueRef(const Location& loc) { Declaration* pdec = new Declaration(loc, DT_TYPE_RVALUEREF); diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index a4d1b70..d4cd6a2 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -310,6 +310,7 @@ public: Declaration* BuildRValueRef(const Location& loc); Declaration* BuildConstRValueRef(const Location& loc); Declaration* NonRefBase(void); + Declaration* DeduceAuto(Declaration* dec); DecType ValueType(void) const; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 28be3a2..0cfc4e0 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -17102,7 +17102,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "test"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 256d784..f1e7198 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -2034,13 +2034,19 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mType->IsReference()) { - vr = Dereference(proc, exp, block, vr, 1); + if (vr.mType->IsReference()) + vr = Dereference(proc, exp, block, vr, 0); + else + { + vr = Dereference(proc, exp, block, vr, 1); + if (vr.mReference != 1) + mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); + } + vl = Dereference(proc, exp, block, vl, 2); if (vl.mReference != 2) mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not a left hand reference expression"); - if (vr.mReference != 1) - mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); if (vr.mTemp != vl.mTemp) { diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 5629a23..94acaa0 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -4168,20 +4168,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ConsumeTokenIf(TK_ASSIGN)) { ndec->mValue = ParseInitExpression(ndec->mBase); - if (ndec->mBase->mType == DT_TYPE_AUTO) - { - 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(); - ndec->mBase->mType = DT_TYPE_POINTER; - ndec->mBase->mSize = 2; - } - } + ndec->mBase = ndec->mBase->DeduceAuto(ndec->mValue->mDecType); if (ndec->mFlags & DTF_GLOBAL) { @@ -7055,6 +7042,71 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) } } } + else if (exp->mType == EX_INITIALIZATION) + { + Declaration* tdec = exp->mLeft->mDecType; + if (tdec->mType == DT_TYPE_STRUCT && exp->mToken == TK_ASSIGN) + { + Declaration* fcons = tdec->mScope ? tdec->mScope->Lookup(tdec->mIdent->PreMangle("+"), SLEVEL_CLASS) : nullptr; + if (fcons) + { + Declaration* mtype = tdec->ToMutableType(); + + Expression* vexp = exp->mLeft; + + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = fcons; + cexp->mDecType = cexp->mDecValue->mBase; + + Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); + fexp->mLeft = cexp; + fexp->mRight = exp->mRight; + + Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = vexp; + texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = mtype; + texp->mDecType->mSize = 2; + + if (fexp->mRight) + { + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = fexp->mRight; + fexp->mRight = lexp; + } + else + fexp->mRight = texp; + + fexp = ResolveOverloadCall(fexp); + + Expression* dexp = nullptr; + if (tdec->mDestructor) + { + Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); + cexp->mDecValue = tdec->mDestructor; + cexp->mDecType = cexp->mDecValue->mBase; + + dexp = new Expression(mScanner->mLocation, EX_CALL); + dexp->mLeft = cexp; + dexp->mRight = texp; + } + + Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST); + nexp->mLeft->mLeft = fexp; + nexp->mLeft->mRight = dexp; + + nexp->mRight = vexp; + nexp->mDecType = vexp->mDecType; + + exp = nexp; + } + } + } else if (exp->mType == EX_INDEX) { Declaration* tdec = exp->mLeft->mDecType; @@ -7690,8 +7742,8 @@ Expression* Parser::ParseStatement(void) endVarDec->mFlags |= DTF_DEFINED; Declaration* valueVarDec = initExp->mDecValue; - if (valueVarDec->mBase->mType == DT_TYPE_AUTO) - valueVarDec->mBase = containerExp->mDecType->mBase; + valueVarDec->mBase = valueVarDec->mBase->DeduceAuto(containerExp->mDecType->mBase); + valueVarDec->mSize = valueVarDec->mBase->mSize; initExp = new Expression(mScanner->mLocation, EX_LIST); initExp->mLeft = new Expression(mScanner->mLocation, EX_INITIALIZATION); @@ -7814,7 +7866,7 @@ Expression* Parser::ParseStatement(void) conditionExp->mRight->mDecValue = endVarDec; conditionExp = CheckOperatorOverload(conditionExp); - bodyExp = new Expression(mScanner->mLocation, EX_ASSIGNMENT); + bodyExp = new Expression(mScanner->mLocation, EX_INITIALIZATION); bodyExp->mToken = TK_ASSIGN; bodyExp->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); @@ -7826,8 +7878,8 @@ Expression* Parser::ParseStatement(void) bodyExp->mRight->mLeft->mDecValue = iterVarDec; bodyExp->mRight = CheckOperatorOverload(bodyExp->mRight); - if (valueVarDec->mBase->mType == DT_TYPE_AUTO) - valueVarDec->mBase = bodyExp->mRight->mDecType->NonRefBase(); + valueVarDec->mBase = valueVarDec->mBase->DeduceAuto(bodyExp->mRight->mDecType); + valueVarDec->mSize = valueVarDec->mBase->mSize; bodyExp->mLeft->mDecType = valueVarDec->mBase; bodyExp->mLeft->mDecValue = valueVarDec; From 64b3bfa30f0304f5833d0a67da13b2ca9dbf9977 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 13 Sep 2023 19:05:33 +0200 Subject: [PATCH 115/169] Optimize temporary object livetime --- oscar64/Parser.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++- oscar64/Parser.h | 6 +++- 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 94acaa0..855e93b 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -23,6 +23,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn mFunctionType = nullptr; mLambda = nullptr; mCaptureScope = nullptr; + mTempVars = nullptr; for (int i = 0; i < 256; i++) mCharMap[i] = i; @@ -3068,6 +3069,57 @@ static Expression* ConcatExpression(Expression* e1, Expression* e2) return e2; } +Declaration* Parser::AllocTempVar(Declaration* type) +{ + Declaration* ptemp = nullptr, * vtemp = mTempVars; + while (vtemp && !vtemp->mBase->IsSame(type)) + { + ptemp = vtemp; + vtemp = vtemp->mNext; + } + + if (vtemp) + { + if (ptemp) + ptemp->mNext = vtemp->mNext; + else + mTempVars = vtemp->mNext; + vtemp->mNext = nullptr; + vtemp->mValue = nullptr; + } + else + { + vtemp = new Declaration(mScanner->mLocation, DT_VARIABLE); + vtemp->mBase = type; + vtemp->mSize = type->mSize; + vtemp->mVarIndex = mLocalIndex++; + vtemp->mFlags |= DTF_DEFINED; + } + + return vtemp; +} + +void Parser::FreeTempVar(Declaration* var) +{ + var->mNext = mTempVars; + mTempVars = var; +} + +void Parser::FreeTempVarExp(Expression* exp) +{ + if (exp->mType == EX_SEQUENCE) + { + FreeTempVarExp(exp->mLeft); + FreeTempVarExp(exp->mRight); + } + else if (exp->mType == EX_CALL && exp->mLeft->mType == EX_CONSTANT && + exp->mRight->mType == EX_PREFIX && exp->mRight->mToken == TK_BINARY_AND && exp->mRight->mLeft->mType == EX_VARIABLE) + { + if (exp->mLeft->mDecValue->mIdent->mString[0] == '~' && exp->mRight->mLeft->mDecValue->mIdent == nullptr) + FreeTempVar(exp->mRight->mLeft->mDecValue); + } +} + Expression* Parser::CleanupExpression(Expression* exp) { if (exp) @@ -3078,6 +3130,8 @@ Expression* Parser::CleanupExpression(Expression* exp) Expression* cexp = new Expression(exp->mLocation, EX_CLEANUP); cexp->mLeft = exp; cexp->mRight = xexp; + + FreeTempVarExp(xexp); return cexp; } } @@ -3261,6 +3315,16 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) rexp = ConcatExpression(rexp, dexp); } } + else if ((pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) && pex->mType == EX_CONSTRUCT && pex->mRight->mType == EX_VARIABLE) + { + // A constructed object is passed by reference + + if (pex->mLeft->mRight) + { + rexp = ConcatExpression(rexp, pex->mLeft->mRight); + pex->mLeft->mRight = nullptr; + } + } else if ((pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) && pex->mType == EX_CONSTANT) { // A simple constant is passed by const ref @@ -5740,12 +5804,15 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) if (fcons) { + Declaration* vdec = AllocTempVar(type->ToMutableType()); +#if 0 Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); vdec->mBase = type->ToMutableType(); vdec->mVarIndex = mLocalIndex++; vdec->mSize = type->mSize; vdec->mFlags |= DTF_DEFINED; +#endif Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); vexp->mDecType = vdec->mBase; @@ -7534,6 +7601,7 @@ Expression* Parser::ParseFunction(Declaration * dec) pdec = pdec->mNext; } mLocalIndex = 0; + mTempVars = nullptr; Expression * exp = ParseStatement(); @@ -7876,7 +7944,10 @@ Expression* Parser::ParseStatement(void) bodyExp->mRight->mLeft = new Expression(mScanner->mLocation, EX_VARIABLE); bodyExp->mRight->mLeft->mDecType = iterVarDec->mBase; bodyExp->mRight->mLeft->mDecValue = iterVarDec; - bodyExp->mRight = CheckOperatorOverload(bodyExp->mRight); + if (iterVarDec->mBase->mType == DT_TYPE_POINTER) + bodyExp->mRight->mDecType = iterVarDec->mBase->mBase; + else + bodyExp->mRight = CheckOperatorOverload(bodyExp->mRight); valueVarDec->mBase = valueVarDec->mBase->DeduceAuto(bodyExp->mRight->mDecType); valueVarDec->mSize = valueVarDec->mBase->mSize; diff --git a/oscar64/Parser.h b/oscar64/Parser.h index e60ddbd..ba1e2b0 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -15,7 +15,7 @@ public: DeclarationScope * mGlobals, * mScope, * mTemplateScope, * mCaptureScope; int mLocalIndex; CompilationUnits * mCompilationUnits; - Declaration * mThisPointer, * mFunctionType, * mFunction, * mLambda; + Declaration * mThisPointer, * mFunctionType, * mFunction, * mLambda, * mTempVars; Token mCaptureToken; LinkerSection * mCodeSection, * mDataSection, * mBSSection; @@ -36,6 +36,10 @@ protected: bool mUnrollLoopPage; bool mInlineCall; + Declaration* AllocTempVar(Declaration* type); + void FreeTempVar(Declaration* var); + void FreeTempVarExp(Expression* exp); + uint8* ParseStringLiteral(int msize); void ParseNamespace(void); From 0e6cb5557aae24bd033d732ee220fca1e521dae4 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 14 Sep 2023 10:30:52 +0200 Subject: [PATCH 116/169] Auto parameters in lambdas --- oscar64/Declaration.cpp | 62 ++++++++++- oscar64/Declaration.h | 30 ++--- oscar64/GlobalAnalyzer.cpp | 2 +- oscar64/Parser.cpp | 219 ++++++++++++++++++++++++++++++------- oscar64/Parser.h | 2 + 5 files changed, 258 insertions(+), 57 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 1597fc8..2b56ef5 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -883,7 +883,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mMangleIdent(nullptr), - mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), + mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mNumVars(0), mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), mMutable(nullptr), mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr), @@ -964,6 +964,11 @@ Declaration* Declaration::NonRefBase(void) return this; } +bool Declaration::IsAuto(void) const +{ + return (mType == DT_TYPE_AUTO || IsReference() && mBase->mType == DT_TYPE_AUTO); +} + Declaration* Declaration::DeduceAuto(Declaration * dec) { if (mType == DT_TYPE_AUTO || IsReference() && mBase->mType == DT_TYPE_AUTO) @@ -1114,6 +1119,61 @@ const Ident* Declaration::MangleIdent(void) return mMangleIdent; } +Declaration* Declaration::ExpandTemplate(DeclarationScope* scope) +{ + if (mType == DT_CONST_FUNCTION) + { + Declaration* dec = this->Clone(); + dec->mBase = dec->mBase->ExpandTemplate(scope); + return dec; + } + else if (mType == DT_TYPE_FUNCTION) + { + Declaration* dec = this->Clone(); + dec->mParams = mParams ? mParams->ExpandTemplate(scope) : nullptr; + dec->mBase = mBase->ExpandTemplate(scope); + Declaration* pdec = dec->mParams; + if (pdec) + { + int vi = pdec->mVarIndex; + while (pdec) + { + pdec->mVarIndex = vi; + vi += pdec->mSize; + pdec = pdec->mNext; + } + } + return dec; + } + else if (mType == DT_ARGUMENT) + { + Declaration* ndec = mNext ? mNext->ExpandTemplate(scope) : nullptr; + Declaration* bdec = mBase->ExpandTemplate(scope); + if (ndec != mNext || bdec != mBase) + { + Declaration* dec = this->Clone(); + dec->mBase = bdec; + dec->mSize = bdec->mSize; + dec->mNext = ndec; + return dec; + } + } + else if (mType == DT_TYPE_REFERENCE || mType == DT_TYPE_POINTER || mType == DT_TYPE_RVALUEREF) + { + Declaration* bdec = mBase->ExpandTemplate(scope); + if (bdec != mBase) + { + Declaration* dec = this->Clone(); + dec->mBase = bdec; + return dec; + } + } + else if (mType == DT_TYPE_TEMPLATE) + return scope->Lookup(mIdent); + + return this; +} + bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) { Declaration* pdec = tdec->mBase->mParams; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index d4cd6a2..e22d2ce 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -92,26 +92,27 @@ 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); -static const uint64 DTF_FUNC_RECURSIVE = (1ULL << 34); -static const uint64 DTF_FUNC_ANALYZING = (1ULL << 35); +static const uint64 DTF_AUTO_TEMPLATE = (1ULL << 32); -static const uint64 DTF_FUNC_CONSTEXPR = (1ULL << 36); -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_FUNC_VARIABLE = (1ULL << 36); +static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 37); +static const uint64 DTF_FUNC_RECURSIVE = (1ULL << 38); +static const uint64 DTF_FUNC_ANALYZING = (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_FUNC_CONSTEXPR = (1ULL << 40); +static const uint64 DTF_FUNC_INTRSAVE = (1ULL << 41); +static const uint64 DTF_FUNC_INTRCALLED = (1ULL << 42); +static const uint64 DTF_FUNC_PURE = (1ULL << 43); -static const uint64 DTF_FUNC_THIS = (1ULL << 43); +static const uint64 DTF_FPARAM_CONST = (1ULL << 44); +static const uint64 DTF_FPARAM_NOCONST = (1ULL << 45); +static const uint64 DTF_VAR_ADDRESS = (1ULL << 46); + +static const uint64 DTF_FUNC_THIS = (1ULL << 47); static const uint64 DTF_VAR_ALIASING = (1ULL << 48); - class Declaration; enum ScopeLevel @@ -311,6 +312,7 @@ public: Declaration* BuildConstRValueRef(const Location& loc); Declaration* NonRefBase(void); Declaration* DeduceAuto(Declaration* dec); + bool IsAuto(void) const; DecType ValueType(void) const; @@ -318,6 +320,8 @@ public: bool ResolveTemplate(Declaration* fdec, Declaration * tdec); bool ResolveTemplate(Expression* pexp, Declaration* tdec); + Declaration* ExpandTemplate(DeclarationScope* scope); + const Ident* MangleIdent(void); int Stride(void) const; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 609826b..ab171d0 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -159,7 +159,7 @@ void GlobalAnalyzer::AutoInline(void) dec = dec->mNext; } - int cost = (f->mComplexity - 20 * nparams); + int cost = (f->mComplexity - 20 * nparams - 20); // printf("CHEK INLINING %s %d * (%d - 1)\n", f->mIdent->mString, cost, f->mCallers.Size()); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 855e93b..ddd5401 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2142,7 +2142,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mVarIndex = -1; cdec->mFlags |= DTF_DEFINED; - cdec->mNumVars = mLocalIndex; cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); } @@ -2186,7 +2185,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mVarIndex = -1; cdec->mFlags |= DTF_DEFINED; - cdec->mNumVars = mLocalIndex; cdec->mValue = new Expression(mScanner->mLocation, EX_VOID); } @@ -2355,7 +2353,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) } cdec->mFlags |= DTF_DEFINED; - cdec->mNumVars = mLocalIndex; } } @@ -2528,8 +2525,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) } cdec->mFlags |= DTF_DEFINED; - cdec->mNumVars = mLocalIndex; - } } @@ -2576,7 +2571,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mVarIndex = -1; cdec->mFlags |= DTF_DEFINED; - cdec->mNumVars = mLocalIndex; Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); pexp->mDecType = vthis; @@ -2653,7 +2647,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mVarIndex = -1; cdec->mFlags |= DTF_DEFINED; - cdec->mNumVars = mLocalIndex; Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); pexp->mDecType = vthis; @@ -2739,7 +2732,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mVarIndex = -1; cdec->mFlags |= DTF_DEFINED; - cdec->mNumVars = mLocalIndex; Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); pexp->mDecType = vthis; @@ -2843,7 +2835,6 @@ void Parser::AddDefaultConstructors(Declaration* pthis) cdec->mVarIndex = -1; cdec->mFlags |= DTF_DEFINED; - cdec->mNumVars = mLocalIndex; Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE); pexp->mDecType = vthis; @@ -3451,8 +3442,10 @@ void Parser::ParseVariableInit(Declaration* ndec) { ndec->mValue = pexp; } - else + else if (pexp) mErrors->Error(pexp->mLocation, EERR_INCOMPATIBLE_TYPES, "Can not initialize variable with expression", ndec->mIdent); + else + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_TYPES, "Can not initialize variable with expression", ndec->mIdent); } Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis, Declaration* ptempl) @@ -4028,6 +4021,10 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (mCompilerOptions & COPT_NATIVE) ndec->mFlags |= DTF_NATIVE; + + Declaration* ntdec = FunctionAutoParamsToTemplate(ndec); + if (ntdec) + return ntdec; } if (ndec->mIdent) @@ -4603,6 +4600,7 @@ Expression* Parser::ParseLambdaExpression(void) Declaration* fdec = new Declaration(mScanner->mLocation, DT_CONST_FUNCTION); fdec->mIdent = Ident::Unique("operator()"); fdec->mQualIdent = cdec->mScope->Mangle(fdec->mIdent); + fdec->mCompilerOptions = mCompilerOptions; cdec->mScope->Insert(fdec->mIdent, fdec); Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); @@ -4727,6 +4725,7 @@ Expression* Parser::ParseLambdaExpression(void) fdec->mVarIndex = -1; + int li = mLocalIndex; DeclarationScope * oscope = mCaptureScope; @@ -4735,7 +4734,13 @@ Expression* Parser::ParseLambdaExpression(void) while (mScope->mLevel >= SLEVEL_NAMESPACE) mScope = mScope->mParent; - fdec->mValue = ParseFunction(fdec->mBase); + Declaration* tfdec = FunctionAutoParamsToTemplate(fdec); + if (tfdec) + { + fdec = tfdec; + } + else + fdec->mValue = ParseFunction(fdec->mBase); mScope = mCaptureScope; mLambda = olambda; @@ -5548,9 +5553,7 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) { Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); - if (tdec->CanResolveTemplate(pexp, fdec)) - return 16; - else + if (!tdec->CanResolveTemplate(pexp, fdec)) return NOOVERLOAD; } @@ -5576,27 +5579,31 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) if (etype->mType == DT_TYPE_REFERENCE) etype = etype->mBase; - if (ptype->mType == DT_TYPE_INTEGER && etype->mType == DT_TYPE_INTEGER) + if (ptype->mType == DT_TYPE_TEMPLATE) + { + dist += 1; + } + else if (ptype->mType == DT_TYPE_INTEGER && etype->mType == DT_TYPE_INTEGER) { if (ptype->mSize == etype->mSize) { if ((ptype->mFlags & DTF_SIGNED) == (etype->mFlags & DTF_SIGNED)) dist += 0; else - dist += 4; + dist += 8; } else if (ptype->mSize > etype->mSize) { if (ptype->mFlags & DTF_SIGNED) { - dist += 1; + dist += 2; } else if (etype->mFlags & DTF_SIGNED) { - dist += 4; + dist += 8; } else - dist += 1; + dist += 2; } else if (ex->mType == EX_CONSTANT && ex->mDecValue->mType == DT_CONST_INTEGER) { @@ -5605,53 +5612,53 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) if (ptype->mFlags & DTF_SIGNED) { if (v >= -128 && v <= 127) - dist += 1; + dist += 2; else if (ptype->mSize >= 2 && v >= -32768 && v <= 32767) - dist += 1; + dist += 2; else if (ptype->mSize == 4) - dist += 1; + dist += 2; else - dist += 16; + dist += 32; } else if (v >= 0) { if (v <= 255) - dist += 1; + dist += 2; else if (ptype->mSize >= 2 && v <= 65535) - dist += 1; + dist += 2; else if (ptype->mSize == 4) - dist += 1; + dist += 2; else - dist += 16; + dist += 32; } else - dist += 16; + dist += 32; } else - dist += 16; + dist += 32; } else if (ptype->mType == DT_TYPE_FLOAT && etype->mType == DT_TYPE_FLOAT) dist += 0; else if (ptype->mType == DT_TYPE_INTEGER && etype->mType == DT_TYPE_FLOAT) - dist += 8; + dist += 16; else if (ptype->mType == DT_TYPE_FLOAT && etype->mType == DT_TYPE_INTEGER) - dist += 4; + dist += 8; else if (ptype->IsSame(ex->mDecType)) ; else if (CanCoerceExpression(ex, ptype)) { dist += 512; if (ptype->mType == DT_TYPE_REFERENCE) - dist += 4; + dist += 8; else if (ptype->mType == DT_TYPE_RVALUEREF) - dist += 2; + dist += 4; } else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_TYPE_STRUCT && etype->mType == DT_TYPE_STRUCT) { if (ex->IsLValue()) - dist += 2; - else if (ptype->mBase->mFlags & DTF_CONST) dist += 4; + else if (ptype->mBase->mFlags & DTF_CONST) + dist += 8; else return NOOVERLOAD; @@ -5668,13 +5675,13 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) if ((etype->mFlags & DTF_CONST) && !(ptype->mBase->mFlags & DTF_CONST)) return NOOVERLOAD; - dist += 16 * ncast; + dist += 32 * ncast; } else return NOOVERLOAD; } else if (ptype->mType == DT_TYPE_POINTER && (etype->mType == DT_TYPE_ARRAY || etype->mType == DT_TYPE_POINTER) && ptype->mBase->IsSameMutable(etype->mBase)) - dist += 1; + dist += 2; else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_FUNCTION && ptype->mBase->IsSame(etype)) dist += 0; else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_POINTER && etype->mBase->mType == DT_TYPE_VOID) @@ -5683,14 +5690,14 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) dist += 256; else if (ptype->mType == DT_TYPE_RVALUEREF && ptype->mBase->IsSameMutable(etype) && ex->IsRValue()) { - dist += 1; + dist += 2; } else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->IsSameMutable(etype)) { if (ex->IsLValue()) - dist += 2; - else if (ptype->mBase->mFlags & DTF_CONST) dist += 4; + else if (ptype->mBase->mFlags & DTF_CONST) + dist += 8; else return NOOVERLOAD; } @@ -8337,7 +8344,6 @@ Expression* Parser::ParseSwitchStatement(void) Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* expd) { - Declaration * tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); @@ -8436,7 +8442,35 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp tmpld->mNext = tdec; p->mTemplateScope = tdec->mScope; - tdec->mBase = p->ParseDeclaration(nullptr, true, false, nullptr, tdec); + if (tmpld->mFlags & DTF_AUTO_TEMPLATE) + { + Declaration * ndec = tmpld->mBase->ExpandTemplate(tdec->mScope); + + Declaration* pdec = tmpld->mBase; + + if (pdec) + { + Declaration* pcdec = nullptr; + + while (pdec && !ndec->mBase->IsSameParams(pdec->mBase)) + { + pcdec = pdec; + pdec = pdec->mNext; + } + + if (!pdec) + pcdec->mNext = ndec; + } + + tdec->mBase = ndec; + ndec->mValue = p->ParseFunction(ndec->mBase); + ndec->mFlags |= DTF_DEFINED; + + ndec->mIdent = ndec->mIdent->Mangle(tdec->mScope->mName->mString); + ndec->mQualIdent = ndec->mQualIdent->Mangle(tdec->mScope->mName->mString); + } + else + tdec->mBase = p->ParseDeclaration(nullptr, true, false, nullptr, tdec); p->mTemplateScope = nullptr; if (tdec->mBase->mType == DT_ANON) @@ -8503,6 +8537,107 @@ void Parser::CompleteTemplateExpansion(Declaration* tmpld) } +Declaration* Parser::FunctionAutoParamsToTemplate(Declaration* fdec) +{ + Declaration* pdec = fdec->mBase->mParams; + while (pdec && !pdec->mBase->IsAuto()) + pdec = pdec->mNext; + + if (pdec) + { + Declaration* tdec = new Declaration(fdec->mLocation, DT_TEMPLATE); + tdec->mParser = this->Clone(); + tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + Declaration* ppdec = nullptr; + + int ntp = 0; + pdec = fdec->mBase->mParams; + while (pdec) + { + Declaration* ptdec = nullptr; + + if (pdec->mBase->mType == DT_TYPE_AUTO) + { + ptdec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); + pdec->mBase = ptdec; + } + else if (pdec->mBase->IsReference() && pdec->mBase->mBase->mType == DT_TYPE_AUTO) + { + ptdec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); + pdec->mBase->mBase = ptdec; + } + + if (ptdec) + { + ptdec->mIdent = Ident::Unique("T" + ntp++); + tdec->mScope->Insert(ptdec->mIdent, ptdec); + ptdec->mFlags |= DTF_DEFINED; + + if (ppdec) + ppdec->mNext = ptdec; + else + tdec->mParams = ptdec; + ppdec = ptdec; + } + + pdec = pdec->mNext; + } + + fdec->mCompilerOptions = mCompilerOptions; + fdec->mBase->mCompilerOptions = mCompilerOptions; + + tdec->mBase = fdec; + fdec->mTemplate = tdec; + + mScanner->BeginRecord(); + + if (ConsumeTokenIf(TK_OPEN_BRACE)) + { + int qdepth = 1; + while (qdepth) + { + if (ConsumeTokenIf(TK_OPEN_BRACE)) + qdepth++; + else if (ConsumeTokenIf(TK_CLOSE_BRACE)) + qdepth--; + else + mScanner->NextToken(); + } + } + + tdec->mTokens = mScanner->CompleteRecord(); + + tdec->mIdent = tdec->mBase->mIdent; + tdec->mQualIdent = tdec->mBase->mQualIdent; + tdec->mScope->mName = tdec->mQualIdent; + tdec->mFlags |= DTF_AUTO_TEMPLATE; + + if (tdec->mQualIdent == mScope->Mangle(tdec->mIdent)) + mScope->Insert(tdec->mIdent, tdec->mBase); + + Declaration* pdec = mCompilationUnits->mScope->Insert(tdec->mQualIdent, tdec->mBase); + if (pdec) + { + Declaration* ppdec = pdec; + while (pdec && !pdec->IsSameTemplate(tdec->mBase)) + { + ppdec = pdec; + pdec = pdec->mNext; + } + + if (!pdec) + { + ppdec->mNext = tdec->mBase; + tdec->mBase->mNext = nullptr; + } + } + + return fdec; + } + else + return nullptr; +} + void Parser::ParseTemplateDeclaration(void) { ConsumeToken(TK_LESS_THAN); diff --git a/oscar64/Parser.h b/oscar64/Parser.h index ba1e2b0..13feebf 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -106,6 +106,8 @@ protected: void ExpandFunctionCallTemplate(Expression* exp); void ParseTemplateDeclaration(void); + Declaration* FunctionAutoParamsToTemplate(Declaration* fdec); + Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); void CompleteTemplateExpansion(Declaration* tmpld); From d9106be820aa68c404df2e26a47d08516f4739d4 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 14 Sep 2023 12:03:28 +0200 Subject: [PATCH 117/169] Lambda in constexpr --- oscar64/Constexpr.cpp | 3 ++- oscar64/Declaration.cpp | 20 ++++++++++++++++-- oscar64/Parser.cpp | 45 ++++++++++++++++++++++++++++++++++------- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index 134e477..1a5b83d 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -570,7 +570,8 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp) 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); + if (pex->mDecValue->mSize > 0) + mParams[pos].PutConst(0, pex->mDecValue->mValue->mDecValue); } else return exp; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 2b56ef5..663ba6b 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1095,9 +1095,14 @@ const Ident* Declaration::MangleIdent(void) Declaration* dec = mParams; while (dec) { - const Ident* id = dec->mBase->MangleIdent(); + const Ident* id; + if (dec->mBase) + id = dec->mBase->MangleIdent(); + else + id = dec->MangleIdent(); if (id) mMangleIdent = mMangleIdent->Mangle(id->mString); + dec = dec->mNext; if (dec) mMangleIdent = mMangleIdent->Mangle(","); @@ -1178,6 +1183,15 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) { Declaration* pdec = tdec->mBase->mParams; + // Insert partially resolved templates + Declaration* ptdec = tdec->mTemplate->mParams; + while (ptdec) + { + if (ptdec->mBase) + mScope->Insert(ptdec->mIdent, ptdec->mBase); + ptdec = ptdec->mNext; + } + while (pexp) { Expression* ex = pexp; @@ -1201,7 +1215,7 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) } Declaration* ppdec = nullptr; - Declaration* ptdec = tdec->mTemplate->mParams; + ptdec = tdec->mTemplate->mParams; while (ptdec) { Declaration* pdec = mScope->Lookup(ptdec->mIdent); @@ -1785,6 +1799,8 @@ bool Declaration::IsSameParams(const Declaration* dec) const if (ld->mValue != rd->mValue) return false; } + else if (ld->mType == DT_TYPE_TEMPLATE || ld->mType == DT_CONST_TEMPLATE) + return false; else if (!ld->mBase->IsSame(rd->mBase)) return false; ld = ld->mNext; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index ddd5401..f68964f 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -4836,7 +4836,7 @@ Expression* Parser::ParseLambdaExpression(void) vdec->mBase = cdec; vdec->mVarIndex = mLocalIndex++; vdec->mSize = cdec->mSize; - vdec->mFlags |= DTF_DEFINED; + vdec->mFlags |= DTF_DEFINED | DTF_CONST; vdec->mIdent = cdec->mIdent; Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE); @@ -8365,6 +8365,25 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp Declaration* ppdec = nullptr; Declaration* pdec = tmpld->mParams; + + // Carry over already specialized parameters + while (pdec && (pdec->mType != DT_TYPE_TEMPLATE && pdec->mType != DT_CONST_TEMPLATE)) + { + Declaration* epdec = pdec->Clone(); + + tdec->mScope->Insert(epdec->mIdent, epdec->mBase); + epdec->mFlags |= DTF_DEFINED; + + if (ppdec) + ppdec->mNext = epdec; + else + tdec->mParams = epdec; + ppdec = epdec; + + pdec = pdec->mNext; + } + + // Now to the new parameters while (pdec) { Declaration* epdec = pdec->Clone(); @@ -8382,7 +8401,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp epdec->mBase = TheVoidTypeDeclaration; } } - else + else if (epdec->mType == DT_CONST_TEMPLATE) { if (exp->mType == EX_CONSTANT && (exp->mDecValue->mType == DT_CONST_INTEGER || exp->mDecValue->mType == DT_CONST_TEMPLATE)) epdec->mBase = exp->mDecValue; @@ -8400,13 +8419,25 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp ppdec = epdec; pdec = pdec->mNext; - if (pdec) - ConsumeToken(TK_COMMA); + if (pdec && !ConsumeTokenIf(TK_COMMA)) + break; } ConsumeToken(TK_GREATER_THAN); + + // Partial template arguments given + if (pdec) + { + if (ppdec) + ppdec->mNext = pdec; + else + tdec->mParams = pdec; + } } + while (!tmpld->mTokens) + tmpld = tmpld->mNext; + Declaration* etdec = tmpld->mNext; while (etdec && !etdec->IsSameParams(tdec)) etdec = etdec->mNext; @@ -8417,16 +8448,16 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp else { Declaration* epdec = tdec->mParams; - while (epdec && epdec->mBase->mType != DT_TYPE_TEMPLATE && epdec->mBase->mType != DT_CONST_TEMPLATE) + while (epdec && epdec->mBase && epdec->mBase->mType != DT_TYPE_TEMPLATE && epdec->mBase->mType != DT_CONST_TEMPLATE) epdec = epdec->mNext; if (epdec) { // Partial template specification - Declaration * bdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT); + Declaration * bdec = new Declaration(mScanner->mLocation, tmpld->mBase->mType); tdec->mBase = bdec; bdec->mTemplate = tdec; - bdec->mBase = tmpld->mBase; + bdec->mBase = tmpld->mBase->mBase; tdec->mNext = tmpld; bdec->mIdent = tdec->MangleIdent(); From 935a38607b8c455de60d340438cf614c1c460d44 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 14 Sep 2023 19:45:55 +0200 Subject: [PATCH 118/169] Bump version number --- README.md | 4 ++++ oscar64/Declaration.cpp | 2 +- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 6 +++--- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 99c82ea..1d9be93 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,10 @@ Supported Features: * default parameters for class members and functions * templates * vector, array and list template classes +* lambda functions +* auto variables, parameters and return types +* for range loop +* constexpr compile time evaluation ## Installation and Usage diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 663ba6b..850aeff 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1799,7 +1799,7 @@ bool Declaration::IsSameParams(const Declaration* dec) const if (ld->mValue != rd->mValue) return false; } - else if (ld->mType == DT_TYPE_TEMPLATE || ld->mType == DT_CONST_TEMPLATE) + else if (!ld->mBase || !rd->mBase) return false; else if (!ld->mBase->IsSame(rd->mBase)) return false; diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 53d3af2..2653d13 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.24.217"); + strcpy(strProductVersion, "1.25.218"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index a49c3fd..1fbb7d2 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,24,217,0 - PRODUCTVERSION 1,24,217,0 + FILEVERSION 1,25,218,0 + PRODUCTVERSION 1,25,218,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.24.217.0" + VALUE "FileVersion", "1.25.218.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.24.217.0" + VALUE "ProductVersion", "1.25.218.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index db7ea13..3e511e2 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5686,15 +5686,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{DC3B50CD-E9C6-4F59-9E59-986778C41793}" - "PackageCode" = "8:{DB830FCB-0CA0-4992-9D69-E76D9CA18459}" + "ProductCode" = "8:{041674C8-9934-4E51-B424-DA00BD3E2C89}" + "PackageCode" = "8:{7F8F7803-BF9B-423B-AD7F-ABAFD9B5DC8F}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.24.217" + "ProductVersion" = "8:1.25.218" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 06ebf85d9d05b8bf17244c8e5c77be505d6a204d Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 17 Sep 2023 10:24:28 +0200 Subject: [PATCH 119/169] Recursive variadic templates --- include/opp/vector.h | 1 + oscar64/Compiler.cpp | 10 + oscar64/Compiler.h | 1 + oscar64/CompilerTypes.h | 7 +- oscar64/Declaration.cpp | 90 ++++++- oscar64/Declaration.h | 10 +- oscar64/Errors.h | 1 + oscar64/InterCode.cpp | 52 ++++- oscar64/InterCode.h | 2 +- oscar64/InterCodeGenerator.cpp | 4 + oscar64/NativeCodeGenerator.cpp | 349 +++++++++++++++++++++++++++- oscar64/NativeCodeGenerator.h | 21 ++ oscar64/Parser.cpp | 399 ++++++++++++++++++++++++++------ oscar64/Parser.h | 5 +- oscar64/Scanner.cpp | 13 +- oscar64/Scanner.h | 1 + 16 files changed, 864 insertions(+), 102 deletions(-) diff --git a/include/opp/vector.h b/include/opp/vector.h index 30c8013..417e122 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -158,6 +158,7 @@ public: void pop_back(void) { _size--; + _data[_size].~T(); } void insert(int at, const T & t); diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index a0d9cb7..baae398 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -463,6 +463,7 @@ void Compiler::CompileProcedure(InterCodeProcedure* proc) printf("Generate native code <%s>\n", proc->mIdent->mString); ncproc->Compile(proc); + mNativeProcedures.Push(ncproc); } else { @@ -983,6 +984,15 @@ bool Compiler::GenerateCode(void) mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection); } + mNativeCodeGenerator->BuildFunctionProxies(); + + for (int i = 0; i < mNativeProcedures.Size(); i++) + { + if (mCompilerOptions & COPT_VERBOSE2) + printf("Assemble native code <%s>\n", mNativeProcedures[i]->mInterProc->mIdent->mString); + mNativeProcedures[i]->Assemble(); + } + LinkerObject* byteCodeObject = nullptr; if (!(mCompilerOptions & COPT_NATIVE)) { diff --git a/oscar64/Compiler.h b/oscar64/Compiler.h index 632b1fb..3b9f00d 100644 --- a/oscar64/Compiler.h +++ b/oscar64/Compiler.h @@ -27,6 +27,7 @@ public: GlobalAnalyzer* mGlobalAnalyzer; GrowingArray mByteCodeFunctions; + ExpandingArray mNativeProcedures; TargetMachine mTargetMachine; uint64 mCompilerOptions; diff --git a/oscar64/CompilerTypes.h b/oscar64/CompilerTypes.h index 5d0d66f..e6c6016 100644 --- a/oscar64/CompilerTypes.h +++ b/oscar64/CompilerTypes.h @@ -12,6 +12,7 @@ static const uint64 COPT_OPTIMIZE_AUTO_UNROLL = 1ULL << 6; static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 1ULL << 7; static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 1ULL << 8; static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9; +static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10; static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16; static const uint64 COPT_NATIVE = 1ULL << 17; @@ -43,11 +44,11 @@ static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS; -static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS; +static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS; -static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS; +static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS; -static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_AUTO_ZEROPAGE | COPT_OPTIMIZE_CONST_PARAMS; +static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_AUTO_ZEROPAGE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS; enum TargetMachine { diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 850aeff..8c3690b 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -300,6 +300,9 @@ void Expression::Dump(int ident) const case EX_RESULT: printf("RESULT"); break; + case EX_PACK: + printf("PACK"); + break; } printf("\n"); @@ -884,7 +887,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mMangleIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mNumVars(0), - mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), + mBase(nullptr), mParams(nullptr), mParamPack(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), mMutable(nullptr), mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), @@ -1076,6 +1079,10 @@ const Ident* Declaration::MangleIdent(void) { mMangleIdent = mBase->MangleIdent()->PreMangle("*"); } + else if (mType == DT_TYPE_ARRAY) + { + mMangleIdent = mBase->MangleIdent()->Mangle("[]"); + } else if (mType == DT_TYPE_STRUCT) { mMangleIdent = mQualIdent->PreMangle("struct "); @@ -1109,6 +1116,30 @@ const Ident* Declaration::MangleIdent(void) } mMangleIdent = mMangleIdent->Mangle(">"); } + else if (mType == DT_PACK_TYPE) + { + Declaration* dec = mBase; + while (dec) + { + const Ident* id; + if (dec->mBase) + id = dec->mBase->MangleIdent(); + else + id = dec->MangleIdent(); + + if (id) + { + if (mMangleIdent) + mMangleIdent = mMangleIdent->Mangle(id->mString); + else + mMangleIdent = id; + } + + dec = dec->mNext; + if (dec) + mMangleIdent = mMangleIdent->Mangle(","); + } + } else mMangleIdent = mQualIdent; @@ -1192,6 +1223,9 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) ptdec = ptdec->mNext; } + Declaration* phead = nullptr, * ptail = nullptr; + int pcnt = 0; + while (pexp) { Expression* ex = pexp; @@ -1205,10 +1239,42 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) if (pdec) { - if (!ResolveTemplate(ex->mDecType, pdec->mBase)) - return false; + if (pdec->mType == DT_PACK_ARGUMENT) + { + Declaration* tpdec = ex->mDecType; + if (tpdec->IsReference()) + tpdec = tpdec->mBase; + tpdec = tpdec->Clone(); - pdec = pdec->mNext; + if (ptail) + ptail->mNext = tpdec; + else + phead = tpdec; + ptail = tpdec; + } + else + { + if (!ResolveTemplate(ex->mDecType, pdec->mBase)) + return false; + + pdec = pdec->mNext; + } + } + else + return false; + } + + if (pdec) + { + if (pdec->mType == DT_PACK_ARGUMENT) + { + Declaration* tpdec = new Declaration(pdec->mLocation, DT_PACK_TYPE); + if (pdec->mBase->mType == DT_TYPE_REFERENCE) + tpdec->mIdent = pdec->mBase->mBase->mIdent; + else + tpdec->mIdent = pdec->mBase->mIdent; + tpdec->mBase = phead; + mScope->Insert(tpdec->mIdent, tpdec); } else return false; @@ -1259,13 +1325,17 @@ bool Declaration::CanResolveTemplate(Expression* pexp, Declaration* tdec) if (!ResolveTemplate(ex->mDecType, pdec->mBase)) return false; - pdec = pdec->mNext; + if (pdec->mType != DT_PACK_ARGUMENT) + pdec = pdec->mNext; } else return false; } - return true; + if (pdec) + return pdec->mType == DT_PACK_ARGUMENT; + else + return true; } bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) @@ -1341,6 +1411,10 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) return true; } + else if (tdec->mType == DT_PACK_TEMPLATE) + { + return true; + } else if (tdec->mType == DT_TYPE_STRUCT && fdec->mType == DT_TYPE_STRUCT && tdec->mTemplate) { Declaration *ftdec = tdec->mTemplate; @@ -1387,6 +1461,7 @@ Declaration* Declaration::Clone(void) ndec->mFlags = mFlags; ndec->mScope = mScope; ndec->mParams = mParams; + ndec->mParamPack = mParamPack; ndec->mIdent = mIdent; ndec->mQualIdent = mQualIdent; ndec->mValue = mValue; @@ -1400,6 +1475,7 @@ Declaration* Declaration::Clone(void) ndec->mMinValue = mMinValue; ndec->mMaxValue = mMaxValue; ndec->mCompilerOptions = mCompilerOptions; + ndec->mParser = mParser; return ndec; } @@ -1913,6 +1989,8 @@ bool Declaration::IsTemplateSame(const Declaration* dec, const Declaration * tde if (dec->mType == DT_TYPE_TEMPLATE) { dec = tdec->mScope->Lookup(dec->mIdent); + if (!dec) + return true; dflags |= dec->mFlags; } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index e22d2ce..757e75e 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -41,6 +41,11 @@ enum DecType DT_CONST_CONSTRUCTOR, DT_CONST_TEMPLATE, + DT_PACK_TEMPLATE, + DT_PACK_VARIABLE, + DT_PACK_ARGUMENT, + DT_PACK_TYPE, + DT_VARIABLE, DT_ARGUMENT, DT_ELEMENT, @@ -216,7 +221,8 @@ enum ExpressionType EX_BANKOF, EX_CONSTRUCT, EX_CLEANUP, - EX_RESULT + EX_RESULT, + EX_PACK }; class Expression @@ -254,7 +260,7 @@ public: Location mLocation, mEndLocation; DecType mType; Token mToken; - Declaration * mBase, * mParams, * mNext, * mPrev, * mConst, * mMutable; + Declaration * mBase, * mParams, * mParamPack, * mNext, * mPrev, * mConst, * mMutable; Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment, * mMoveConstructor, * mMoveAssignment; Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; Declaration * mVTable, * mClass, * mTemplate; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index c2d4b5c..7505713 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -85,6 +85,7 @@ enum ErrorID EERR_FUNCTION_TEMPLATE, EERR_INVALID_BITFIELD, EERR_INVALID_CAPTURE, + EERR_INVALID_PACK_USAGE, EERR_INVALID_CONSTEXPR, EERR_DOUBLE_FREE, diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 0cfc4e0..bfcd4a7 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4315,10 +4315,12 @@ void InterOperand::Disassemble(FILE* file, InterCodeProcedure* proc) } else if (mMemory == IM_PROCEDURE) { - if (mLinkerObject && mLinkerObject->mIdent) + if (proc->mModule->mProcedures[mVarIndex]) + vname = proc->mModule->mProcedures[mVarIndex]->mIdent->mString; + else if (mLinkerObject && mLinkerObject->mIdent) vname = mLinkerObject->mIdent->mString; } - else if (mMemory == IM_GLOBAL || mMemory == IM_PROCEDURE) + else if (mMemory == IM_GLOBAL) { if (mVarIndex < 0) vname = ""; @@ -4495,6 +4497,24 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc) else vname = proc->mLocalVars[mConst.mVarIndex]->mIdent->mString; } + else if (mConst.mMemory == IM_PROCEDURE) + { + if (proc->mModule->mProcedures[mConst.mVarIndex]) + vname = proc->mModule->mProcedures[mConst.mVarIndex]->mIdent->mString; + else if (mConst.mLinkerObject && mConst.mLinkerObject->mIdent) + vname = mConst.mLinkerObject->mIdent->mString; + } + else if (mConst.mMemory == IM_GLOBAL) + { + if (mConst.mVarIndex < 0) + vname = ""; + else if (!proc->mModule->mGlobalVars[mConst.mVarIndex]) + vname = "null"; + else if (!proc->mModule->mGlobalVars[mConst.mVarIndex]->mIdent) + vname = ""; + else + vname = proc->mModule->mGlobalVars[mConst.mVarIndex]->mIdent->mString; + } fprintf(file, "C%c%d(%d:%d '%s')", memchars[mConst.mMemory], mConst.mOperandSize, mConst.mVarIndex, int(mConst.mIntConst), vname); } @@ -15876,6 +15896,26 @@ void InterCodeBasicBlock::CollectGlobalReferences(NumberSet& referencedGlobals, else globalsChecked = false; break; + case IC_DISPATCH: + { + for (int j = 0; j < mProc->mCalledFunctions.Size(); j++) + { + InterCodeProcedure* proc = mProc->mCalledFunctions[j]; + + if (proc->mGlobalsChecked) + { + if (proc->mStoresIndirect) + storesIndirect = true; + if (proc->mLoadsIndirect) + loadsIndirect = true; + referencedGlobals |= proc->mReferencedGlobals; + modifiedGlobals |= proc->mModifiedGlobals; + } + else + globalsChecked = false; + } + } + break; } } @@ -16237,7 +16277,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mValueForwardingTable(nullptr), mLocalVars(nullptr), mParamVars(nullptr), mModule(mod), mIdent(ident), mLinkerObject(linkerObject), mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false), - mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), + mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mAssembled(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), mCheckUnreachable(true), mReturnType(IT_NONE), mCheapInline(false), mDeclaration(nullptr), mGlobalsChecked(false), mDispatchedCall(false) @@ -17102,7 +17142,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "test"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; @@ -17251,6 +17291,10 @@ void InterCodeProcedure::Close(void) else CollectVariables(paramMemory); + for (int i = 0; i < mLocalVars.Size(); i++) + if (i < mLocalAliasedSet.Size() && mLocalAliasedSet[i]) + mLocalVars[i]->mAliased = true; + BuildDataFlowSets(); ResetVisited(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 1c8e973..9fcf1eb 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -602,7 +602,7 @@ public: GrowingIntArray mTempOffset, mTempSizes; int mTempSize, mCommonFrameSize, mCallerSavedTemps, mFreeCallerSavedTemps, mFastCallBase; bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure; - bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack; + bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack, mAssembled; bool mDispatchedCall; bool mCheckUnreachable; GrowingInterCodeProcedurePtrArray mCalledFunctions; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index f1e7198..36efa32 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1640,6 +1640,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } break; + case EX_PACK: + mErrors->Error(exp->mLocation, EERR_INVALID_PACK_USAGE, "Invalid pack usage"); + return ExValue(TheVoidTypeDeclaration); + case EX_RESULT: { if (lrexp) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 44470aa..a6f8280 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -23308,6 +23308,53 @@ void NativeCodeBasicBlock::PropagateZPAbsolute(void) } } +void NativeCodeBasicBlock::RegisterFunctionCalls(void) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mIns.Size(); i++) + { + if (mIns[i].mType == ASMIT_JSR && mIns[i].mLinkerObject) + mProc->mGenerator->RegisterFunctionCall(this, i); + } + + if (mTrueJump) mTrueJump->RegisterFunctionCalls(); + if (mFalseJump) mFalseJump->RegisterFunctionCalls(); + } +} + +bool NativeCodeBasicBlock::MergeFunctionCalls(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mIns.Size(); i++) + { + if (mIns[i].mType == ASMIT_JSR && mIns[i].mLinkerObject) + { + if (mProc->mGenerator->MergeFunctionCall(this, i)) + changed = true; + } + } + + if (changed) + RemoveNops(); + + if (mTrueJump && mTrueJump->MergeFunctionCalls()) + changed = true; + if (mFalseJump && mFalseJump->MergeFunctionCalls()) + changed = true; + } + + return changed; +} + + bool NativeCodeBasicBlock::IsDominatedBy(const NativeCodeBasicBlock* block) const { if (this == block) @@ -41149,11 +41196,12 @@ void NativeCodeProcedure::LoadTempsFromStack(int tempSave) } } + void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "test"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41598,15 +41646,32 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) else mExitBlock->mIns.Push(NativeCodeInstruction(mExitBlock->mBranchIns, ASMIT_RTS, ASMIM_IMPLIED)); + + proc->mLinkerObject->mType = LOT_NATIVE_CODE; + + if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS) + { + ResetVisited(); + mEntryBlock->RegisterFunctionCalls(); + } +} + +void NativeCodeProcedure::Assemble(void) +{ + if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS) + { + ResetVisited(); + mEntryBlock->MergeFunctionCalls(); + } + mEntryBlock->Assemble(); + ResetVisited(); mEntryBlock = mEntryBlock->BypassEmptyBlocks(); ResetVisited(); mEntryBlock->ShortcutTailRecursion(); - proc->mLinkerObject->mType = LOT_NATIVE_CODE; - ExpandingArray placement; int total; @@ -41626,7 +41691,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) progress = true; } while (progress); - uint8* data = proc->mLinkerObject->AddSpace(total); + uint8* data = mInterProc->mLinkerObject->AddSpace(total); for (int i = 0; i < placement.Size(); i++) { @@ -41640,7 +41705,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) range.mIdent = Ident::Unique(buffer); range.mOffset = placement[i]->mOffset; range.mSize = placement[i]->mSize; - proc->mLinkerObject->mRanges.Push(range); + mInterProc->mLinkerObject->mRanges.Push(range); placement[i]->CopyCode(this, data); } @@ -41648,10 +41713,10 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) for (int i = 0; i < mRelocations.Size(); i++) { LinkerReference& rl(mRelocations[i]); - rl.mObject = proc->mLinkerObject; + rl.mObject = mInterProc->mLinkerObject; if (!rl.mRefObject) - rl.mRefObject = proc->mLinkerObject; - proc->mLinkerObject->AddReference(rl); + rl.mRefObject = mInterProc->mLinkerObject; + mInterProc->mLinkerObject->AddReference(rl); } if (mGenerator->mCompilerOptions & COPT_DEBUGINFO) @@ -41672,12 +41737,11 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) } mCodeLocations.SetSize(j + 1); - proc->mLinkerObject->AddLocations(mCodeLocations); + mInterProc->mLinkerObject->AddLocations(mCodeLocations); } } } - bool NativeCodeProcedure::MapFastParamsToTemps(void) { NumberSet used(256), modified(256), statics(256), pairs(256); @@ -41926,7 +41990,6 @@ void NativeCodeProcedure::Optimize(void) changed = true; #endif - if (step == 2) { ResetVisited(); @@ -43149,7 +43212,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode NativeCodeGenerator::NativeCodeGenerator(Errors* errors, Linker* linker, LinkerSection* runtimeSection) - : mErrors(errors), mLinker(linker), mRuntimeSection(runtimeSection), mCompilerOptions(COPT_DEFAULT) + : mErrors(errors), mLinker(linker), mRuntimeSection(runtimeSection), mCompilerOptions(COPT_DEFAULT), mFunctionCalls(nullptr) { } @@ -43257,6 +43320,242 @@ NativeCodeGenerator::Runtime& NativeCodeGenerator::ResolveRuntime(const Ident* i return mRuntime[i]; } +void NativeCodeGenerator::RegisterFunctionCall(NativeCodeBasicBlock* block, int at) +{ + LinkerObject* lo = block->mIns[at].mLinkerObject; + if (lo->mIdent && !(block->mIns[at].mFlags & NCIF_USE_ZP_32_X)) + { + int i = at; + while (i >= 2 && + block->mIns[i - 1].mType == ASMIT_STA && block->mIns[i - 1].mMode == ASMIM_ZERO_PAGE && + block->mIns[i - 1].mAddress >= BC_REG_FPARAMS && block->mIns[i - 1].mAddress < BC_REG_FPARAMS_END && + block->mIns[i - 2].mType == ASMIT_LDA && (block->mIns[i - 2].mMode == ASMIM_IMMEDIATE || block->mIns[i - 2].mMode == ASMIM_IMMEDIATE_ADDRESS || block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE)) + { + i -= 2; + } + + if (i < at) + { + FunctionCall* ncp = new FunctionCall(); + ncp->mLinkerObject = lo; + ncp->mProxyObject = nullptr; + ncp->mCount = 1; + while (i < at) + { + ncp->mIns[block->mIns[i + 1].mAddress - BC_REG_FPARAMS] = block->mIns[i]; + i += 2; + } + + FunctionCall* cp = mFunctionCalls; + while (cp && cp->mLinkerObject != ncp->mLinkerObject) + cp = cp->mNext; + if (!cp) + { + ncp->mNext = mFunctionCalls; + mFunctionCalls = ncp; + ncp->mSame = nullptr; + } + else + { + FunctionCall* scp = cp; + while (scp && !scp->IsSame(ncp)) + scp = scp->mSame; + if (!scp) + { + ncp->mSame = cp->mSame; + cp->mSame = ncp; + } + else + { + scp->mCount++; + ncp = scp; + } + } + } + } + +} + +bool NativeCodeGenerator::MergeFunctionCall(NativeCodeBasicBlock* block, int at) +{ + LinkerObject* lo = block->mIns[at].mLinkerObject; + if (lo->mIdent) + { + int i = at; + while (i >= 2 && + block->mIns[i - 1].mType == ASMIT_STA && block->mIns[i - 1].mMode == ASMIM_ZERO_PAGE && + block->mIns[i - 1].mAddress >= BC_REG_FPARAMS && block->mIns[i - 1].mAddress < BC_REG_FPARAMS_END && + block->mIns[i - 2].mType == ASMIT_LDA && (block->mIns[i - 2].mMode == ASMIM_IMMEDIATE || block->mIns[i - 2].mMode == ASMIM_IMMEDIATE_ADDRESS || block->mIns[i - 2].mMode == ASMIM_ZERO_PAGE || block->mIns[i - 2].mMode == ASMIM_ABSOLUTE)) + { + i -= 2; + } + + if (i < at) + { + FunctionCall ncp; + ncp.mLinkerObject = lo; + int j = i; + while (i < at) + { + ncp.mIns[block->mIns[i + 1].mAddress - BC_REG_FPARAMS] = block->mIns[i]; + i += 2; + } + + FunctionCall* cp = mFunctionCalls; + while (cp && cp->mLinkerObject != ncp.mLinkerObject) + cp = cp->mNext; + if (cp) + { + FunctionCall* bcp = nullptr; + int bmatch = 0; + + FunctionCall* scp = cp; + while (scp) + { + if (scp->mProxyObject) + { + int m = ncp.Matches(scp); + if (m > bmatch) + { + bmatch = m; + bcp = scp; + } + } + scp = scp->mSame; + } + + if (bcp) + { + while (j < at) + { + if (bcp->mIns[block->mIns[j + 1].mAddress - BC_REG_FPARAMS].mType != ASMIT_INV) + { + block->mIns[j + 0].mType = ASMIT_NOP; block->mIns[j + 0].mMode = ASMIM_IMPLIED; + block->mIns[j + 1].mType = ASMIT_NOP; block->mIns[j + 1].mMode = ASMIM_IMPLIED; + } + j += 2; + } + block->mIns[j].mLinkerObject = bcp->mProxyObject; + return true; + } + } + } + } + return false; +} + +void NativeCodeGenerator::BuildFunctionProxies(void) +{ + FunctionCall* cp = mFunctionCalls; + while (cp) + { + FunctionCall* ncp = cp; + while (ncp) + { + if (ncp->mCount > 1) + { + printf("RFC %s : %d\n", ncp->mLinkerObject->mIdent->mString, ncp->mCount); + ncp->mProxyObject = mLinker->AddObject(ncp->mLinkerObject->mLocation, ncp->mLinkerObject->mIdent->Mangle("@proxy"), ncp->mLinkerObject->mSection, ncp->mLinkerObject->mType); + + ExpandingArray code; + for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) + { + NativeCodeInstruction& ins(ncp->mIns[i - BC_REG_FPARAMS]); + if (ins.mType == ASMIT_LDA) + { + switch (ins.mMode) + { + case ASMIM_IMMEDIATE: + code.Push(uint8(AsmInsOpcodes[ASMIT_LDA][ASMIM_IMMEDIATE])); + code.Push(uint8(ins.mAddress)); + break; + case ASMIM_ZERO_PAGE: + code.Push(uint8(AsmInsOpcodes[ASMIT_LDA][ASMIM_ZERO_PAGE])); + if (ins.mLinkerObject) + { + LinkerReference rl; + rl.mObject = ncp->mProxyObject; + rl.mOffset = code.Size(); + + rl.mRefObject = ins.mLinkerObject; + rl.mRefOffset = ins.mAddress; + rl.mFlags = LREF_LOWBYTE; + + ncp->mProxyObject->AddReference(rl); + code.Push(0); + } + else + code.Push(uint8(ins.mAddress)); + break; + case ASMIM_IMMEDIATE_ADDRESS: + code.Push(uint8(AsmInsOpcodes[ASMIT_LDA][ASMIM_IMMEDIATE])); + if (ins.mLinkerObject) + { + LinkerReference rl; + rl.mObject = ncp->mProxyObject; + rl.mOffset = code.Size(); + rl.mFlags = 0; + if (ins.mFlags & NCIF_LOWER) + rl.mFlags |= LREF_LOWBYTE; + if (ins.mFlags & NCIF_UPPER) + rl.mFlags |= LREF_HIGHBYTE; + rl.mRefObject = ins.mLinkerObject; + rl.mRefOffset = ins.mAddress; + + ins.mLinkerObject->mFlags |= LOBJF_NO_CROSS; + + ncp->mProxyObject->AddReference(rl); + code.Push(0); + } + else + code.Push(uint8(ins.mAddress)); + break; + case ASMIM_ABSOLUTE: + code.Push(uint8(AsmInsOpcodes[ASMIT_LDA][ASMIM_ABSOLUTE])); + if (ins.mLinkerObject) + { + LinkerReference rl; + rl.mObject = ncp->mProxyObject; + rl.mOffset = code.Size(); + rl.mRefObject = ins.mLinkerObject; + rl.mRefOffset = ins.mAddress; + rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE; + ncp->mProxyObject->AddReference(rl); + code.Push(0); + code.Push(0); + } + else + { + code.Push(uint8(ins.mAddress & 0xff)); + code.Push(uint8(ins.mAddress >> 8)); + } + break; + } + code.Push(uint8(AsmInsOpcodes[ASMIT_STA][ASMIM_ZERO_PAGE])); + code.Push(uint8(i)); + } + } + code.Push(uint8(AsmInsOpcodes[ASMIT_JMP][ASMIM_ABSOLUTE])); + + LinkerReference rl; + rl.mObject = ncp->mProxyObject; + rl.mOffset = code.Size(); + rl.mRefObject = ncp->mLinkerObject; + rl.mRefOffset = 0; + rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE; + ncp->mProxyObject->AddReference(rl); + code.Push(0); + code.Push(0); + + ncp->mProxyObject->AddData(&(code[0]), code.Size()); + } + ncp = ncp->mSame; + } + cp = cp->mNext; + } +} + + void NativeCodeGenerator::RegisterRuntime(const Ident* ident, LinkerObject* object, int offset) { Runtime rt; @@ -43265,3 +43564,29 @@ void NativeCodeGenerator::RegisterRuntime(const Ident* ident, LinkerObject* obje rt.mOffset = offset; mRuntime.Push(rt); } + +bool NativeCodeGenerator::FunctionCall::IsSame(const FunctionCall* fc) const +{ + for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) + if (!mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS])) + return false; + return true; +} + +int NativeCodeGenerator::FunctionCall::Matches(const FunctionCall* fc) const +{ + int match = 0; + + for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++) + { + if (fc->mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV && mIns[i - BC_REG_FPARAMS].mType != ASMIT_INV) + { + if (!mIns[i - BC_REG_FPARAMS].IsSame(fc->mIns[i - BC_REG_FPARAMS])) + return -1; + match++; + } + } + + return match; +} + diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 9f2b280..eb72c46 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -669,6 +669,9 @@ public: void PropagateZPAbsolute(void); + void RegisterFunctionCalls(void); + bool MergeFunctionCalls(void); + bool IsDominatedBy(const NativeCodeBasicBlock* block) const; void CheckLive(void); @@ -702,6 +705,7 @@ class NativeCodeProcedure void Compile(InterCodeProcedure* proc); void Optimize(void); + void Assemble(void); NativeCodeBasicBlock* CompileBlock(InterCodeProcedure* iproc, InterCodeBasicBlock* block); NativeCodeBasicBlock* AllocateBlock(void); @@ -756,4 +760,21 @@ public: ExpandingArray mRuntime; ExpandingArray mMulTables; + + struct FunctionCall + { + LinkerObject * mLinkerObject, * mProxyObject; + NativeCodeInstruction mIns[64]; + FunctionCall * mNext, * mSame; + int mCount; + + bool IsSame(const FunctionCall* fc) const; + int Matches(const FunctionCall* fc) const; + }; + + FunctionCall* mFunctionCalls; + + void RegisterFunctionCall(NativeCodeBasicBlock* block, int at); + void BuildFunctionProxies(void); + bool MergeFunctionCall(NativeCodeBasicBlock* block, int at); }; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index f68964f..30391e4 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -271,6 +271,10 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio { break; } + else if (ConsumeTokenIf(TK_TEMPLATE)) + { + ParseTemplateDeclaration(pthis); + } else { Declaration* mdec = ParseDeclaration(nullptr, false, false, pthis); @@ -770,40 +774,48 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl dec = ParseBaseTypeQualify(qualified, dec, pident); - if (dec && dec->mType <= DT_TYPE_FUNCTION) + if (dec) { - if ((flags & ~dec->mFlags) == DTF_CONST) - dec = dec->ToConstType(); - else if (dec->IsSimpleType() && (flags & ~dec->mFlags)) - { - Declaration* ndec = new Declaration(dec->mLocation, dec->mType); - ndec->mFlags = dec->mFlags | flags; - ndec->mSize = dec->mSize; - ndec->mBase = dec->mBase; - dec = ndec; - } - else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) + if (dec->mType <= DT_TYPE_FUNCTION) { if ((flags & ~dec->mFlags) == DTF_CONST) dec = dec->ToConstType(); - else + else if (dec->IsSimpleType() && (flags & ~dec->mFlags)) { Declaration* ndec = new Declaration(dec->mLocation, dec->mType); ndec->mFlags = dec->mFlags | flags; ndec->mSize = dec->mSize; ndec->mBase = dec->mBase; - ndec->mScope = dec->mScope; - ndec->mParams = dec->mParams; - ndec->mIdent = dec->mIdent; - ndec->mQualIdent = dec->mQualIdent; dec = ndec; } + else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) + { + if ((flags & ~dec->mFlags) == DTF_CONST) + dec = dec->ToConstType(); + else + { + Declaration* ndec = new Declaration(dec->mLocation, dec->mType); + ndec->mFlags = dec->mFlags | flags; + ndec->mSize = dec->mSize; + ndec->mBase = dec->mBase; + ndec->mScope = dec->mScope; + ndec->mParams = dec->mParams; + ndec->mIdent = dec->mIdent; + ndec->mQualIdent = dec->mQualIdent; + dec = ndec; + } + } } + else if (dec->mType == DT_PACK_TEMPLATE || dec->mType == DT_PACK_TYPE) + { + if ((flags & ~dec->mFlags) == DTF_CONST) + dec = dec->ToConstType(); + } + else + mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); } - else if (!dec) - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); else - mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); break; @@ -1014,9 +1026,8 @@ Declaration* Parser::ParsePostfixDeclaration(void) ndec->mBase = dec; return ndec; } - else if (mScanner->mToken == TK_OPEN_PARENTHESIS) + else if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) { - mScanner->NextToken(); Declaration* vdec = ParsePostfixDeclaration(); if (mScanner->mToken == TK_CLOSE_PARENTHESIS) mScanner->NextToken(); @@ -1024,6 +1035,23 @@ Declaration* Parser::ParsePostfixDeclaration(void) mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "')' expected"); dec = vdec; } + else if (ConsumeTokenIf(TK_ELLIPSIS)) + { + if (mScanner->mToken == TK_IDENT) + { + dec = new Declaration(mScanner->mLocation, DT_PACK_VARIABLE); + dec->mIdent = mScanner->mTokenIdent; + dec->mSection = mBSSection; + dec->mBase = nullptr; + mScanner->NextToken(); + } + else + { + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + dec = new Declaration(mScanner->mLocation, DT_ANON); + dec->mBase = nullptr; + } + } else if (mScanner->mToken == TK_IDENT) { dec = new Declaration(mScanner->mLocation, DT_VARIABLE); @@ -1041,7 +1069,12 @@ Declaration* Parser::ParsePostfixDeclaration(void) while (!ConsumeTokenIf(TK_GREATER_THAN)) mScanner->NextToken(); - if (mTemplateScope->mName) + if (mTemplateScope->mParent) + { + if (mTemplateScope->mParent->mName) + dec->mIdent = dec->mIdent->Mangle(mTemplateScope->mParent->mName->mString); + } + else if (mTemplateScope->mName) dec->mIdent = dec->mIdent->Mangle(mTemplateScope->mName->mString); } } @@ -1145,31 +1178,94 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) if (!(adec->mBase->mFlags & DTF_DEFINED) && adec->mBase->mType != DT_TYPE_ARRAY && !adec->mBase->mTemplate) mErrors->Error(adec->mLocation, EERR_UNDEFINED_OBJECT, "Type of argument not defined"); - adec->mType = DT_ARGUMENT; - adec->mVarIndex = vi; - adec->mOffset = 0; - if (adec->mBase->mType == DT_TYPE_ARRAY) + if (adec->mType == DT_PACK_VARIABLE) { - Declaration* ndec = new Declaration(adec->mBase->mLocation, DT_TYPE_POINTER); - ndec->mBase = adec->mBase->mBase; - ndec->mSize = 2; - ndec->mFlags |= DTF_DEFINED; - adec->mBase = ndec; + adec->mType = DT_PACK_ARGUMENT; + if (adec->mBase) + { + ndec->mParamPack = adec; + + Declaration* atdec = adec->mBase; + + if (atdec->IsReference()) + atdec = atdec->mBase; + if (atdec->mType == DT_PACK_TYPE) + { + atdec = atdec->mBase; + + Declaration* apdec = adec; + while (atdec) + { + apdec = new Declaration(adec->mLocation, DT_ARGUMENT); + if (!adec->mParams) + adec->mParams = apdec; + + if (adec->mBase->IsReference()) + apdec->mBase = atdec->BuildReference(adec->mLocation); + else + apdec->mBase = atdec; + atdec = atdec->mNext; + apdec->mFlags = DTF_DEFINED; + apdec->mVarIndex = vi; + apdec->mOffset = 0; + + if (apdec->mBase->mType == DT_TYPE_ARRAY) + { + Declaration* ndec = new Declaration(apdec->mBase->mLocation, DT_TYPE_POINTER); + ndec->mBase = apdec->mBase->mBase; + ndec->mSize = 2; + ndec->mFlags |= DTF_DEFINED; + apdec->mBase = ndec; + } + + apdec->mSize = apdec->mBase->mSize; + + vi += apdec->mSize; + if (pdec) + pdec->mNext = apdec; + else + ndec->mParams = apdec; + pdec = apdec; + } + } + else + { + if (pdec) + pdec->mNext = adec; + else + ndec->mParams = adec; + pdec = adec; + } + } } - - adec->mSize = adec->mBase->mSize; - - if ((mCompilerOptions & COPT_CPLUSPLUS) && ConsumeTokenIf(TK_ASSIGN)) - { - adec->mValue = ParseExpression(false); - } - - vi += adec->mSize; - if (pdec) - pdec->mNext = adec; else - ndec->mParams = adec; - pdec = adec; + { + adec->mType = DT_ARGUMENT; + adec->mVarIndex = vi; + adec->mOffset = 0; + if (adec->mBase->mType == DT_TYPE_ARRAY) + { + Declaration* ndec = new Declaration(adec->mBase->mLocation, DT_TYPE_POINTER); + ndec->mBase = adec->mBase->mBase; + ndec->mSize = 2; + ndec->mFlags |= DTF_DEFINED; + adec->mBase = ndec; + } + + adec->mSize = adec->mBase->mSize; + + if ((mCompilerOptions & COPT_CPLUSPLUS) && ConsumeTokenIf(TK_ASSIGN)) + { + adec->mValue = ParseExpression(false); + } + + vi += adec->mSize; + if (pdec) + pdec->mNext = adec; + else + ndec->mParams = adec; + pdec = adec; + } if (mScanner->mToken == TK_COMMA) mScanner->NextToken(); @@ -4057,6 +4153,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ldec && ldec != pdec) mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); } + else if (ptempl && mTemplateScope && pthis) + { + } else if (!pdec) mErrors->Error(ndec->mLocation, EERR_OBJECT_NOT_FOUND, "Object not declarared in scope", ndec->mQualIdent); @@ -4433,7 +4532,7 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) } else if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mBase->mDestructor) { - Expression* vexp = new Expression(pdec->mLocation, EX_VARIABLE); + Expression* vexp = new Expression(dec->mLocation, EX_VARIABLE); vexp->mDecType = dec->mBase; vexp->mDecValue = dec; @@ -5203,6 +5302,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp->mDecType = dec->mBase; } } + else if (dec->mType == DT_PACK_ARGUMENT) + { + exp = new Expression(mScanner->mLocation, EX_PACK); + exp->mDecValue = dec; + exp->mDecType = dec->mBase; + } else if (dec->mType <= DT_TYPE_FUNCTION) { if (lhs) @@ -5561,6 +5666,7 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) int dist = 0; + bool packtemp = false; while (pexp) { Expression* ex = pexp; @@ -5579,9 +5685,21 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) if (etype->mType == DT_TYPE_REFERENCE) etype = etype->mBase; - if (ptype->mType == DT_TYPE_TEMPLATE) + if (ptype->mType == DT_PACK_TEMPLATE || ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_PACK_TEMPLATE) + packtemp = true; + + if (ptype->mType == DT_TYPE_TEMPLATE || ptype->mType == DT_PACK_TEMPLATE) { dist += 1; + } + else if (ptype->mType == DT_TYPE_REFERENCE && (ptype->mBase->mType == DT_TYPE_TEMPLATE || ptype->mBase->mType == DT_PACK_TEMPLATE)) + { + if (ex->IsLValue()) + dist += 1; + else if (ptype->mBase->mFlags & DTF_CONST) + dist += 1; + else + return NOOVERLOAD; } else if (ptype->mType == DT_TYPE_INTEGER && etype->mType == DT_TYPE_INTEGER) { @@ -5701,10 +5819,15 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) else return NOOVERLOAD; } + else if (ptype->mType == DT_TYPE_REFERENCE && (ptype->mBase->mFlags & DTF_CONST) && ptype->mBase->CanAssign(etype)) + { + dist += 32; + } else return NOOVERLOAD; - pdec = pdec->mNext; + if (!packtemp) + pdec = pdec->mNext; } else if (fdec->mBase->mFlags & DTF_VARIADIC) { @@ -5721,6 +5844,16 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) pdec = pdec->mNext; } + if (pdec) + { + Declaration* ptype = pdec->mBase; + if (ptype->mType == DT_PACK_TEMPLATE || ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_PACK_TEMPLATE) + packtemp = true; + } + + if (pdec && packtemp) + return dist; + if (pdec) return NOOVERLOAD; @@ -7567,15 +7700,43 @@ Expression* Parser::ParseExpression(bool lhs) return ParseAssignmentExpression(lhs); } +Expression* Parser::ExpandArgumentPack(Expression* exp, Declaration* dec) +{ + Expression* vex = new Expression(exp->mLocation, EX_VARIABLE); + vex->mDecType = dec->mBase; + vex->mDecValue = dec; + + if (dec->mNext) + { + Expression* lex = new Expression(exp->mLocation, EX_LIST); + lex->mToken = TK_COMMA; + lex->mLeft = vex; + lex->mRight = ExpandArgumentPack(exp, dec->mNext); + return lex; + } + else + return vex; +} + Expression* Parser::ParseListExpression(bool lhs) { Expression* exp = ParseExpression(lhs); - if (mScanner->mToken == TK_COMMA) + if (exp->mType == EX_PACK) + { + if (ConsumeTokenIf(TK_ELLIPSIS)) + { + if (exp->mDecValue->mParams) + exp = ExpandArgumentPack(exp, exp->mDecValue->mParams); + else + exp = nullptr; + } + } + + if (ConsumeTokenIf(TK_COMMA)) { Expression* nexp = new Expression(mScanner->mLocation, EX_LIST); - nexp->mToken = mScanner->mToken; + nexp->mToken = TK_COMMA; nexp->mLeft = exp; - mScanner->NextToken(); nexp->mRight = ParseListExpression(false); exp = nexp; } @@ -7607,6 +7768,8 @@ Expression* Parser::ParseFunction(Declaration * dec) scope->Insert(pdec->mIdent, pdec); pdec = pdec->mNext; } + if (dec->mParamPack) + mScope->Insert(dec->mParamPack->mIdent, dec->mParamPack); mLocalIndex = 0; mTempVars = nullptr; @@ -8183,6 +8346,16 @@ Expression* Parser::ParseStatement(void) if (mFunctionType->mBase->mType == DT_TYPE_AUTO) { mFunctionType->mBase = exp->mLeft->mDecType; + if (mFunctionType->mBase->mType == DT_TYPE_STRUCT) + { + // Make room for value struct return + Declaration* p = mFunctionType->mParams; + while (p) + { + p->mVarIndex += 2; + p = p->mNext; + } + } } exp->mLeft = CoerceExpression(exp->mLeft, mFunctionType->mBase); } @@ -8349,15 +8522,50 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp if (expd) { - tdec->mParams = expd->mParams; - Declaration* dec = tdec->mParams; - Declaration* xdec = tmpld->mParams; + if (tmpld->mBase->mType == DT_TEMPLATE) + { + Parser* p = tmpld->mBase->mParser->Clone(); + + p->mScanner->Replay(tmpld->mBase->mTokens); + + tdec = tmpld->mBase->Clone(); + tdec->mScope->mName = expd->mScope->mName; + tdec->mScope->mParent = expd->mScope; + + p->ParseTemplateDeclarationBody(tdec, nullptr); + + return tdec; + } + + Declaration* ppdec = nullptr; + Declaration* dec = expd->mParams; + Declaration* pdec = tmpld->mParams; + while (dec) { - tdec->mScope->Insert(xdec->mIdent, dec->mBase); + Declaration* epdec = dec->Clone(); + + tdec->mScope->Insert(epdec->mIdent, epdec->mBase); + epdec->mFlags |= DTF_DEFINED; + + if (ppdec) + ppdec->mNext = epdec; + else + tdec->mParams = epdec; + ppdec = epdec; + dec = dec->mNext; - xdec = xdec->mNext; + pdec = pdec->mNext; } + + if (pdec) + { + if (ppdec) + ppdec->mNext = pdec; + else + tdec->mParams = pdec; + } + } else { @@ -8438,6 +8646,8 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp while (!tmpld->mTokens) tmpld = tmpld->mNext; + Declaration* pthis = tmpld->mClass; + Declaration* etdec = tmpld->mNext; while (etdec && !etdec->IsSameParams(tdec)) etdec = etdec->mNext; @@ -8464,7 +8674,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp return bdec; } - Parser* p = tmpld->mParser; + Parser* p = tmpld->mParser->Clone(); p->mScanner->Replay(tmpld->mTokens); @@ -8472,6 +8682,8 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp tdec->mNext = tmpld->mNext; tmpld->mNext = tdec; + tdec->mScope->mParent = tmpld->mScope->mParent; + p->mTemplateScope = tdec->mScope; if (tmpld->mFlags & DTF_AUTO_TEMPLATE) { @@ -8501,7 +8713,10 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp ndec->mQualIdent = ndec->mQualIdent->Mangle(tdec->mScope->mName->mString); } else - tdec->mBase = p->ParseDeclaration(nullptr, true, false, nullptr, tdec); + { + tdec->mBase = p->ParseDeclaration(nullptr, true, false, tmpld->mClass, tdec); + } + p->mTemplateScope = nullptr; if (tdec->mBase->mType == DT_ANON) @@ -8522,7 +8737,15 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp mpdec = mpdec->mNext; if (mpdec && mpdec->mTemplate) { - p->ParseTemplateExpansion(mpdec->mTemplate, tdec); + if (mdec->mTemplate) + { + Declaration * mtdec = p->ParseTemplateExpansion(mpdec->mTemplate, tdec); + mtdec->mClass = mdec->mTemplate->mClass; + mdec->mTemplate = mtdec; + mdec->mTemplate->mBase = mdec; + } + else + p->ParseTemplateExpansion(mpdec->mTemplate, tdec); } } @@ -8669,21 +8892,33 @@ Declaration* Parser::FunctionAutoParamsToTemplate(Declaration* fdec) return nullptr; } -void Parser::ParseTemplateDeclaration(void) +Declaration * Parser::ParseTemplateDeclaration(Declaration* pthis) { - ConsumeToken(TK_LESS_THAN); Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); tdec->mParser = this->Clone(); - tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + tdec->mScope = new DeclarationScope(mTemplateScope, SLEVEL_TEMPLATE); + tdec->mClass = pthis; Declaration* ppdec = nullptr; + ConsumeToken(TK_LESS_THAN); for (;;) { Declaration* pdec = nullptr; - if (ConsumeTokenIf(TK_CLASS)) + if (ConsumeTokenIf(TK_CLASS) || ConsumeTokenIf(TK_TYPENAME)) { - if (mScanner->mToken == TK_IDENT) + if (ConsumeTokenIf(TK_ELLIPSIS)) + { + if (mScanner->mToken == TK_IDENT) + { + pdec = new Declaration(mScanner->mLocation, DT_PACK_TEMPLATE); + pdec->mIdent = mScanner->mTokenIdent; + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + } + else if (mScanner->mToken == TK_IDENT) { pdec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); pdec->mIdent = mScanner->mTokenIdent; @@ -8724,6 +8959,21 @@ void Parser::ParseTemplateDeclaration(void) ConsumeToken(TK_GREATER_THAN); + if (ConsumeTokenIf(TK_TEMPLATE)) + { + mTemplateScope = tdec->mScope; + tdec->mBase = ParseTemplateDeclaration(pthis); + mTemplateScope = tdec->mScope->mParent; + tdec->mBase->mBase->mTemplate = tdec; + } + else + ParseTemplateDeclarationBody(tdec, pthis); + + return tdec; +} + +void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthis) +{ mScanner->BeginRecord(); if (mScanner->mToken == TK_CLASS) { @@ -8772,10 +9022,13 @@ void Parser::ParseTemplateDeclaration(void) adec = ReverseDeclaration(adec, bdec); - mTemplateScope = nullptr; + mTemplateScope = tdec->mScope->mParent; if (adec->mBase->mType == DT_TYPE_FUNCTION) { + if (pthis) + PrependThisArgument(adec->mBase, pthis); + if (ConsumeTokenIf(TK_CONST)) adec->mBase->mFlags |= DTF_CONST; @@ -8801,6 +9054,18 @@ void Parser::ParseTemplateDeclaration(void) mScanner->NextToken(); } } + else if (ConsumeTokenIf(TK_SEMICOLON)) + { + + } + else + { + mErrors->Error(bdec->mLocation, EERR_FUNCTION_TEMPLATE, "Function template body expected"); + adec->mType = DT_TYPE_VOID; + tdec->mBase = adec; + adec->mIdent = adec->mQualIdent = Ident::Unique("_"); + adec->mTemplate = tdec; + } } else { @@ -10440,7 +10705,7 @@ void Parser::ParseNamespace(void) else if (mScanner->mToken == TK_TEMPLATE) { mScanner->NextToken(); - ParseTemplateDeclaration(); + ParseTemplateDeclaration(nullptr); } else if (mScanner->mToken == TK_NAMESPACE) { @@ -10523,7 +10788,7 @@ void Parser::Parse(void) else if (mScanner->mToken == TK_TEMPLATE) { mScanner->NextToken(); - ParseTemplateDeclaration(); + ParseTemplateDeclaration(nullptr); } else if (mScanner->mToken == TK_NAMESPACE) { diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 13feebf..7e56ab5 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -105,7 +105,8 @@ protected: void CompleteFunctionDefaultParams(Expression* exp); void ExpandFunctionCallTemplate(Expression* exp); - void ParseTemplateDeclaration(void); + Declaration * ParseTemplateDeclaration(Declaration* pthis); + void ParseTemplateDeclarationBody(Declaration* tdec, Declaration* pthis); Declaration* FunctionAutoParamsToTemplate(Declaration* fdec); Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); @@ -130,6 +131,8 @@ protected: Expression* ParseAssignmentExpression(bool lhs); Expression* ParseExpression(bool lhs); Expression* ParseRExpression(void); + + Expression* ExpandArgumentPack(Expression * exp, Declaration* dec); Expression* ParseListExpression(bool lhs); Expression* ParseParenthesisExpression(void); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 5b23920..849a06e 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -165,6 +165,7 @@ const char* TokenNames[] = "'template'", "'friend'", "'constexpr'", + "'typename'", }; @@ -482,14 +483,12 @@ void Scanner::NextToken(void) mReplay = mReplay->mNext; } else - { NextPreToken(); - if (mRecord) - { - mRecordLast->mNext = new TokenSequence(this); - mRecordLast = mRecordLast->mNext; - } + if (mRecord) + { + mRecordLast->mNext = new TokenSequence(this); + mRecordLast = mRecordLast->mNext; } } @@ -1520,6 +1519,8 @@ void Scanner::NextRawToken(void) mToken = TK_FRIEND; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "constexpr")) mToken = TK_CONSTEXPR; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "typename")) + mToken = TK_TYPENAME; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 3408285..9d6ade7 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -164,6 +164,7 @@ enum Token TK_TEMPLATE, TK_FRIEND, TK_CONSTEXPR, + TK_TYPENAME, NUM_TOKENS }; From c674fc9a8b9d3386c87f602dc0cfb479b5476ff9 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 17 Sep 2023 11:39:18 +0200 Subject: [PATCH 120/169] Add variadic sizeof... --- oscar64/Declaration.cpp | 12 ++++-------- oscar64/InterCodeGenerator.cpp | 16 ++++++++++++---- oscar64/Linker.cpp | 32 ++++++++++++++++++++++++++++++++ oscar64/Linker.h | 3 +++ oscar64/Parser.cpp | 30 ++++++++++++++++++++++++++---- 5 files changed, 77 insertions(+), 16 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 8c3690b..8622ac8 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1069,15 +1069,15 @@ const Ident* Declaration::MangleIdent(void) } else if (mType == DT_TYPE_REFERENCE) { - mMangleIdent = mBase->MangleIdent()->PreMangle("&"); + mMangleIdent = mBase->MangleIdent()->Mangle("&"); } else if (mType == DT_TYPE_RVALUEREF) { - mMangleIdent = mBase->MangleIdent()->PreMangle("&&"); + mMangleIdent = mBase->MangleIdent()->Mangle("&&"); } else if (mType == DT_TYPE_POINTER) { - mMangleIdent = mBase->MangleIdent()->PreMangle("*"); + mMangleIdent = mBase->MangleIdent()->Mangle("*"); } else if (mType == DT_TYPE_ARRAY) { @@ -1121,11 +1121,7 @@ const Ident* Declaration::MangleIdent(void) Declaration* dec = mBase; while (dec) { - const Ident* id; - if (dec->mBase) - id = dec->mBase->MangleIdent(); - else - id = dec->MangleIdent(); + const Ident* id = dec->MangleIdent(); if (id) { diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 36efa32..4593fa3 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1851,11 +1851,19 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* var->mIdent = dec->mQualIdent; var->mOffset = 0; var->mSize = dec->mSize; - if ((dec->mFlags & DTF_VAR_ALIASING) || dec->mBase->mType == DT_TYPE_ARRAY) - var->mAliased = true; var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment); - dec->mLinkerObject = var->mLinkerObject; + + if (dec->mBase->mFlags & DTF_CONST) + var->mLinkerObject->mFlags |= LOBJF_CONST; + else if ((dec->mFlags & DTF_VAR_ALIASING) || dec->mBase->mType == DT_TYPE_ARRAY) + var->mAliased = true; var->mLinkerObject->AddData(dec->mData, dec->mSize); + + LinkerObject* aobj = mLinker->FindSame(var->mLinkerObject); + if (aobj) + var->mLinkerObject = aobj; + + dec->mLinkerObject = var->mLinkerObject; proc->mModule->mGlobalVars.Push(var); } @@ -4989,7 +4997,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 1 if (proc->mIdent && !strcmp(proc->mIdent->mString, "main")) exp->Dump(0); #endif diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index 05d803a..8bc60d5 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -274,6 +274,38 @@ LinkerObject* Linker::FindObjectByAddr(int bank, int addr) return FindObjectByAddr(addr); } +LinkerObject* Linker::FindSame(LinkerObject* obj) +{ + for (int i = 0; i < mObjects.Size(); i++) + { + LinkerObject* lobj = mObjects[i]; + if (lobj != obj && obj->IsSameConst(lobj)) + return lobj; + } + + return nullptr; +} + +bool LinkerObject::IsSameConst(const LinkerObject* obj) const +{ + if ((mFlags & LOBJF_CONST) && mFlags == obj->mFlags && + mSection == obj->mSection && mSize == obj->mSize && mAlignment == obj->mAlignment && + mReferences.Size() == obj->mReferences.Size()) + { + for (int i = 0; i < mSize; i++) + if (mData[i] != obj->mData[i]) + return false; + + for (int i = 0; i < mReferences.Size(); i++) + if (mReferences[i] != obj->mReferences[i]) + return false; + + return true; + } + + return false; +} + LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, LinkerSection * section, LinkerObjectType type, int alignment) { LinkerObject* obj = new LinkerObject; diff --git a/oscar64/Linker.h b/oscar64/Linker.h index 364c3c8..c87a689 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -213,6 +213,8 @@ public: void MoveToSection(LinkerSection* section); void MarkRelevant(void); + + bool IsSameConst(const LinkerObject* obj) const; }; class LinkerOverlay @@ -246,6 +248,7 @@ public: bool IsSectionPlaced(LinkerSection* section); LinkerObject * AddObject(const Location & location, const Ident* ident, LinkerSection * section, LinkerObjectType type, int alignment = 1); + LinkerObject* FindSame(LinkerObject* obj); LinkerOverlay* AddOverlay(const Location& location, const Ident* ident, int bank); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 30391e4..5089016 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3415,7 +3415,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) else if ((pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) && pex->mType == EX_CONSTANT) { // A simple constant is passed by const ref - if (pex->mDecValue->mType == DT_CONST_INTEGER || pex->mDecValue->mType == DT_CONST_FLOAT || pex->mDecValue->mType == DT_CONST_POINTER) + if (pex->mDecValue->mType == DT_CONST_INTEGER || pex->mDecValue->mType == DT_CONST_FLOAT || pex->mDecValue->mType == DT_CONST_POINTER || pex->mDecValue->mType == DT_CONST_ADDRESS) { int nindex = mLocalIndex++; @@ -5076,7 +5076,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) dec->mBase = new Declaration(mScanner->mLocation, DT_TYPE_ARRAY); dec->mBase->mSize = dec->mSize; dec->mBase->mBase = TheConstCharTypeDeclaration; - dec->mBase->mFlags |= DTF_DEFINED; + dec->mBase->mFlags |= DTF_DEFINED | DTF_CONST; uint8* d = new uint8[size + 1]; dec->mData = d; @@ -5343,10 +5343,32 @@ Expression* Parser::ParseSimpleExpression(bool lhs) break; case TK_SIZEOF: mScanner->NextToken(); - rexp = ParseParenthesisExpression(); + dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); dec->mBase = TheSignedIntTypeDeclaration; - dec->mInteger = rexp->mDecType->mSize; + + if (ConsumeTokenIf(TK_ELLIPSIS)) + { + rexp = ParseParenthesisExpression(); + if (rexp->mType == EX_PACK) + { + int n = 0; + Declaration* vdec = rexp->mDecValue->mParams; + while (vdec) + { + n++; + vdec = vdec->mNext; + } + dec->mInteger = n; + } + else + mErrors->Error(mScanner->mLocation, EERR_INVALID_PACK_USAGE, "variadic pack expected"); + } + else + { + rexp = ParseParenthesisExpression(); + dec->mInteger = rexp->mDecType->mSize; + } exp = new Expression(mScanner->mLocation, EX_CONSTANT); exp->mDecValue = dec; exp->mDecType = dec->mBase; From 38274fb4f7dcd9ee162fd4d45be4163912cda7a2 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 17 Sep 2023 15:40:05 +0200 Subject: [PATCH 121/169] Add emplace_back in vector --- include/opp/vector.h | 26 +++++++++++++++---- oscar64/Constexpr.cpp | 26 ++++++++++++++++--- oscar64/Declaration.cpp | 46 +++++++++++++++++++++++++++------- oscar64/InterCode.cpp | 41 ++++++++++++++++++++++++++++-- oscar64/InterCodeGenerator.cpp | 2 +- oscar64/Parser.cpp | 32 ++++++++++++++++++++--- 6 files changed, 148 insertions(+), 25 deletions(-) diff --git a/include/opp/vector.h b/include/opp/vector.h index 417e122..d28d51e 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -164,6 +164,11 @@ public: void insert(int at, const T & t); void erase(int at, int n = 1); + + template + void emplace_back(const P&... p); +protected: + T * add_back(void); }; @@ -224,19 +229,30 @@ void vector::shrink_to_fit(void) } template -void vector::push_back(const T & t) +T * vector::add_back(void) { if (_size == _capacity) reserve(_size + 1 + (_size >> 1)); - new (_data + _size++)T(t); + return _data + _size++; +} + +template +void vector::push_back(const T & t) +{ + new (add_back())T(t); } template void vector::push_back(T && t) { - if (_size == _capacity) - reserve(_size + 1 + (_size >> 1)); - new (_data + _size++)T(t); + new (add_back())T(t); +} + +template +template +void vector::emplace_back(const P&... p) +{ + new (add_back())T(p...); } template diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index 1a5b83d..3d36080 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -885,7 +885,11 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons if (dec) pos = dec->mVarIndex; - mParams[pos] = caller->REval(pex->mLeft); + if (dec) + mParams[pos] = caller->EvalCoerce(pex->mLeft, caller->Eval(pex->mLeft), dec->mBase); + else + mParams[pos] = caller->REval(pex->mLeft); + pos += dec->mSize; pex = pex->mRight; if (dec) @@ -895,7 +899,10 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons { if (dec) pos = dec->mVarIndex; - mParams[pos] = caller->REval(pex); + if (dec) + mParams[pos] = caller->EvalCoerce(pex, caller->Eval(pex), dec->mBase); + else + mParams[pos] = caller->REval(pex); } if (exp->mLeft->mDecValue->mFlags & DTF_INTRINSIC) @@ -976,14 +983,25 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) return Value(exp); case EX_VARIABLE: if (exp->mDecValue->mType == DT_ARGUMENT) - return Value(&mParams[exp->mDecValue->mVarIndex]); + { + if (mParams[exp->mDecValue->mVarIndex].mBaseValue) + return mParams[exp->mDecValue->mVarIndex]; + else + 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]); + return Value(&mLocals[exp->mDecValue->mVarIndex]); + } + else if (mLocals[exp->mDecValue->mVarIndex].mBaseValue) + return mLocals[exp->mDecValue->mVarIndex]; + else + return Value(&mLocals[exp->mDecValue->mVarIndex]); } } break; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 8622ac8..bef5f0d 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1240,7 +1240,11 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) Declaration* tpdec = ex->mDecType; if (tpdec->IsReference()) tpdec = tpdec->mBase; - tpdec = tpdec->Clone(); + + if (tpdec->mType == DT_TYPE_ARRAY) + tpdec = tpdec->mBase->BuildPointer(tpdec->mLocation); + else + tpdec = tpdec->Clone(); if (ptail) ptail->mNext = tpdec; @@ -1338,6 +1342,8 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) { if (tdec->IsSame(fdec)) return true; + else if (fdec->IsReference()) + return ResolveTemplate(fdec->mBase, tdec); else if (tdec->mType == DT_TYPE_FUNCTION) { if (fdec->mType == DT_TYPE_FUNCTION) @@ -1369,17 +1375,11 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) } else if (tdec->mType == DT_TYPE_REFERENCE) { - if (fdec->mType == DT_TYPE_REFERENCE) - return ResolveTemplate(fdec->mBase, tdec->mBase); - else - return ResolveTemplate(fdec, tdec->mBase); + return ResolveTemplate(fdec, tdec->mBase); } else if (tdec->mType == DT_TYPE_RVALUEREF) { - if (fdec->mType == DT_TYPE_RVALUEREF) - return ResolveTemplate(fdec->mBase, tdec->mBase); - else - return ResolveTemplate(fdec, tdec->mBase); + return ResolveTemplate(fdec, tdec->mBase); } else if (tdec->mType == DT_TYPE_POINTER) { @@ -1390,6 +1390,9 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) } else if (tdec->mType == DT_TYPE_TEMPLATE) { + if (fdec->mType == DT_TYPE_ARRAY) + fdec = fdec->mBase->BuildPointer(fdec->mLocation); + Declaration* pdec; if (tdec->mBase) { @@ -1871,6 +1874,11 @@ bool Declaration::IsSameParams(const Declaration* dec) const if (ld->mValue != rd->mValue) return false; } + else if (ld->mType == DT_PACK_TEMPLATE && rd->mType == DT_PACK_TEMPLATE) + { + if (!ld->mBase->IsSameParams(rd->mBase)) + return false; + } else if (!ld->mBase || !rd->mBase) return false; else if (!ld->mBase->IsSame(rd->mBase)) @@ -1881,6 +1889,19 @@ bool Declaration::IsSameParams(const Declaration* dec) const return !ld && !rd; } + else if (mType == DT_PACK_TYPE && dec->mType == DT_PACK_TYPE) + { + Declaration* ld = mBase, * rd = dec->mBase; + while (ld && rd) + { + if (!ld->IsSame(rd)) + return false; + ld = ld->mNext; + rd = rd->mNext; + } + + return !ld && !rd; + } else return false; } @@ -1989,6 +2010,13 @@ bool Declaration::IsTemplateSame(const Declaration* dec, const Declaration * tde return true; dflags |= dec->mFlags; } + else if (dec->mType == DT_PACK_TEMPLATE) + { + dec = tdec->mScope->Lookup(dec->mIdent); + if (!dec) + return true; + dflags |= dec->mFlags; + } if (this == dec) return true; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index bfcd4a7..9c008a9 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -692,7 +692,19 @@ bool InterCodeBasicBlock::CanSwapInstructions(const InterInstruction* ins0, cons ins0->mCode == IC_PUSH_FRAME || ins0->mCode == IC_POP_FRAME || ins0->mCode == IC_MALLOC || ins0->mCode == IC_FREE) return false; - if (ins0->mCode == IC_LOAD || ins0->mCode == IC_STORE || ins0->mCode == IC_COPY || ins0->mCode == IC_STRCPY) + if (ins0->mCode == IC_LOAD) + { + if (ins0->mSrc[0].mTemp >= 0) + return false; + if (ins0->mSrc[0].mMemory == IM_PARAM || ins0->mSrc[0].mMemory == IM_FPARAM) + { + if (mProc->mParamAliasedSet[ins0->mSrc[0].mVarIndex]) + return false; + } + else + return false; + } + else if (ins0->mCode == IC_STORE || ins0->mCode == IC_COPY || ins0->mCode == IC_STRCPY) return false; } if (ins0->mCode == IC_CALL || ins0->mCode == IC_CALL_NATIVE || ins0->mCode == IC_ASSEMBLER) @@ -13675,6 +13687,31 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa InterCodeBasicBlock* tailBlock = this == mTrueJump ? mFalseJump : mTrueJump; assert(tailBlock->mNumEntries == 1); + // remove counting loop without body + if (mInstructions.Size() == 3) + { + InterInstruction* ains = mInstructions[0]; + InterInstruction* cins = mInstructions[1]; + InterInstruction* bins = mInstructions[2]; + + if (ains->mCode == IC_BINARY_OPERATOR && cins->mCode == IC_RELATIONAL_OPERATOR && bins->mCode == IC_BRANCH) + { + if (ains->mSrc[1].mTemp == ains->mDst.mTemp && ains->mSrc[0].mTemp < 0 && + cins->mSrc[1].mTemp == ains->mDst.mTemp && ains->mSrc[0].mTemp < 0 && + bins->mSrc[0].mTemp == cins->mDst.mTemp && bins->mSrc[0].mFinal) + { + if (ains->mOperator == IA_ADD && ains->mSrc[0].mIntConst == 1 && + cins->mOperator == IA_CMPLU && mTrueJump == this && !tailBlock->mEntryRequiredTemps[ains->mDst.mTemp]) + { + cins->mCode = IC_CONSTANT; + cins->mConst.mType = IT_BOOL; + cins->mConst.mIntConst = 0; + cins->mNumOperands = 0; + } + } + } + } + if (!hasCall) { // Check forwarding globals @@ -17142,7 +17179,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "bv"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 4593fa3..d34f7c3 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -4997,7 +4997,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 1 +#if 0 if (proc->mIdent && !strcmp(proc->mIdent->mString, "main")) exp->Dump(0); #endif diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 5089016..9fabfb9 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1201,9 +1201,15 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) adec->mParams = apdec; if (adec->mBase->IsReference()) - apdec->mBase = atdec->BuildReference(adec->mLocation); + { + if (adec->mBase->mBase->mFlags & DTF_CONST) + apdec->mBase = atdec->ToConstType()->BuildReference(adec->mLocation); + else + apdec->mBase = atdec->BuildReference(adec->mLocation); + } else apdec->mBase = atdec; + atdec = atdec->mNext; apdec->mFlags = DTF_DEFINED; apdec->mVarIndex = vi; @@ -3616,7 +3622,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else if (mScanner->mToken == TK_CONSTEXPR) { - storageFlags |= DTF_CONSTEXPR; + storageFlags |= DTF_CONSTEXPR | DTF_REQUEST_INLINE; mScanner->NextToken(); } else if (mScanner->mToken == TK_EXTERN) @@ -7920,8 +7926,10 @@ Expression* Parser::ParseStatement(void) switch (mScanner->mToken) { case TK_IF: + { mScanner->NextToken(); - exp = new Expression(mScanner->mLocation, EX_IF); + bool constExp = ConsumeTokenIf(TK_CONSTEXPR); + exp = new Expression(mScanner->mLocation, EX_IF); exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration); exp->mRight = new Expression(mScanner->mLocation, EX_ELSE); exp->mRight->mLeft = ParseStatement(); @@ -7932,7 +7940,23 @@ Expression* Parser::ParseStatement(void) } else exp->mRight->mRight = nullptr; - break; + + if (constExp) + { + Expression * cexp = exp->mLeft->ConstantFold(mErrors, mDataSection); + if (cexp->mType == EX_CONSTANT && cexp->mDecValue->mType == DT_CONST_INTEGER) + { + if (cexp->mDecValue->mInteger) + exp = exp->mRight->mLeft; + else if (exp->mRight->mRight) + exp = exp->mRight->mRight; + else + exp = new Expression(mScanner->mLocation, EX_VOID); + } + else + mErrors->Error(exp->mLocation, EERR_INVALID_CONSTEXPR, "Condition is not constant"); + } + } break; case TK_WHILE: { mScanner->NextToken(); From f211eef83744477372cb1a1b842cac074eabaf4a Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 17 Sep 2023 20:34:42 +0200 Subject: [PATCH 122/169] Add fold expressions for argument packs --- include/opp/iostream.cpp | 6 + include/opp/iostream.h | 1 + oscar64/Declaration.cpp | 31 ++++- oscar64/Declaration.h | 6 +- oscar64/Errors.h | 1 + oscar64/Parser.cpp | 284 ++++++++++++++++++++++++++++++++++++++- oscar64/Parser.h | 6 + 7 files changed, 323 insertions(+), 12 deletions(-) diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp index b53d408..ed44e08 100644 --- a/include/opp/iostream.cpp +++ b/include/opp/iostream.cpp @@ -322,6 +322,12 @@ ostream & ostream::operator<<(bool val) return *this; } +ostream & ostream::operator<<(char val) +{ + bput(val); + return *this; +} + ostream & ostream::operator<<(int val) { if (val < 0) diff --git a/include/opp/iostream.h b/include/opp/iostream.h index 42c0e89..5548bef 100644 --- a/include/opp/iostream.h +++ b/include/opp/iostream.h @@ -91,6 +91,7 @@ public: ostream & write(const char * s, int n); ostream & operator<<(bool val); + ostream & operator<<(char val); ostream & operator<<(int val); ostream & operator<<(unsigned val); ostream & operator<<(long val); diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index bef5f0d..3358fc1 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -923,15 +923,30 @@ Declaration* Declaration::BuildConstPointer(const Location& loc) return pdec; } -Declaration* Declaration::BuildConstReference(const Location& loc) +Declaration* Declaration::BuildConstReference(const Location& loc, DecType type) { - Declaration* pdec = new Declaration(loc, DT_TYPE_REFERENCE); + Declaration* pdec = new Declaration(loc, type); pdec->mBase = this; pdec->mFlags = DTF_DEFINED | DTF_CONST; pdec->mSize = 2; return pdec; } +Declaration* Declaration::BuildArrayPointer(void) +{ + if (mType == DT_TYPE_ARRAY) + { + Declaration* pdec = new Declaration(mLocation, DT_TYPE_POINTER); + pdec->mBase = mBase; + pdec->mFlags = DTF_DEFINED; + pdec->mSize = 2; + pdec->mStride = mStride; + return pdec; + } + else + return this; +} + Declaration* Declaration::BuildPointer(const Location& loc) { Declaration* pdec = new Declaration(loc, DT_TYPE_POINTER); @@ -941,9 +956,9 @@ Declaration* Declaration::BuildPointer(const Location& loc) return pdec; } -Declaration* Declaration::BuildReference(const Location& loc) +Declaration* Declaration::BuildReference(const Location& loc, DecType type) { - Declaration* pdec = new Declaration(loc, DT_TYPE_REFERENCE); + Declaration* pdec = new Declaration(loc, type); pdec->mBase = this; pdec->mFlags = DTF_DEFINED; pdec->mSize = 2; @@ -987,7 +1002,7 @@ Declaration* Declaration::DeduceAuto(Declaration * dec) dec = dec->ToMutableType(); if (IsReference()) - dec = dec->BuildReference(mLocation); + dec = dec->BuildReference(mLocation, mType); return dec; } @@ -2167,6 +2182,12 @@ bool Declaration::IsReference(void) const return mType == DT_TYPE_REFERENCE || mType == DT_TYPE_RVALUEREF; } +bool Declaration::IsIndexed(void) const +{ + return mType == DT_TYPE_ARRAY || mType == DT_TYPE_POINTER; +} + + bool Declaration::IsSimpleType(void) const { return mType == DT_TYPE_INTEGER || mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_ENUM || mType == DT_TYPE_POINTER; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 757e75e..05be0ae 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -299,6 +299,7 @@ public: bool IsNumericType(void) const; bool IsSimpleType(void) const; bool IsReference(void) const; + bool IsIndexed(void) const; void SetDefined(void); @@ -311,12 +312,13 @@ public: Declaration* Last(void); Declaration* BuildPointer(const Location& loc); - Declaration* BuildReference(const Location& loc); + Declaration* BuildReference(const Location& loc, DecType type = DT_TYPE_REFERENCE); Declaration* BuildConstPointer(const Location& loc); - Declaration* BuildConstReference(const Location& loc); + Declaration* BuildConstReference(const Location& loc, DecType type = DT_TYPE_REFERENCE); Declaration* BuildRValueRef(const Location& loc); Declaration* BuildConstRValueRef(const Location& loc); Declaration* NonRefBase(void); + Declaration* BuildArrayPointer(void); Declaration* DeduceAuto(Declaration* dec); bool IsAuto(void) const; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 7505713..f26cefd 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -86,6 +86,7 @@ enum ErrorID EERR_INVALID_BITFIELD, EERR_INVALID_CAPTURE, EERR_INVALID_PACK_USAGE, + EERR_INVALID_FOLD_EXPRESSION, EERR_INVALID_CONSTEXPR, EERR_DOUBLE_FREE, diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 9fabfb9..8f66d00 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1203,9 +1203,9 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) if (adec->mBase->IsReference()) { if (adec->mBase->mBase->mFlags & DTF_CONST) - apdec->mBase = atdec->ToConstType()->BuildReference(adec->mLocation); + apdec->mBase = atdec->ToConstType()->BuildReference(adec->mLocation, adec->mBase->mType); else - apdec->mBase = atdec->BuildReference(adec->mLocation); + apdec->mBase = atdec->BuildReference(adec->mLocation, adec->mBase->mType); } else apdec->mBase = atdec; @@ -5009,7 +5009,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) case TK_CHARACTER: dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); dec->mInteger = mCharMap[(unsigned char)mScanner->mTokenInteger]; - dec->mBase = TheUnsignedIntTypeDeclaration; + dec->mBase = TheUnsignedCharTypeDeclaration; exp = new Expression(mScanner->mLocation, EX_CONSTANT); exp->mDecValue = dec; exp->mDecType = dec->mBase; @@ -5382,7 +5382,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) case TK_OPEN_PARENTHESIS: mScanner->NextToken(); - exp = ParseExpression(true); + exp = ParseListExpression(true); if (mScanner->mToken == TK_CLOSE_PARENTHESIS) mScanner->NextToken(); else @@ -6099,6 +6099,9 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) { if (exp->mType == EX_CALL && exp->mLeft->mDecValue) { + if (exp->mRight && FindPackExpression(exp->mRight)) + return exp; + Declaration* fdec = exp->mLeft->mDecValue; Declaration* fdec2 = exp2 ? exp2->mLeft->mDecValue : nullptr; @@ -6928,6 +6931,10 @@ Expression* Parser::ParseMulExpression(bool lhs) nexp->mToken = mScanner->mToken; nexp->mLeft = exp; mScanner->NextToken(); + + if (ConsumeTokenIf(TK_ELLIPSIS)) + return ParseBinaryFoldExpression(nexp); + nexp->mRight = ParsePrefixExpression(false); if (nexp->mLeft->mDecType->mType == DT_TYPE_FLOAT || nexp->mRight->mDecType->mType == DT_TYPE_FLOAT) @@ -6943,6 +6950,192 @@ Expression* Parser::ParseMulExpression(bool lhs) return exp; } +Expression* Parser::FindPackExpression(Expression* exp) +{ + if (exp->mType == EX_PACK) + return exp; + + if (exp->mLeft) + { + Expression* nexp = FindPackExpression(exp->mLeft); + if (nexp) + return nexp; + } + + if (exp->mRight) + { + Expression* nexp = FindPackExpression(exp->mRight); + if (nexp) + return nexp; + } + + return nullptr; +} + +Expression* Parser::ExpandPackExpression(Expression* exp, Expression* pack, Expression* item) +{ + if (exp == pack) + return item; + + Expression* left = exp->mLeft ? ExpandPackExpression(exp->mLeft, pack, item) : nullptr; + Expression* right = exp->mRight ? ExpandPackExpression(exp->mRight, pack, item) : nullptr; + + if (left == exp->mLeft && right == exp->mRight) + return exp; + + Expression* nexp = new Expression(exp->mLocation, exp->mType); + nexp->mToken = exp->mToken; + nexp->mLeft = left; + nexp->mRight = right; + nexp->mDecValue = exp->mDecValue; + nexp->mDecType = exp->mDecType; + + if (nexp->mType == EX_CALL) + nexp = ResolveOverloadCall(nexp); + + return nexp; +} + +Declaration* Parser::OperatorResultType(Expression* exp) +{ + if (exp->mType == EX_BINARY) + { + Declaration* lt = exp->mLeft->mDecType->NonRefBase(); + Declaration* rt = exp->mRight->mDecType->NonRefBase(); + + switch (exp->mToken) + { + case TK_MUL: + case TK_DIV: + case TK_MOD: + if (lt->mType == DT_TYPE_FLOAT || rt->mType == DT_TYPE_FLOAT) + return TheFloatTypeDeclaration; + else + return lt; + + case TK_ADD: + case TK_SUB: + if (lt->IsIndexed() && rt->IsIntegerType()) + return lt->BuildArrayPointer(); + else if (rt->IsIndexed() && lt->IsIntegerType()) + return rt->BuildArrayPointer(); + else if (lt->mType == DT_TYPE_FLOAT || rt->mType == DT_TYPE_FLOAT) + return TheFloatTypeDeclaration; + else if (lt->IsIndexed() && rt->IsIndexed()) + return TheSignedIntTypeDeclaration; + else + return lt; + + case TK_LEFT_SHIFT: + case TK_RIGHT_SHIFT: + case TK_BINARY_AND: + case TK_BINARY_OR: + case TK_BINARY_XOR: + return lt; + } + } + else if (exp->mType == EX_RELATIONAL || exp->mType == EX_LOGICAL_AND || exp->mType == EX_LOGICAL_OR || exp->mType == EX_LOGICAL_NOT) + return TheBoolTypeDeclaration; + else if (exp->mType == EX_LIST) + return exp->mRight->mDecType; + + return exp->mLeft->mDecType; +} + +Expression* Parser::ParseBinaryFoldExpression(Expression * exp) +{ + if (ConsumeTokenIf(exp->mToken)) + exp->mRight = ParsePrefixExpression(false); + + if (exp->mLeft) + { + Expression* pexp = FindPackExpression(exp->mLeft); + if (pexp) + { + Declaration* dpack = pexp->mDecValue->mParams; + Expression* nexp = exp->mRight; + if (dpack) + { + dpack = dpack->Last(); + if (!nexp) + { + Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE); + vexp->mDecType = dpack->mBase; + vexp->mDecValue = dpack; + nexp = ExpandPackExpression(exp->mLeft, pexp, vexp); + dpack = dpack->mPrev; + } + + while (dpack) + { + Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE); + vexp->mDecType = dpack->mBase; + vexp->mDecValue = dpack; + + Expression* oexp = new Expression(exp->mLocation, exp->mType); + oexp->mToken = exp->mToken; + oexp->mLeft = ExpandPackExpression(exp->mLeft, pexp, vexp); + oexp->mRight = nexp; + oexp->mDecType = OperatorResultType(oexp); + + nexp = CheckOperatorOverload(oexp); + + nexp = nexp->ConstantFold(mErrors, mDataSection); + + dpack = dpack->mPrev; + } + } + + return nexp; + } + } + + if (exp->mRight) + { + Expression* pexp = FindPackExpression(exp->mRight); + if (pexp) + { + Declaration* dpack = pexp->mDecValue->mParams; + Expression* nexp = exp->mLeft; + if (dpack) + { + if (!nexp) + { + Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE); + vexp->mDecType = dpack->mBase; + vexp->mDecValue = dpack; + nexp = ExpandPackExpression(exp->mRight, pexp, vexp); + dpack = dpack->mNext; + } + + while (dpack) + { + Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE); + vexp->mDecType = dpack->mBase; + vexp->mDecValue = dpack; + + Expression* oexp = new Expression(exp->mLocation, exp->mType); + oexp->mToken = exp->mToken; + oexp->mLeft = nexp; + oexp->mRight = ExpandPackExpression(exp->mRight, pexp, vexp); + oexp->mDecType = OperatorResultType(oexp); + + nexp = CheckOperatorOverload(oexp); + + nexp = nexp->ConstantFold(mErrors, mDataSection); + + dpack = dpack->mNext; + } + } + + return nexp; + } + } + + mErrors->Error(exp->mLocation, EERR_INVALID_FOLD_EXPRESSION, "No parameter pack"); + return exp; +} + Expression* Parser::ParseAddExpression(bool lhs) { Expression* exp = ParseMulExpression(lhs); @@ -6953,6 +7146,10 @@ Expression* Parser::ParseAddExpression(bool lhs) nexp->mToken = mScanner->mToken; nexp->mLeft = exp; mScanner->NextToken(); + + if (ConsumeTokenIf(TK_ELLIPSIS)) + return ParseBinaryFoldExpression(nexp); + nexp->mRight = ParseMulExpression(false); if (nexp->mLeft->mDecType->mType == DT_TYPE_POINTER && nexp->mRight->mDecType->IsIntegerType()) nexp->mDecType = nexp->mLeft->mDecType; @@ -7001,6 +7198,10 @@ Expression* Parser::ParseShiftExpression(bool lhs) nexp->mToken = mScanner->mToken; nexp->mLeft = exp; mScanner->NextToken(); + + if (ConsumeTokenIf(TK_ELLIPSIS)) + return ParseBinaryFoldExpression(nexp); + nexp->mRight = ParseAddExpression(false); nexp->mDecType = exp->mDecType; @@ -7022,6 +7223,10 @@ Expression* Parser::ParseRelationalExpression(bool lhs) nexp->mToken = mScanner->mToken; nexp->mLeft = exp; mScanner->NextToken(); + + if (ConsumeTokenIf(TK_ELLIPSIS)) + return ParseBinaryFoldExpression(nexp); + nexp->mRight = ParseShiftExpression(false); nexp->mDecType = TheBoolTypeDeclaration; @@ -7064,6 +7269,10 @@ Expression* Parser::ParseBinaryXorExpression(bool lhs) nexp->mToken = mScanner->mToken; nexp->mLeft = exp; mScanner->NextToken(); + + if (ConsumeTokenIf(TK_ELLIPSIS)) + return ParseBinaryFoldExpression(nexp); + nexp->mRight = ParseBinaryAndExpression(false); nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(mErrors, mDataSection); @@ -7084,6 +7293,10 @@ Expression* Parser::ParseBinaryOrExpression(bool lhs) nexp->mToken = mScanner->mToken; nexp->mLeft = exp; mScanner->NextToken(); + + if (ConsumeTokenIf(TK_ELLIPSIS)) + return ParseBinaryFoldExpression(nexp); + nexp->mRight = ParseBinaryXorExpression(false); nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(mErrors, mDataSection); @@ -7104,6 +7317,10 @@ Expression* Parser::ParseLogicAndExpression(bool lhs) nexp->mToken = mScanner->mToken; nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration); mScanner->NextToken(); + + if (ConsumeTokenIf(TK_ELLIPSIS)) + return ParseBinaryFoldExpression(nexp); + nexp->mRight = CoerceExpression(ParseBinaryOrExpression(false), TheBoolTypeDeclaration); nexp->mDecType = TheBoolTypeDeclaration; exp = nexp->ConstantFold(mErrors, mDataSection); @@ -7122,6 +7339,10 @@ Expression* Parser::ParseLogicOrExpression(bool lhs) nexp->mToken = mScanner->mToken; nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration); mScanner->NextToken(); + + if (ConsumeTokenIf(TK_ELLIPSIS)) + return ParseBinaryFoldExpression(nexp); + nexp->mRight = CoerceExpression(ParseLogicAndExpression(false), TheBoolTypeDeclaration); nexp->mDecType = TheBoolTypeDeclaration; exp = nexp->ConstantFold(mErrors, mDataSection); @@ -7748,6 +7969,55 @@ Expression* Parser::ExpandArgumentPack(Expression* exp, Declaration* dec) Expression* Parser::ParseListExpression(bool lhs) { + if (ConsumeTokenIf(TK_ELLIPSIS)) + { + ExpressionType et = EX_ERROR; + switch (mScanner->mToken) + { + case TK_MUL: + case TK_DIV: + case TK_MOD: + case TK_ADD: + case TK_SUB: + case TK_LEFT_SHIFT: + case TK_RIGHT_SHIFT: + case TK_BINARY_AND: + case TK_BINARY_OR: + case TK_BINARY_XOR: + et = EX_BINARY; + break; + case TK_EQUAL: + case TK_NOT_EQUAL: + case TK_GREATER_THAN: + case TK_GREATER_EQUAL: + case TK_LESS_THAN: + case TK_LESS_EQUAL: + et = EX_RELATIONAL; + break; + case TK_LOGICAL_AND: + et = EX_LOGICAL_AND; + break; + case TK_LOGICAL_OR: + et = EX_LOGICAL_OR; + break; + case TK_LOGICAL_NOT: + et = EX_LOGICAL_NOT; + break; + case TK_COMMA: + et = EX_LIST; + break; + } + + if (et == EX_ERROR) + mErrors->Error(mScanner->mLocation, EERR_INVALID_FOLD_EXPRESSION, "Invalid operator in fold expression"); + + Expression* nexp = new Expression(mScanner->mLocation, et); + nexp->mToken = mScanner->mToken; + mScanner->NextToken(); + nexp->mRight = ParseExpression(false); + return ParseBinaryFoldExpression(nexp); + } + Expression* exp = ParseExpression(lhs); if (exp->mType == EX_PACK) { @@ -7765,6 +8035,10 @@ Expression* Parser::ParseListExpression(bool lhs) Expression* nexp = new Expression(mScanner->mLocation, EX_LIST); nexp->mToken = TK_COMMA; nexp->mLeft = exp; + + if (ConsumeTokenIf(TK_ELLIPSIS)) + return ParseBinaryFoldExpression(nexp); + nexp->mRight = ParseListExpression(false); exp = nexp; } @@ -9213,7 +9487,7 @@ Expression* Parser::ParseAssemblerBaseOperand(Declaration* pcasm, int pcoffset) case TK_CHARACTER: dec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); dec->mInteger = mCharMap[(unsigned char)mScanner->mTokenInteger]; - dec->mBase = TheUnsignedIntTypeDeclaration; + dec->mBase = TheUnsignedCharTypeDeclaration; exp = new Expression(mScanner->mLocation, EX_CONSTANT); exp->mDecValue = dec; exp->mDecType = dec->mBase; diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 7e56ab5..b0f5e9e 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -114,6 +114,12 @@ protected: Expression* ParseNewOperator(void); Expression* ParseLambdaExpression(void); + + Declaration* OperatorResultType(Expression* exp); + + Expression* FindPackExpression(Expression* exp); + Expression* ExpandPackExpression(Expression* exp, Expression* pack, Expression* item); + Expression* ParseBinaryFoldExpression(Expression * exp); Expression* ParseSimpleExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs); From e20c098ab10f5012c4c67f31a672f255bfbc425f Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 18 Sep 2023 07:41:49 +0200 Subject: [PATCH 123/169] Fix samples build error --- oscar64/InterCode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 9c008a9..9ee5698 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4502,7 +4502,7 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc) if (mConst.mMemory == IM_LOCAL) { - if (!proc->mLocalVars[mConst.mVarIndex]) + if (mConst.mVarIndex < 0 || !proc->mLocalVars[mConst.mVarIndex]) vname = "null"; else if (!proc->mLocalVars[mConst.mVarIndex]->mIdent) vname = ""; @@ -4511,7 +4511,7 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc) } else if (mConst.mMemory == IM_PROCEDURE) { - if (proc->mModule->mProcedures[mConst.mVarIndex]) + if (mConst.mVarIndex >= 0 && proc->mModule->mProcedures[mConst.mVarIndex]) vname = proc->mModule->mProcedures[mConst.mVarIndex]->mIdent->mString; else if (mConst.mLinkerObject && mConst.mLinkerObject->mIdent) vname = mConst.mLinkerObject->mIdent->mString; From a0409002b6696dd4b556befb902532165c569037 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:19:56 +0200 Subject: [PATCH 124/169] Fix pointers in constexpr --- autotest/autotest.bat | 3 + autotest/opp_pairtest.cpp | 28 + include/opp/move.h | 14 - include/opp/utility.h | 34 ++ include/opp/vector.h | 2 +- oscar64/Constexpr.cpp | 142 ++++- oscar64/Constexpr.h | 3 +- oscar64/Declaration.cpp | 76 ++- oscar64/Declaration.h | 4 +- oscar64/GlobalAnalyzer.cpp | 11 +- oscar64/InterCode.cpp | 53 +- oscar64/InterCodeGenerator.cpp | 63 ++- oscar64/Parser.cpp | 985 +++++++++++++++++++++++++-------- oscar64/Parser.h | 2 + oscar64/Scanner.cpp | 94 ++++ oscar64/Scanner.h | 8 + 16 files changed, 1216 insertions(+), 306 deletions(-) create mode 100644 autotest/opp_pairtest.cpp delete mode 100644 include/opp/move.h create mode 100644 include/opp/utility.h diff --git a/autotest/autotest.bat b/autotest/autotest.bat index b5ed668..a5eaf07 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -18,6 +18,9 @@ rem @echo off @call :test opp_streamtest.cpp @if %errorlevel% neq 0 goto :error +@call :test opp_pairtest.cpp +@if %errorlevel% neq 0 goto :error + @call :test operatoroverload.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/opp_pairtest.cpp b/autotest/opp_pairtest.cpp new file mode 100644 index 0000000..7a1113c --- /dev/null +++ b/autotest/opp_pairtest.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +using namespace opp; + +int main(void) +{ + vector > 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; +} diff --git a/include/opp/move.h b/include/opp/move.h deleted file mode 100644 index 977fb64..0000000 --- a/include/opp/move.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef OPP_MOVE_H -#define OPP_MOVE_H - -namespace opp { - -template -T && move(T & m) -{ - return (T &&)m; -} - -} - -#endif diff --git a/include/opp/utility.h b/include/opp/utility.h new file mode 100644 index 0000000..b09c0aa --- /dev/null +++ b/include/opp/utility.h @@ -0,0 +1,34 @@ +#ifndef OPP_UTILITY_H +#define OPP_UTILITY_H + +namespace opp { + +template +T && move(T & m) +{ + return (T &&)m; +} + + +template +struct pair +{ + T1 first; + T2 second; + + pair(T1 && t1, T2 && t2) + : first(t1), second(t2) + {} +}; + +template +constexpr pair make_pair(T1 && t1, T2 && t2) +{ + return pair(t1, t2); +} + +} + + + +#endif diff --git a/include/opp/vector.h b/include/opp/vector.h index d28d51e..f1fa8dd 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -2,7 +2,7 @@ #define OPP_VECTOR_H #include -#include +#include namespace opp { diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index 3d36080..97efbfa 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -37,6 +37,7 @@ void ConstexprInterpreter::Value::PutConst(int offset, Declaration* dec) switch (dec->mType) { case DT_CONST_INTEGER: + case DT_CONST_ADDRESS: PutIntAt(dec->mInteger, offset, dec->mBase); break; 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) PutConst(pdec->mOffset, pdec); 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) - : mLocation(value->mLocation), +ConstexprInterpreter::Value::Value(const Location& location, Value* value, Declaration* type, int offset) + : mLocation(location), mDecType(type), mBaseValue(value), mOffset(offset), mDataSize(0), mData(mShortData) @@ -331,7 +336,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Value::GetPtrAt(int at, Declar { 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) @@ -448,19 +453,27 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type dec->mSize = type->mSize; dec->mSection = dataSection; dec->mOffset = offset; + Declaration* ldec = nullptr; - for (Declaration* mdec = type->mParams; mdec; mdec = mdec->mNext) + while (type) { - Declaration * cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection); - cdec->mOffset = mdec->mOffset; + 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; + if (ldec) + ldec->mNext = cdec; + else + dec->mParams = cdec; + + ldec = cdec; + } + + if (type->mBase) + type = type->mBase->mBase; else - dec->mParams = cdec; - - ldec = cdec; - + type = nullptr; } break; } @@ -486,6 +499,46 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type } 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) { - + for (int i = 0; i < mTemps.Size(); i++) + delete mTemps[i]; } 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; 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) { if (dec) pos = dec->mVarIndex; 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)) { mParams[pos] = Value(pex->mLeft->mLocation, pex->mLeft->mDecValue->mBase); @@ -566,7 +637,17 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp) pos = dec->mVarIndex; 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)) { 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]); } } + 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 { switch (exp->mToken) @@ -880,6 +967,13 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons Declaration* dec = exp->mLeft->mDecType->mParams; 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) { if (dec) @@ -1096,7 +1190,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) { Value v = Eval(exp->mLeft); 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: @@ -1107,15 +1201,26 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) if (v.mDecType->mType == DT_TYPE_ARRAY) { 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) { 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: return Value(exp->mLocation); @@ -1162,6 +1267,7 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) case EX_PREINCDEC: case EX_QUALIFY: case EX_INDEX: + case EX_RESULT: Eval(exp); return FLOW_NEXT; diff --git a/oscar64/Constexpr.h b/oscar64/Constexpr.h index 88f24e8..8a0df57 100644 --- a/oscar64/Constexpr.h +++ b/oscar64/Constexpr.h @@ -29,7 +29,7 @@ protected: Value(const Location& location, Declaration* dec, int count); Value(const 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(const Location& location, const uint8 * data, Declaration* type); Value(const Location& location, const ValueItem* data, Declaration* type); @@ -101,6 +101,7 @@ protected: GrowingArray mParams, mLocals; ExpandingArray mDestructStack; ExpandingArray * mHeap; + ExpandingArray mTemps; Errors * mErrors; Value mResult; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 3358fc1..3d5facf 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -303,6 +303,9 @@ void Expression::Dump(int ident) const case EX_PACK: printf("PACK"); break; + case EX_PACK_TYPE: + printf("PACK_TYPE"); + break; } printf("\n"); @@ -355,6 +358,16 @@ bool Expression::IsRValue(void) const 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 { if (mDecType->mFlags & DTF_CONST) @@ -996,7 +1009,7 @@ Declaration* Declaration::DeduceAuto(Declaration * dec) if (dec->mType == DT_TYPE_ARRAY) dec = dec->mBase->BuildPointer(mLocation); - if (mFlags & DTF_CONST) + if ((IsReference() ? mBase->mFlags : mFlags) & DTF_CONST) dec = dec->ToConstType(); else dec = dec->ToMutableType(); @@ -1133,7 +1146,7 @@ const Ident* Declaration::MangleIdent(void) } else if (mType == DT_PACK_TYPE) { - Declaration* dec = mBase; + Declaration* dec = mParams; while (dec) { const Ident* id = dec->MangleIdent(); @@ -1288,7 +1301,7 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) tpdec->mIdent = pdec->mBase->mBase->mIdent; else tpdec->mIdent = pdec->mBase->mIdent; - tpdec->mBase = phead; + tpdec->mParams = phead; mScope->Insert(tpdec->mIdent, tpdec); } else @@ -1434,25 +1447,66 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) Declaration *ftdec = tdec->mTemplate; while (ftdec) { - if (ftdec->mBase->IsConstSame(fdec)) + if (ftdec->mBase->mQualIdent == fdec->mQualIdent) { Declaration* fpdec = ftdec->mParams; Declaration* tpdec = tdec->mTemplate->mParams; - while (fpdec) + while (fpdec && tpdec) { 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)) 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; tpdec = tpdec->mNext; } - return true; + return !fpdec && !tpdec; } ftdec = ftdec->mNext; @@ -1604,6 +1658,7 @@ Declaration* Declaration::ToConstType(void) ndec->mQualIdent = mQualIdent; ndec->mTemplate = mTemplate; + ndec->mDestructor = mDestructor; ndec->mDefaultConstructor = mDefaultConstructor; ndec->mCopyConstructor = mCopyConstructor; ndec->mMoveConstructor = mMoveConstructor; @@ -1636,6 +1691,7 @@ Declaration* Declaration::ToMutableType(void) ndec->mQualIdent = mQualIdent; ndec->mTemplate = mTemplate; + ndec->mDestructor = mDestructor; ndec->mDefaultConstructor = mDefaultConstructor; ndec->mCopyConstructor = mCopyConstructor; ndec->mMoveConstructor = mMoveConstructor; @@ -1659,6 +1715,8 @@ bool Declaration::IsSameTemplate(const Declaration* dec) const if (mType == DT_CONST_FUNCTION) return mBase->IsSame(dec->mBase); + else if (mType == DT_TYPE_STRUCT) + return true; return false; } @@ -1673,7 +1731,7 @@ bool Declaration::IsSubType(const Declaration* dec) const 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); } @@ -1906,7 +1964,7 @@ bool Declaration::IsSameParams(const Declaration* dec) const } 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) { if (!ld->IsSame(rd)) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 05be0ae..17bb110 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -222,7 +222,8 @@ enum ExpressionType EX_CONSTRUCT, EX_CLEANUP, EX_RESULT, - EX_PACK + EX_PACK, + EX_PACK_TYPE, }; class Expression @@ -247,6 +248,7 @@ public: bool IsSame(const Expression* exp) const; bool IsRValue(void) const; bool IsLValue(void) const; + bool IsConstRef(void) const; void Dump(int ident) const; }; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index ab171d0..1d50024 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -557,7 +557,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) while (pdec) { 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->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))) ldec->mBase->mFlags |= DTF_STACKCALL; + RegisterProc(Analyze(pex, procDec, pdec && pdec->mBase->IsReference())); + if (pdec) pdec = pdec->mNext; @@ -892,7 +894,6 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo else rex = nullptr; } - RegisterProc(Analyze(exp->mRight, procDec, false)); } break; case EX_LIST: @@ -901,7 +902,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo case EX_RETURN: 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->mMoveConstructor) @@ -1031,8 +1032,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo procDec->mComplexity += exp->mDecType->mSize * 10; ldec = Analyze(exp->mLeft, procDec, false); - RegisterProc(Analyze(exp->mRight->mLeft, procDec, false)); - RegisterProc(Analyze(exp->mRight->mRight, procDec, false)); + RegisterProc(Analyze(exp->mRight->mLeft, procDec, lhs)); + RegisterProc(Analyze(exp->mRight->mRight, procDec, lhs)); break; } diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 9ee5698..1599ca1 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -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) { 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) { requiredVars.Fill(); @@ -5241,12 +5285,11 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI break; 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].mType = ins->mDst.mType; ins->mSrc[i].mTemp = -1; } } @@ -16376,6 +16419,8 @@ void InterCodeProcedure::ResetVisited(void) int InterCodeProcedure::AddTemporary(InterType type) { + assert(type != IT_NONE); + int temp = mTemporaries.Size(); mTemporaries.Push(type); return temp; @@ -17179,7 +17224,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "bv"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index d34f7c3..39ca8ee 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -63,6 +63,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* ins->mSrc[0].mOperandSize = v.mReference == 1 ? v.mType->mSize : 2; 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) { ins->mDst.mRange.LimitMin(v.mType->mMinValue); @@ -1641,6 +1647,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* break; case EX_PACK: + case EX_PACK_TYPE: mErrors->Error(exp->mLocation, EERR_INVALID_PACK_USAGE, "Invalid pack usage"); 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 (!vl.mType->CanAssign(vr.mType)) + { + vl.mType->CanAssign(vr.mType); mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + } } 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); + if (vr.mType->IsReference()) + { + vr.mReference++; + vr.mType = vr.mType->mBase; + } + vr = Dereference(proc, exp, block, vr, 1); 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].mTemp = vr.mTemp; ins->mSrc[0].mMemory = IM_INDIRECT; @@ -3766,18 +3785,28 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { if (inlineMapper->mResultExp) { - ins->mSrc[1].mType = IT_POINTER; - ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp; - ins->mSrc[1].mMemory = IM_INDIRECT; - ins->mCode = IC_STORE; - ins->mSrc[1].mOperandSize = 2; - ins->mNumOperands = 2; + if (inlineMapper->mResultExp->mType->IsReference()) + { + ins->mSrc[1].mType = IT_POINTER; + ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + 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 { InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); 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.mOperandSize = procType->mBase->mSize; ains->mConst.mIntConst = 0; @@ -4007,7 +4036,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); 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.mOperandSize = procType->mBase->mSize; ains->mConst.mIntConst = 0; @@ -4148,14 +4177,24 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vc = Dereference(proc, exp, block, vc); - int ttemp; + int ttemp, tref = 0; InterType ttype, stypel, styper; stypel = InterTypeOf(vl.mType); styper = InterTypeOf(vr.mType); - Declaration* dtype; - if (stypel == IT_POINTER || styper == IT_POINTER) + Declaration* dtype = exp->mDecType; + + 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) vl = Dereference(proc, exp, block, vl, 1); @@ -4224,7 +4263,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* sins->mDst.mTemp = ttemp; block->Append(sins); - return ExValue(dtype, ttemp); + return ExValue(dtype, ttemp, tref); } else #endif diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 8f66d00..313b047 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -595,6 +595,16 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio AddDefaultConstructors(pthis); + if (pthis->mBase->mConst) + { + pthis->mBase->mConst->mDestructor = pthis->mBase->mDestructor; + pthis->mBase->mConst->mDefaultConstructor = pthis->mBase->mDefaultConstructor; + pthis->mBase->mConst->mCopyConstructor = pthis->mBase->mCopyConstructor; + pthis->mBase->mConst->mMoveConstructor = pthis->mBase->mMoveConstructor; + pthis->mBase->mConst->mVectorConstructor = pthis->mBase->mVectorConstructor; + pthis->mBase->mConst->mVectorCopyConstructor = pthis->mBase->mVectorCopyConstructor; + } + // Lookup constructors, have same name as class Declaration* cdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+"), SLEVEL_SCOPE); while (cdec) @@ -753,24 +763,26 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl case TK_IDENT: pident = mScanner->mTokenIdent; + mScanner->NextToken(); + if (mTemplateScope) - dec = mTemplateScope->Lookup(mScanner->mTokenIdent); + { + dec = mTemplateScope->Lookup(pident); + if (dec && mScanner->mToken == TK_LESS_THAN && !dec->mTemplate) + dec = nullptr; + } if (!dec) { - dec = mScope->Lookup(mScanner->mTokenIdent); + dec = mScope->Lookup(pident); if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS) - dec = mScope->mParent->Lookup(mScanner->mTokenIdent); - - mScanner->NextToken(); + dec = mScope->mParent->Lookup(pident); dec = ParseBaseTypeQualify(qualified, dec, pident); if (dec && dec->mTemplate) dec = ParseTemplateExpansion(dec->mTemplate, nullptr); } - else - mScanner->NextToken(); dec = ParseBaseTypeQualify(qualified, dec, pident); @@ -1191,7 +1203,7 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) atdec = atdec->mBase; if (atdec->mType == DT_PACK_TYPE) { - atdec = atdec->mBase; + atdec = atdec->mParams; Declaration* apdec = adec; while (atdec) @@ -1827,8 +1839,11 @@ Expression* Parser::BuildMemberInitializer(Expression* vexp) nexp->mDecType = vexp->mDecType; nexp->mLeft = vexp; ConsumeToken(TK_OPEN_PARENTHESIS); - nexp->mRight = ParseRExpression(); - ConsumeToken(TK_CLOSE_PARENTHESIS); + if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) + { + nexp->mRight = ParseRExpression(); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } return nexp; } @@ -2043,6 +2058,9 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc) scope->Insert(pdec->mIdent, pdec); pdec = pdec->mNext; } + if (cfunc->mBase->mParamPack) + mScope->Insert(cfunc->mBase->mParamPack->mIdent, cfunc->mBase->mParamPack); + Declaration* othis = mThisPointer; mThisPointer = pthis; @@ -2165,6 +2183,12 @@ void Parser::AddDefaultConstructors(Declaration* pthis) if (!(bcdec->mBase->mCopyConstructor->mBase->mFlags & DTF_REQUEST_INLINE)) inlineCopy = false; } + if (bcdec->mBase->mMoveConstructor) + { + simpleMove = false; + if (!(bcdec->mBase->mMoveConstructor->mBase->mFlags & DTF_REQUEST_INLINE)) + inlineCopy = false; + } if (bcdec->mBase->mCopyAssignment) simpleAssignment = false; bcdec = bcdec->mNext; @@ -2202,6 +2226,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis) simpleCopy = false; if (bdec->mCopyAssignment) simpleAssignment = false; + if (bdec->mMoveConstructor) + simpleMove = false; } if (dec->mValue) simpleConstructor = false; @@ -3242,16 +3268,18 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) // Returning a value object for pass by address // add a temporary variable - int nindex = mLocalIndex++; + //int nindex = mLocalIndex++; Declaration* rtdec = exp->mLeft->mDecType; + Declaration* vdec = AllocTempVar(rtdec); +#if 0 Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); vdec->mVarIndex = nindex; vdec->mBase = rtdec; vdec->mSize = rtdec->mSize; - +#endif Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE); vexp->mDecType = rtdec; vexp->mDecValue = vdec; @@ -3293,16 +3321,18 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) // Returning a value object for pass by address // add a temporary variable - int nindex = mLocalIndex++; +// int nindex = mLocalIndex++; Declaration* rtdec = exp->mLeft->mDecType; + Declaration* vdec = AllocTempVar(rtdec); +#if 0 Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); vdec->mVarIndex = nindex; vdec->mBase = rtdec; vdec->mSize = rtdec->mSize; - +#endif Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE); vexp->mDecType = rtdec; vexp->mDecValue = vdec; @@ -3361,16 +3391,18 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) // Returning a value object for pass as reference // add a temporary variable + Declaration* vdec = AllocTempVar(pex->mDecType); +#if 0 int nindex = mLocalIndex++; Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); vdec->mVarIndex = nindex; - vdec->mBase = pdec->mBase->mBase; - vdec->mSize = pdec->mBase->mBase->mSize; - + vdec->mBase = pex->mDecType; + vdec->mSize = pex->mDecType->mSize; +#endif Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE); - vexp->mDecType = pdec->mBase->mBase; + vexp->mDecType = pex->mDecType; vexp->mDecValue = vdec; Expression* cexp = new Expression(pex->mLocation, pex->mType); @@ -3450,6 +3482,28 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) pex->mDecType = vdec->mBase; } } + else if ((pdec->mBase->mType == DT_TYPE_REFERENCE && !pex->IsConstRef()) || (pdec->mBase->mType == DT_TYPE_RVALUEREF && !pex->IsLValue())) + { + Declaration* vdec = AllocTempVar(pex->mDecType); + + Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE); + vexp->mDecType = pex->mDecType; + vexp->mDecValue = vdec; + + Expression* cexp = new Expression(pex->mLocation, pex->mType); + cexp->mDecType = pex->mDecType; + cexp->mDecValue = pex->mDecValue; + cexp->mLeft = pex->mLeft; + cexp->mRight = pex->mRight; + cexp->mToken = pex->mToken; + + pex->mType = EX_INITIALIZATION; + pex->mToken = TK_ASSIGN; + pex->mLeft = vexp; + pex->mRight = cexp; + pex->mDecValue = nullptr; + pex->mDecType = vdec->mBase; + } pdec = pdec->mNext; } @@ -3753,7 +3807,15 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ctdec->mParams) mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Cast operators can't have parameter"); - PrependThisArgument(ctdec, pthis); + Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + bthis->mFlags |= DTF_CONST | DTF_DEFINED; + if (ConsumeTokenIf(TK_CONST)) + bthis->mBase = pthis->mBase->ToConstType(); + else + bthis->mBase = pthis->mBase; + bthis->mSize = 2; + + PrependThisArgument(ctdec, bthis); Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); cdec->mBase = ctdec; @@ -4995,6 +5057,21 @@ Expression* Parser::ParseSimpleExpression(bool lhs) } break; case TK_CONST: + if (lhs) + exp = ParseDeclarationExpression(nullptr); + else + { + mScanner->NextToken(); + exp = new Expression(mScanner->mLocation, EX_TYPE); + exp->mDecValue = nullptr; + exp->mDecType = ParseBaseTypeDeclaration(DTF_CONST, true); + while (ConsumeTokenIf(TK_MUL)) + exp->mDecType = exp->mDecType->BuildPointer(mScanner->mLocation); + while (ConsumeTokenIf(TK_BINARY_AND)) + exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation); + } + break; + case TK_VOLATILE: case TK_STRUCT: case TK_CLASS: @@ -5314,6 +5391,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp->mDecValue = dec; exp->mDecType = dec->mBase; } + else if (dec->mType == DT_PACK_TYPE) + { + exp = new Expression(mScanner->mLocation, EX_PACK_TYPE); + exp->mDecValue = nullptr; + exp->mDecType = dec; + } else if (dec->mType <= DT_TYPE_FUNCTION) { if (lhs) @@ -5335,6 +5418,11 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp->mDecValue = dec; exp->mDecType = TheSignedIntTypeDeclaration; } + else if (dec->mType == DT_PACK_TEMPLATE) + { + exp = new Expression(mScanner->mLocation, EX_PACK_TYPE); + exp->mDecType = dec; + } else if (dec->mType == DT_ELEMENT) { mErrors->Error(mScanner->mLocation, EERR_NON_STATIC_MEMBER, "Non static member access", mScanner->mTokenIdent); @@ -5411,6 +5499,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; nexp->mLeft = ParsePrefixExpression(false); + nexp = CheckOperatorOverload(nexp); exp = nexp->ConstantFold(mErrors, mDataSection); } } @@ -5514,6 +5603,7 @@ Expression* Parser::ParseQualify(Expression* exp) uint64 mflags = 0; Declaration* mdec = nullptr; const Ident* ident = nullptr; + bool destructor = false; if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_BINARY_NOT) { @@ -5529,6 +5619,7 @@ Expression* Parser::ParseQualify(Expression* exp) } ident = ident->PreMangle("~"); + destructor = true; } else mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); @@ -5628,6 +5719,12 @@ Expression* Parser::ParseQualify(Expression* exp) exp = nexp; } } + else if (destructor) + { + mScanner->NextToken(); + ConsumeToken(TK_OPEN_PARENTHESIS); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } else { mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not found", mScanner->mTokenIdent); @@ -5808,23 +5905,30 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) else return NOOVERLOAD; - int ncast = 0; - Declaration* ext = ex->mDecType; - while (ext && !ext->IsConstSame(ptype->mBase)) + if (ptype->mBase->mTemplate) { - ncast++; - ext = ext->mBase; - } - - if (ext) - { - if ((etype->mFlags & DTF_CONST) && !(ptype->mBase->mFlags & DTF_CONST)) - return NOOVERLOAD; - - dist += 32 * ncast; + dist += 16; } else - return NOOVERLOAD; + { + int ncast = 0; + Declaration* ext = ex->mDecType; + while (ext && !ext->IsConstSame(ptype->mBase)) + { + ncast++; + ext = ext->mBase; + } + + if (ext) + { + if ((etype->mFlags & DTF_CONST) && !(ptype->mBase->mFlags & DTF_CONST)) + return NOOVERLOAD; + + dist += 32 * ncast; + } + else + return NOOVERLOAD; + } } else if (ptype->mType == DT_TYPE_POINTER && (etype->mType == DT_TYPE_ARRAY || etype->mType == DT_TYPE_POINTER) && ptype->mBase->IsSameMutable(etype->mBase)) dist += 2; @@ -5912,7 +6016,7 @@ bool Parser::CanCoerceExpression(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))) @@ -6148,7 +6252,12 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) if (ibest == NOOVERLOAD) { #if _DEBUG - int d = OverloadDistance(exp->mLeft->mDecValue, exp->mRight); + fdec = exp->mLeft->mDecValue; + while (fdec) + { + int d = OverloadDistance(exp->mLeft->mDecValue, exp->mRight); + fdec = fdec->mNext; + } #endif mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call", exp->mLeft->mDecValue->mQualIdent); } @@ -6301,6 +6410,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; nexp->mLeft = pexp; + nexp = CheckOperatorOverload(nexp); exp = nexp->ConstantFold(mErrors, mDataSection); } else @@ -6639,20 +6749,33 @@ Expression* Parser::ParseNewOperator(void) if (mScanner->mToken == TK_OPEN_PARENTHESIS || dec->mDefaultConstructor) { Declaration* mdec = dec->mDefaultConstructor; + Expression* pexp = nullptr; - bool plist = false; if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) { if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) { - plist = true; - if (dec->mType == DT_TYPE_STRUCT) - mdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+")); - else - mdec = nullptr; + pexp = ParseListExpression(false); + ConsumeToken(TK_CLOSE_PARENTHESIS); } } + if (dec->mType == DT_TYPE_STRUCT) + { + mdec = dec->mScope ? dec->mScope->Lookup(dec->mIdent->PreMangle("+")) : nullptr; + if (pexp && pexp->mType != EX_LIST) + { + if (pexp->mDecType->IsSame(dec)) + mdec = dec->mCopyConstructor; + else if (pexp->mDecType->mType == DT_TYPE_REFERENCE && pexp->mDecType->mBase->IsSame(dec)) + mdec = dec->mCopyConstructor; + else if (pexp->mDecType->mType == DT_TYPE_RVALUEREF && pexp->mDecType->mBase->IsSame(dec)) + mdec = dec->mMoveConstructor; + } + } + else + mdec = nullptr; + if (mdec) { Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); @@ -6670,19 +6793,10 @@ Expression* Parser::ParseNewOperator(void) iexp->mRight = nexp; iexp->mDecType = nexp->mDecType; - Expression* pexp = vexp; - - if (plist) - { - pexp = ParseListExpression(false); - - ConsumeToken(TK_CLOSE_PARENTHESIS); - - Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); - lexp->mLeft = vexp; - lexp->mRight = pexp; - pexp = lexp; - } + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = vexp; + lexp->mRight = pexp; + pexp = lexp; Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); cexp->mDecValue = mdec; @@ -6718,32 +6832,25 @@ Expression* Parser::ParseNewOperator(void) nexp->mRight = coexp; nexp->mDecType = coexp->mDecType; } - else if (plist && !mdec) + else if (pexp && pexp->mType != EX_LIST) { - Expression * pexp = ParseListExpression(false); - ConsumeToken(TK_CLOSE_PARENTHESIS); - - if (pexp && pexp->mType != EX_LIST) - { - Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX); - dexp->mToken = TK_MUL; - dexp->mLeft = nexp; - dexp->mDecType = nexp->mDecType->mBase; - - Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); - iexp->mToken = TK_ASSIGN; - iexp->mLeft = dexp; - iexp->mRight = pexp; - iexp->mDecType = nexp->mDecType; - - nexp = iexp; - } - else - mErrors->Error(mScanner->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor", dec->mIdent); + Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX); + dexp->mToken = TK_MUL; + dexp->mLeft = nexp; + dexp->mDecType = nexp->mDecType->mBase; + Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + iexp->mToken = TK_ASSIGN; + iexp->mLeft = dexp; + iexp->mRight = pexp; + iexp->mDecType = nexp->mDecType; + nexp = new Expression(mScanner->mLocation, EX_PREFIX); + nexp->mToken = TK_BINARY_AND; + nexp->mDecType = nexp->mDecType; + nexp->mLeft = iexp; } - else if (plist) + else if (pexp) { mErrors->Error(mScanner->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor", dec->mIdent); } @@ -7880,6 +7987,56 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) } } } + else if (exp->mType == EX_TYPECAST) + { + Declaration* tdec = exp->mLeft->mDecType; + if (exp->mLeft->mDecType) + { + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) + tdec = tdec->mBase; + + if (tdec->mType == DT_TYPE_STRUCT) + { + Declaration* mdec = tdec->mScope->Lookup(Ident::Unique("(cast)")); + while (mdec && !mdec->mBase->mBase->IsSame(exp->mDecType)) + mdec = mdec->mNext; + while (!mdec && tdec->mBase && tdec->mBase->mBase) + { + tdec = tdec->mBase->mBase; + mdec = tdec->mScope->Lookup(Ident::Unique("(cast)")); + while (mdec && !mdec->mBase->mBase->IsSame(exp->mDecType)) + mdec = mdec->mNext; + } + + if (mdec) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_CALL); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + nexp->mRight = exp->mRight; + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp->mLeft; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = tdec; + texp->mDecType->mSize = 2; + + nexp->mRight = texp->ConstantFold(mErrors, mDataSection); + + nexp = ResolveOverloadCall(nexp); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + + exp = nexp; + } + } + } + } else if (exp->mType == EX_LOGICAL_NOT) { const Ident* opident = Ident::Unique("operator!"); @@ -8133,6 +8290,30 @@ Expression* Parser::ParseFunction(Declaration * dec) return exp; } +void Parser::SkipStatement(void) +{ + if (ConsumeTokenIf(TK_OPEN_BRACE)) + { + int cnt = 1; + while (cnt > 0) + { + if (ConsumeTokenIf(TK_OPEN_BRACE)) + cnt++; + else if (ConsumeTokenIf(TK_CLOSE_BRACE)) + cnt--; + else + mScanner->NextToken(); + } + } + else + { + while (!ConsumeTokenIf(TK_SEMICOLON)) + { + mScanner->NextToken(); + } + } +} + Expression* Parser::ParseStatement(void) { Expression* exp = nullptr; @@ -8202,34 +8383,45 @@ Expression* Parser::ParseStatement(void) case TK_IF: { mScanner->NextToken(); - bool constExp = ConsumeTokenIf(TK_CONSTEXPR); - exp = new Expression(mScanner->mLocation, EX_IF); - exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration); - exp->mRight = new Expression(mScanner->mLocation, EX_ELSE); - exp->mRight->mLeft = ParseStatement(); - if (mScanner->mToken == TK_ELSE) + + if (ConsumeTokenIf(TK_CONSTEXPR)) { - mScanner->NextToken(); - exp->mRight->mRight = ParseStatement(); - } - else - exp->mRight->mRight = nullptr; - - if (constExp) - { - Expression * cexp = exp->mLeft->ConstantFold(mErrors, mDataSection); - if (cexp->mType == EX_CONSTANT && cexp->mDecValue->mType == DT_CONST_INTEGER) + exp = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration)->ConstantFold(mErrors, mDataSection); + if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) { - if (cexp->mDecValue->mInteger) - exp = exp->mRight->mLeft; - else if (exp->mRight->mRight) - exp = exp->mRight->mRight; + if (exp->mDecValue->mInteger) + { + exp = ParseStatement(); + if (ConsumeTokenIf(TK_ELSE)) + SkipStatement(); + } else - exp = new Expression(mScanner->mLocation, EX_VOID); + { + SkipStatement(); + if (ConsumeTokenIf(TK_ELSE)) + exp = ParseStatement(); + else + exp = new Expression(mScanner->mLocation, EX_VOID); + } } else mErrors->Error(exp->mLocation, EERR_INVALID_CONSTEXPR, "Condition is not constant"); } + else + { + exp = new Expression(mScanner->mLocation, EX_IF); + exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration); + exp->mRight = new Expression(mScanner->mLocation, EX_ELSE); + exp->mRight->mLeft = ParseStatement(); + if (mScanner->mToken == TK_ELSE) + { + mScanner->NextToken(); + exp->mRight->mRight = ParseStatement(); + } + else + exp->mRight->mRight = nullptr; + } + } break; case TK_WHILE: { @@ -8663,9 +8855,10 @@ Expression* Parser::ParseStatement(void) exp->mLeft = ParseRExpression(); if (mFunctionType && mFunctionType->mBase) { - if (mFunctionType->mBase->mType == DT_TYPE_AUTO) + if (mFunctionType->mBase->mType == DT_TYPE_AUTO || mFunctionType->mBase->IsReference() && mFunctionType->mBase->mBase->mType == DT_TYPE_AUTO) { - mFunctionType->mBase = exp->mLeft->mDecType; + mFunctionType->mBase = mFunctionType->mBase->DeduceAuto(exp->mLeft->mDecType); + ; if (mFunctionType->mBase->mType == DT_TYPE_STRUCT) { // Make room for value struct return @@ -8835,11 +9028,323 @@ Expression* Parser::ParseSwitchStatement(void) return sexp; } +int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec) +{ + Declaration* ptdec = tdec->mParams; + Declaration* psdec = spec->mParams; + + int cost = 0; + if (tdec->mParser) + cost = 100000; + + while (ptdec && psdec) + { + if (ptdec->mType == DT_CONST_TEMPLATE && psdec->mType == DT_CONST_TEMPLATE) + { + if (ptdec->mBase) + { + if (ptdec->mBase->mInteger != psdec->mBase->mInteger) + return NOOVERLOAD; + } + else + cost += 100; + } + else if (ptdec->mType == DT_TYPE_TEMPLATE && psdec->mType == DT_TYPE_TEMPLATE) + { + if (ptdec->mBase) + { + if (!ptdec->mBase->IsSame(psdec->mBase)) + return NOOVERLOAD; + } + else + cost += 100; + } + else if (ptdec->mType == DT_PACK_TEMPLATE && psdec->mType == DT_PACK_TEMPLATE) + { + if (ptdec->mBase) + { + + Declaration* tvp = ptdec->mBase->mParams; + Declaration* svp = psdec->mBase->mParams; + + while (tvp && svp && tvp->IsSame(svp)) + { + tvp = tvp->mNext; + svp = svp->mNext; + } + + if (tvp || svp) + return NOOVERLOAD; + } + else if (psdec->mBase) + { + Declaration* dec = psdec->mBase->mParams; + while (dec) + { + cost += 200; + dec = dec->mNext; + } + } + } + else if (ptdec->mType == DT_PACK_TEMPLATE) + { + if (ptdec->mBase) + { + ptdec = ptdec->mBase->mParams; + continue; + } + else + { + while (psdec) + { + cost += 200; + psdec = psdec->mNext; + } + + return cost; + } + } + else + return NOOVERLOAD; + + ptdec = ptdec->mNext; + psdec = psdec->mNext; + } + + if (ptdec && ptdec->mType == DT_PACK_TEMPLATE) + { + if (ptdec->mBase) + { + if (ptdec->mBase->mParams) + return NOOVERLOAD; + } + else + cost += 50; + } + else if (ptdec || psdec) + return NOOVERLOAD; + + return cost; +} + Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* expd) { Declaration * tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); +#if 1 + if (expd) + { + if (tmpld->mBase->mType == DT_TEMPLATE) + { + Parser* p = tmpld->mBase->mParser->Clone(); + + p->mScanner->Replay(tmpld->mBase->mTokens); + + tdec = tmpld->mBase->Clone(); + tdec->mScope->mName = expd->mScope->mName; + tdec->mScope->mParent = expd->mScope; + + p->ParseTemplateDeclarationBody(tdec, nullptr); + + return tdec; + } + + Declaration* ppdec = nullptr; + Declaration* dec = expd->mParams; + + while (dec) + { + Declaration* epdec = dec->Clone(); + + if (ppdec) + ppdec->mNext = epdec; + else + tdec->mParams = epdec; + ppdec = epdec; + + dec = dec->mNext; + } + } + else + { + ConsumeToken(TK_LESS_THAN); + + Declaration* ppdec = nullptr; + + if (!ConsumeTokenIf(TK_GREATER_THAN)) + { + do + { + Expression* exp = ParseShiftExpression(false); + Declaration* pdec = nullptr; + + if (exp->mType == EX_TYPE) + { + pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE); + pdec->mBase = exp->mDecType; + } + else if (exp->mType == EX_PACK_TYPE) + { + ConsumeToken(TK_ELLIPSIS); + + if (exp->mDecType->mType == DT_PACK_TYPE) + { + Declaration* ptdec = exp->mDecType->mParams; + while (ptdec) + { + pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE); + pdec->mBase = ptdec; + + if (pdec) + { + if (ppdec) + ppdec->mNext = pdec; + else + tdec->mParams = pdec; + ppdec = pdec; + } + + ptdec = ptdec->mNext; + } + continue; + } + else + { + pdec = new Declaration(exp->mLocation, DT_PACK_TEMPLATE); + pdec->mBase = exp->mDecType; + } + } + else if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_FUNCTION) + { + pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE); + pdec->mBase = exp->mDecValue; + } + else if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) + { + pdec = new Declaration(exp->mLocation, DT_CONST_TEMPLATE); + pdec->mBase = exp->mDecValue; + } + else + mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Template specification expected"); + + if (pdec) + { + if (ppdec) + ppdec->mNext = pdec; + else + tdec->mParams = pdec; + ppdec = pdec; + } + + } while (ConsumeTokenIf(TK_COMMA)); + + ConsumeToken(TK_GREATER_THAN); + } + } + + while (!tmpld->mTokens) + tmpld = tmpld->mNext; + + Declaration* epdec = tdec->mParams; + while (epdec && epdec->mBase && epdec->mBase->mType != DT_TYPE_TEMPLATE && epdec->mBase->mType != DT_CONST_TEMPLATE && epdec->mBase->mType != DT_PACK_TEMPLATE) + epdec = epdec->mNext; + + if (epdec) + { + // Partial template specification + Declaration* bdec = new Declaration(mScanner->mLocation, tmpld->mBase->mType); + tdec->mBase = bdec; + bdec->mTemplate = tdec; + bdec->mBase = tmpld->mBase->mBase; + tdec->mNext = tmpld; + bdec->mIdent = tdec->MangleIdent(); + + return bdec; + } + + Declaration* pthis = tmpld->mClass; + + int mindist = NOOVERLOAD; + Declaration* etdec = nullptr; + + Declaration* dec = tmpld; + while (dec) + { + int dist = ExpansionDistance(dec, tdec); + if (dist < mindist) + { + mindist = dist; + etdec = dec; + } + dec = dec->mNext; + } + + if (mindist == 0) + return etdec->mBase; + else if (mindist == NOOVERLOAD) + mErrors->Error(tdec->mLocation, EERR_TEMPLATE_PARAMS, "No matching template parameters"); + else + tmpld = etdec; + + dec = tdec->mParams; + Declaration * pdec = tmpld->mParams; + + Declaration * ppdec = nullptr; + while (pdec) + { + if (pdec->mType == DT_PACK_TEMPLATE) + { + if (!dec) + { + Declaration* packd = new Declaration(tdec->mLocation, DT_PACK_TEMPLATE); + packd->mBase = new Declaration(tdec->mLocation, DT_PACK_TYPE); + if (ppdec) + ppdec->mNext = packd; + else + tdec->mParams = packd; + dec = packd; + } + else if (dec->mType != DT_PACK_TEMPLATE) + { + Declaration* packd = new Declaration(dec->mLocation, DT_PACK_TEMPLATE); + packd->mBase = new Declaration(dec->mLocation, DT_PACK_TYPE); + if (ppdec) + ppdec->mNext = packd; + else + tdec->mParams = packd; + + ppdec = nullptr; + while (dec) + { + Declaration* ndec = dec->mBase->Clone(); + + if (ppdec) + ppdec->mNext = ndec; + else + packd->mBase->mParams = ndec; + ppdec = ndec; + dec = dec->mNext; + } + + dec = packd; + } + } + + if (dec) + { + dec->mIdent = pdec->mIdent; + tdec->mScope->Insert(dec->mIdent, dec->mBase); + + ppdec = dec; + dec = dec->mNext; + } + + pdec = pdec->mNext; + } + + +#else if (expd) { if (tmpld->mBase->mType == DT_TEMPLATE) @@ -8971,112 +9476,90 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp Declaration* etdec = tmpld->mNext; while (etdec && !etdec->IsSameParams(tdec)) etdec = etdec->mNext; - if (etdec) +#endif + + Parser* p = tmpld->mParser->Clone(); + + p->mScanner->Replay(tmpld->mTokens); + + tdec->mScope->mName = tdec->MangleIdent(); + tdec->mNext = tmpld->mNext; + tmpld->mNext = tdec; + + tdec->mScope->mParent = tmpld->mScope->mParent; + + p->mTemplateScope = tdec->mScope; + if (tmpld->mFlags & DTF_AUTO_TEMPLATE) { - return etdec->mBase; + Declaration * ndec = tmpld->mBase->ExpandTemplate(tdec->mScope); + + Declaration* pdec = tmpld->mBase; + + if (pdec) + { + Declaration* pcdec = nullptr; + + while (pdec && !ndec->mBase->IsSameParams(pdec->mBase)) + { + pcdec = pdec; + pdec = pdec->mNext; + } + + if (!pdec) + pcdec->mNext = ndec; + } + + tdec->mBase = ndec; + ndec->mValue = p->ParseFunction(ndec->mBase); + ndec->mFlags |= DTF_DEFINED; + + ndec->mIdent = ndec->mIdent->Mangle(tdec->mScope->mName->mString); + ndec->mQualIdent = ndec->mQualIdent->Mangle(tdec->mScope->mName->mString); } else { - Declaration* epdec = tdec->mParams; - while (epdec && epdec->mBase && epdec->mBase->mType != DT_TYPE_TEMPLATE && epdec->mBase->mType != DT_CONST_TEMPLATE) - epdec = epdec->mNext; - - if (epdec) - { - // Partial template specification - Declaration * bdec = new Declaration(mScanner->mLocation, tmpld->mBase->mType); - tdec->mBase = bdec; - bdec->mTemplate = tdec; - bdec->mBase = tmpld->mBase->mBase; - tdec->mNext = tmpld; - bdec->mIdent = tdec->MangleIdent(); - - return bdec; - } - - Parser* p = tmpld->mParser->Clone(); - - p->mScanner->Replay(tmpld->mTokens); - - tdec->mScope->mName = tdec->MangleIdent(); - tdec->mNext = tmpld->mNext; - tmpld->mNext = tdec; - - tdec->mScope->mParent = tmpld->mScope->mParent; - - p->mTemplateScope = tdec->mScope; - if (tmpld->mFlags & DTF_AUTO_TEMPLATE) - { - Declaration * ndec = tmpld->mBase->ExpandTemplate(tdec->mScope); - - Declaration* pdec = tmpld->mBase; - - if (pdec) - { - Declaration* pcdec = nullptr; - - while (pdec && !ndec->mBase->IsSameParams(pdec->mBase)) - { - pcdec = pdec; - pdec = pdec->mNext; - } - - if (!pdec) - pcdec->mNext = ndec; - } - - tdec->mBase = ndec; - ndec->mValue = p->ParseFunction(ndec->mBase); - ndec->mFlags |= DTF_DEFINED; - - ndec->mIdent = ndec->mIdent->Mangle(tdec->mScope->mName->mString); - ndec->mQualIdent = ndec->mQualIdent->Mangle(tdec->mScope->mName->mString); - } - else - { - tdec->mBase = p->ParseDeclaration(nullptr, true, false, tmpld->mClass, tdec); - } - - p->mTemplateScope = nullptr; - - if (tdec->mBase->mType == DT_ANON) - { - tdec->mBase = tdec->mBase->mBase; - mCompilationUnits->mTemplateScope->Insert(tmpld->mQualIdent, tmpld); - - tdec->mBase->mScope->Iterate([=](const Ident* ident, Declaration* mdec) - { - if (mdec->mType == DT_CONST_FUNCTION) - { - while (mdec) - { - if (!(mdec->mFlags & DTF_DEFINED)) - { - Declaration* mpdec = mCompilationUnits->mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); - while (mpdec && !mdec->mBase->IsTemplateSameParams(mpdec->mBase, tdec)) - mpdec = mpdec->mNext; - if (mpdec && mpdec->mTemplate) - { - if (mdec->mTemplate) - { - Declaration * mtdec = p->ParseTemplateExpansion(mpdec->mTemplate, tdec); - mtdec->mClass = mdec->mTemplate->mClass; - mdec->mTemplate = mtdec; - mdec->mTemplate->mBase = mdec; - } - else - p->ParseTemplateExpansion(mpdec->mTemplate, tdec); - } - } - - mdec = mdec->mNext; - } - } - }); - } - - return tdec->mBase; + tdec->mBase = p->ParseDeclaration(nullptr, true, false, tmpld->mClass, tdec); } + + p->mTemplateScope = nullptr; + + if (tdec->mBase->mType == DT_ANON) + { + tdec->mBase = tdec->mBase->mBase; + mCompilationUnits->mTemplateScope->Insert(tmpld->mQualIdent, tmpld); + + tdec->mBase->mScope->Iterate([=](const Ident* ident, Declaration* mdec) + { + if (mdec->mType == DT_CONST_FUNCTION) + { + while (mdec) + { + if (!(mdec->mFlags & DTF_DEFINED)) + { + Declaration* mpdec = mCompilationUnits->mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); + while (mpdec && !mdec->mBase->IsTemplateSameParams(mpdec->mBase, tdec)) + mpdec = mpdec->mNext; + if (mpdec && mpdec->mTemplate) + { + if (mdec->mTemplate) + { + Declaration * mtdec = p->ParseTemplateExpansion(mpdec->mTemplate, tdec); + mtdec->mClass = mdec->mTemplate->mClass; + mdec->mTemplate = mtdec; + mdec->mTemplate->mBase = mdec; + } + else + p->ParseTemplateExpansion(mpdec->mTemplate, tdec); + } + } + + mdec = mdec->mNext; + } + } + }); + } + + return tdec->mBase; } void Parser::CompleteTemplateExpansion(Declaration* tmpld) @@ -9121,7 +9604,7 @@ Declaration* Parser::FunctionAutoParamsToTemplate(Declaration* fdec) { Declaration* tdec = new Declaration(fdec->mLocation, DT_TEMPLATE); tdec->mParser = this->Clone(); - tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + tdec->mScope = new DeclarationScope(mTemplateScope, SLEVEL_TEMPLATE); Declaration* ppdec = nullptr; int ntp = 0; @@ -9221,60 +9704,63 @@ Declaration * Parser::ParseTemplateDeclaration(Declaration* pthis) Declaration* ppdec = nullptr; ConsumeToken(TK_LESS_THAN); - for (;;) + if (mScanner->mToken != TK_GREATER_THAN) { - Declaration* pdec = nullptr; - - if (ConsumeTokenIf(TK_CLASS) || ConsumeTokenIf(TK_TYPENAME)) + for (;;) { - if (ConsumeTokenIf(TK_ELLIPSIS)) + Declaration* pdec = nullptr; + + if (ConsumeTokenIf(TK_CLASS) || ConsumeTokenIf(TK_TYPENAME)) { - if (mScanner->mToken == TK_IDENT) + if (ConsumeTokenIf(TK_ELLIPSIS)) { - pdec = new Declaration(mScanner->mLocation, DT_PACK_TEMPLATE); + if (mScanner->mToken == TK_IDENT) + { + pdec = new Declaration(mScanner->mLocation, DT_PACK_TEMPLATE); + pdec->mIdent = mScanner->mTokenIdent; + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + } + else if (mScanner->mToken == TK_IDENT) + { + pdec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); pdec->mIdent = mScanner->mTokenIdent; mScanner->NextToken(); } else mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); } - else if (mScanner->mToken == TK_IDENT) + else if (ConsumeTokenIf(TK_INT)) { - pdec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); - pdec->mIdent = mScanner->mTokenIdent; - mScanner->NextToken(); + if (mScanner->mToken == TK_IDENT) + { + pdec = new Declaration(mScanner->mLocation, DT_CONST_TEMPLATE); + pdec->mIdent = mScanner->mTokenIdent; + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); } else - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); - } - else if (ConsumeTokenIf(TK_INT)) - { - if (mScanner->mToken == TK_IDENT) + mErrors->Error(mScanner->mLocation, EERR_TEMPLATE_PARAMS, "'class' or 'int' expected as template parameter"); + + if (pdec) { - pdec = new Declaration(mScanner->mLocation, DT_CONST_TEMPLATE); - pdec->mIdent = mScanner->mTokenIdent; - mScanner->NextToken(); + tdec->mScope->Insert(pdec->mIdent, pdec); + pdec->mFlags |= DTF_DEFINED; + + if (ppdec) + ppdec->mNext = pdec; + else + tdec->mParams = pdec; + ppdec = pdec; } - else - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + + if (!ConsumeTokenIf(TK_COMMA)) + break; } - else - mErrors->Error(mScanner->mLocation, EERR_TEMPLATE_PARAMS, "'class' or 'int' expected as template parameter"); - - if (pdec) - { - tdec->mScope->Insert(pdec->mIdent, pdec); - pdec->mFlags |= DTF_DEFINED; - - if (ppdec) - ppdec->mNext = pdec; - else - tdec->mParams = pdec; - ppdec = pdec; - } - - if (!ConsumeTokenIf(TK_COMMA)) - break; } ConsumeToken(TK_GREATER_THAN); @@ -9295,7 +9781,7 @@ Declaration * Parser::ParseTemplateDeclaration(Declaration* pthis) void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthis) { mScanner->BeginRecord(); - if (mScanner->mToken == TK_CLASS) + if (mScanner->mToken == TK_CLASS || mScanner->mToken == TK_STRUCT) { // Class template Declaration* bdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT); @@ -9404,7 +9890,24 @@ void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthi tdec->mScope->mName = tdec->mQualIdent; if (tdec->mQualIdent == mScope->Mangle(tdec->mIdent)) - mScope->Insert(tdec->mIdent, tdec->mBase); + { + Declaration* pdec = mScope->Insert(tdec->mIdent, tdec->mBase); + if (pdec) + { + Declaration* ppdec = pdec; + while (pdec && !pdec->IsSameTemplate(tdec->mBase)) + { + ppdec = pdec; + pdec = pdec->mNext; + } + + if (pdec && pdec->mTemplate) + { + tdec->mNext = pdec->mTemplate->mNext; + pdec->mTemplate->mNext = tdec; + } + } + } Declaration* pdec = mCompilationUnits->mScope->Insert(tdec->mQualIdent, tdec->mBase); if (pdec) diff --git a/oscar64/Parser.h b/oscar64/Parser.h index b0f5e9e..ade1d6c 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -91,6 +91,7 @@ protected: Declaration* ParseQualIdent(void); + void SkipStatement(void); Expression* ParseStatement(void); Expression* ParseSwitchStatement(void); @@ -109,6 +110,7 @@ protected: void ParseTemplateDeclarationBody(Declaration* tdec, Declaration* pthis); Declaration* FunctionAutoParamsToTemplate(Declaration* fdec); + int ExpansionDistance(Declaration* tdec, Declaration* spec); Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); void CompleteTemplateExpansion(Declaration* tmpld); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 849a06e..472c04e 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -148,6 +148,7 @@ const char* TokenNames[] = "'#repeat'", "'#until'", "'#embed'", + "'#for'", "'##'", "'namespace'", @@ -596,6 +597,84 @@ void Scanner::NextPreToken(void) 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) { NextRawToken(); @@ -1313,6 +1392,8 @@ void Scanner::NextRawToken(void) mToken = TK_PREP_UNTIL; else if (!strcmp(tkprep, "embed")) mToken = TK_PREP_EMBED; + else if (!strcmp(tkprep, "for")) + mToken = TK_PREP_FOR; else mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "Invalid preprocessor command", tkprep); } @@ -1912,6 +1993,19 @@ bool Scanner::NextChar(void) { 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; // delete mDefineArguments; diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 9d6ade7..8db05ac 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -146,6 +146,7 @@ enum Token TK_PREP_REPEAT, TK_PREP_UNTIL, TK_PREP_EMBED, + TK_PREP_FOR, TK_PREP_CONCAT, @@ -284,7 +285,14 @@ protected: const char * mLine; int mOffset; char mChar; + Macro * mLoopIndex; + int64 mLoopCount, mLoopLimit; MacroDict* mDefinedArguments; + + MacroExpansion(void) + : mLink(nullptr), mLine(nullptr), mOffset(0), mChar(0), mLoopIndex(nullptr), mLoopCount(0), mLoopLimit(0), mDefinedArguments(nullptr) + {} + } * mMacroExpansion; int mMacroExpansionDepth; From c7f919e22e8ec8dadb5e453be9fd94c04a023b9f Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 20 Sep 2023 18:06:48 +0200 Subject: [PATCH 125/169] Bump version number --- README.md | 8 +++++ oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++--- oscar64setup/oscar64setup.vdproj | 58 ++++++++++++++++---------------- 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 1d9be93..2b0ef43 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ Supported Features: * auto variables, parameters and return types * for range loop * constexpr compile time evaluation +* parameter packs and templates ## Installation and Usage @@ -558,6 +559,13 @@ This sample fills a single screen column with a given color, by generating 25 as This sample initially assigns the value 0 to the pre processor macro ry and increments it each time the loop body is replicated. The loop generates 25 copies of the body, each with a different value for ry. +A simpler loop with only a single line template expansion is provided with the #for(iterator, count) preprocessor command: + + char * const ScreenRows2[] = { + #for(i,SCREEN_HEIGHT) Screen + SCREEN_WIDTH * i, + }; + + ### Linker control diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 2653d13..cb0e4db 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.25.218"); + strcpy(strProductVersion, "1.26.219"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 1fbb7d2..bd4392e 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,25,218,0 - PRODUCTVERSION 1,25,218,0 + FILEVERSION 1,26,219,0 + PRODUCTVERSION 1,26,219,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.25.218.0" + VALUE "FileVersion", "1.26.219.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.25.218.0" + VALUE "ProductVersion", "1.26.219.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 3e511e2..abcda9f 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -244,12 +244,6 @@ } "Entry" { - "MsmKey" = "8:_32B099B0E98B47D0892700BA42D0760E" - "OwnerKey" = "8:_UNDEFINED" - "MsmSig" = "8:_UNDEFINED" - } - "Entry" - { "MsmKey" = "8:_33E047EAEFFB45778C59472F157161DA" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1006,6 +1000,12 @@ } "Entry" { + "MsmKey" = "8:_D38EB85FE8E3492DA4BD8E6E4F7CEBEB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_D52B954DFBCE4EB0932433DE7FCE9090" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -2073,26 +2073,6 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } - "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_32B099B0E98B47D0892700BA42D0760E" - { - "SourcePath" = "8:..\\include\\opp\\move.h" - "TargetName" = "8:move.h" - "Tag" = "8:" - "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" - "Condition" = "8:" - "Transitive" = "11:FALSE" - "Vital" = "11:TRUE" - "ReadOnly" = "11:FALSE" - "Hidden" = "11:FALSE" - "System" = "11:FALSE" - "Permanent" = "11:FALSE" - "SharedLegacy" = "11:FALSE" - "PackageAs" = "3:1" - "Register" = "3:1" - "Exclude" = "11:FALSE" - "IsDependency" = "11:FALSE" - "IsolateTo" = "8:" - } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_33E047EAEFFB45778C59472F157161DA" { "SourcePath" = "8:..\\include\\c64\\iecbus.h" @@ -4613,6 +4593,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D38EB85FE8E3492DA4BD8E6E4F7CEBEB" + { + "SourcePath" = "8:..\\include\\opp\\utility.h" + "TargetName" = "8:utility.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D52B954DFBCE4EB0932433DE7FCE9090" { "SourcePath" = "8:..\\samples\\hiresmc\\paint.c" @@ -5686,15 +5686,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{041674C8-9934-4E51-B424-DA00BD3E2C89}" - "PackageCode" = "8:{7F8F7803-BF9B-423B-AD7F-ABAFD9B5DC8F}" + "ProductCode" = "8:{CBCAE13D-B17A-44B2-8FC3-38EE53B02C31}" + "PackageCode" = "8:{75E5F5B4-AE17-4214-ADB6-18D9177E8E1B}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.25.218" + "ProductVersion" = "8:1.26.219" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 9d8c6991e8374e4d2b4a2adf4c01ddf7ecf04816 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 23 Sep 2023 14:56:04 +0200 Subject: [PATCH 126/169] Add global optimizer for parameter/return optimizations --- README.md | 6 +- include/opp/iostream.h | 6 +- oscar64/Compiler.cpp | 29 +- oscar64/Compiler.h | 2 + oscar64/CompilerTypes.h | 7 +- oscar64/Constexpr.cpp | 47 +- oscar64/Constexpr.h | 1 + oscar64/Declaration.cpp | 91 +++- oscar64/Declaration.h | 8 +- oscar64/GlobalAnalyzer.cpp | 3 + oscar64/GlobalOptimizer.cpp | 925 ++++++++++++++++++++++++++++++++ oscar64/GlobalOptimizer.h | 43 ++ oscar64/InterCode.cpp | 66 ++- oscar64/InterCode.h | 1 + oscar64/InterCodeGenerator.cpp | 33 +- oscar64/Parser.cpp | 24 +- oscar64/oscar64.cpp | 7 + oscar64/oscar64.vcxproj | 2 + oscar64/oscar64.vcxproj.filters | 6 + 19 files changed, 1258 insertions(+), 49 deletions(-) create mode 100644 oscar64/GlobalOptimizer.cpp create mode 100644 oscar64/GlobalOptimizer.h diff --git a/README.md b/README.md index 2b0ef43..d0d1876 100644 --- a/README.md +++ b/README.md @@ -559,7 +559,11 @@ This sample fills a single screen column with a given color, by generating 25 as This sample initially assigns the value 0 to the pre processor macro ry and increments it each time the loop body is replicated. The loop generates 25 copies of the body, each with a different value for ry. -A simpler loop with only a single line template expansion is provided with the #for(iterator, count) preprocessor command: +A simpler loop with only a single line template expansion is provided with the for preprocessor command: + + #for(, ) + +This sample generates an array with pointers to screen rows: char * const ScreenRows2[] = { #for(i,SCREEN_HEIGHT) Screen + SCREEN_WIDTH * i, diff --git a/include/opp/iostream.h b/include/opp/iostream.h index 5548bef..5d43bc6 100644 --- a/include/opp/iostream.h +++ b/include/opp/iostream.h @@ -9,7 +9,7 @@ class ios { public: - ios(void); + constexpr ios(void); virtual ~ios(void); char fill() const; @@ -85,7 +85,7 @@ typedef ostream & (* manip)(ostream &); class ostream : public ios { public: - ostream(void); + constexpr ostream(void); ostream & put(char c); ostream & write(const char * s, int n); @@ -150,7 +150,7 @@ protected: class costream : public ostream { public: - costream(void); + constexpr costream(void); protected: void bput(char ch); diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index baae398..2a76edf 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -33,6 +33,7 @@ Compiler::Compiler(void) mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker, mCompilationUnits->mSectionCode); mInterCodeModule = new InterCodeModule(mErrors, mLinker); mGlobalAnalyzer = new GlobalAnalyzer(mErrors, mLinker); + mGlobalOptimizer = new GlobalOptimizer(mErrors, mLinker); mCartridgeID = 0x0000; } @@ -835,8 +836,6 @@ bool Compiler::GenerateCode(void) dcrtstart->mSection = sectionStartup; - mGlobalAnalyzer->mCompilerOptions = mCompilerOptions; - if (mCompilerOptions & COPT_CPLUSPLUS) { if (mCompilerOptions & COPT_VERBOSE) @@ -845,6 +844,32 @@ bool Compiler::GenerateCode(void) BuildVTables(); } + if (mCompilerOptions & COPT_OPTIMIZE_GLOBAL) + { + mGlobalOptimizer->mCompilerOptions = mCompilerOptions; + + if (mCompilerOptions & COPT_VERBOSE) + printf("Global optimizer\n"); + + do { + mGlobalOptimizer->Reset(); + + mGlobalOptimizer->AnalyzeAssembler(dcrtstart->mValue, nullptr); + + for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++) + { + Declaration* dec = mCompilationUnits->mReferenced[i]; + if (dec->mType == DT_CONST_FUNCTION) + mGlobalOptimizer->AnalyzeProcedure(dec->mValue, dec); + else + mGlobalOptimizer->AnalyzeGlobalVariable(dec); + } + } while (mGlobalOptimizer->Optimize()); + + } + + mGlobalAnalyzer->mCompilerOptions = mCompilerOptions; + if (mCompilerOptions & COPT_VERBOSE) printf("Global analyzer\n"); diff --git a/oscar64/Compiler.h b/oscar64/Compiler.h index 3b9f00d..474dcce 100644 --- a/oscar64/Compiler.h +++ b/oscar64/Compiler.h @@ -7,6 +7,7 @@ #include "NativeCodeGenerator.h" #include "InterCodeGenerator.h" #include "GlobalAnalyzer.h" +#include "GlobalOptimizer.h" #include "Linker.h" #include "CompilerTypes.h" @@ -25,6 +26,7 @@ public: InterCodeGenerator* mInterCodeGenerator; InterCodeModule* mInterCodeModule; GlobalAnalyzer* mGlobalAnalyzer; + GlobalOptimizer* mGlobalOptimizer; GrowingArray mByteCodeFunctions; ExpandingArray mNativeProcedures; diff --git a/oscar64/CompilerTypes.h b/oscar64/CompilerTypes.h index e6c6016..79b8fc5 100644 --- a/oscar64/CompilerTypes.h +++ b/oscar64/CompilerTypes.h @@ -13,6 +13,7 @@ static const uint64 COPT_OPTIMIZE_CONST_EXPRESSIONS = 1ULL << 7; static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 1ULL << 8; static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9; static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10; +static const uint64 COPT_OPTIMIZE_GLOBAL = 1ULL << 11; static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16; static const uint64 COPT_NATIVE = 1ULL << 17; @@ -44,11 +45,11 @@ static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS; -static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS; +static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL; -static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS; +static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL; -static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_AUTO_ZEROPAGE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS; +static const uint64 COPT_OPTIMIZE_ALL = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_AUTO_ZEROPAGE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL; enum TargetMachine { diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index 97efbfa..6f52b05 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -434,6 +434,7 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type { case DT_TYPE_INTEGER: case DT_TYPE_BOOL: + case DT_TYPE_ENUM: dec = new Declaration(mLocation, DT_CONST_INTEGER); dec->mBase = type; dec->mFlags = type->mFlags & DTF_SIGNED; @@ -454,20 +455,25 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type dec->mSection = dataSection; dec->mOffset = offset; - Declaration* ldec = nullptr; while (type) { for (Declaration* mdec = type->mParams; mdec; mdec = mdec->mNext) { Declaration* cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection); cdec->mOffset = mdec->mOffset; + cdec->mNext = dec->mParams; + dec->mParams = cdec; + } - if (ldec) - ldec->mNext = cdec; - else - dec->mParams = cdec; - - ldec = cdec; + if (type->mVTable) + { + Declaration * cdec = new Declaration(mLocation, DT_CONST_INTEGER); + cdec->mBase = TheConstCharTypeDeclaration; + cdec->mSize = 1; + cdec->mInteger = type->mVTable->mDefaultConstructor->mInteger; + cdec->mOffset = offset + type->mVTable->mOffset; + cdec->mNext = dec->mParams; + dec->mParams = cdec; } if (type->mBase) @@ -587,6 +593,29 @@ void ConstexprInterpreter::DeleteValue(Value* v) mErrors->Error(v->mLocation, EERR_DOUBLE_FREE, "Freeing not allocated memory"); } +Expression* ConstexprInterpreter::EvalConstructor(Expression* exp) +{ + mProcType = exp->mLeft->mDecType; + + Declaration* cdec = exp->mLeft->mDecType->mParams; + + int pos = 0; + mResult = Value(exp->mLocation, cdec->mBase->mBase); + mParams[pos] = Value(exp->mLocation, cdec->mBase); + mParams[pos].PutPtr(Value(&mResult)); + pos = 2; + + mHeap = new ExpandingArray(); + + Execute(exp->mLeft->mDecValue->mValue); + + if (mHeap->Size() > 0) + mErrors->Error(exp->mLocation, EERR_UNBALANCED_HEAP_USE, "Unbalanced heap use in constexpr"); + delete mHeap; + + return mResult.ToExpression(mDataSection); +} + Expression* ConstexprInterpreter::EvalCall(Expression* exp) { mProcType = exp->mLeft->mDecType; @@ -1118,6 +1147,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) } case EX_LIST: + case EX_COMMA: Eval(exp->mLeft); return Eval(exp->mRight); @@ -1191,6 +1221,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) Value v = Eval(exp->mLeft); if (v.mBaseValue) return Value(exp->mLocation, v.mBaseValue, exp->mDecType, v.mOffset + exp->mDecValue->mOffset); + break; } case EX_INDEX: @@ -1208,6 +1239,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) Value p = v.GetPtr(); return Value(exp->mLocation, p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt())); } + break; } case EX_RESULT: @@ -1256,6 +1288,7 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) case EX_PREFIX: case EX_TYPECAST: case EX_CALL: + case EX_COMMA: case EX_LIST: case EX_CONDITIONAL: case EX_LOGICAL_AND: diff --git a/oscar64/Constexpr.h b/oscar64/Constexpr.h index 8a0df57..7986427 100644 --- a/oscar64/Constexpr.h +++ b/oscar64/Constexpr.h @@ -9,6 +9,7 @@ public: ~ConstexprInterpreter(void); Expression* EvalCall(Expression* exp); + Expression* EvalConstructor(Expression* exp); protected: struct Value; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 3d5facf..2772d84 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -222,6 +222,9 @@ void Expression::Dump(int ident) const case EX_LIST: printf("LIST"); break; + case EX_COMMA: + printf("COMMA"); + break; case EX_RETURN: printf("RETURN"); break; @@ -523,6 +526,10 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio ex->mDecType = mDecType; return ex; } + else if (mType == EX_PREFIX && mToken == TK_BINARY_AND && mLeft->mType == EX_PREFIX && mLeft->mToken == TK_MUL) + { + return mLeft->mLeft; + } #endif else if (mType == EX_TYPECAST && mLeft->mType == EX_CONSTANT) { @@ -888,7 +895,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio return ex; } } - else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_CONSTEXPR)) + else if (mType == EX_CALL && mLeft->mType == EX_CONSTANT && (mLeft->mDecValue->mFlags & DTF_CONSTEXPR) && dataSection) { ConstexprInterpreter cinter(mLocation, errors, dataSection); return cinter.EvalCall(this); @@ -900,7 +907,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio Declaration::Declaration(const Location& loc, DecType type) : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr), mMangleIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mNumVars(0), - mBase(nullptr), mParams(nullptr), mParamPack(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), + mBase(nullptr), mParams(nullptr), mParamPack(nullptr), mValue(nullptr), mReturn(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), mMutable(nullptr), mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), @@ -908,7 +915,7 @@ Declaration::Declaration(const Location& loc, DecType type) mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr), - mShift(0), mBits(0) + mShift(0), mBits(0), mOptFlags(0) {} Declaration::~Declaration(void) @@ -960,6 +967,71 @@ Declaration* Declaration::BuildArrayPointer(void) return this; } +Declaration* Declaration::ConstCast(Declaration* ntype) +{ + if (ntype == mBase) + return this; + else if (ntype->mType == DT_TYPE_POINTER) + { + if (mBase->mType == DT_TYPE_POINTER) + { + if (mBase->mBase->IsSame(ntype->mBase)) + return this; + + Declaration* pdec = this->Clone(); + pdec->mBase = ntype; + return pdec; + } + else if (mType == DT_TYPE_INTEGER) + { + Declaration* pdec = this->Clone(); + pdec->mType = DT_CONST_ADDRESS; + pdec->mBase = ntype; + pdec->mSize = 2; + return pdec; + } + else + return this; + } + else if (ntype->mType == DT_TYPE_INTEGER || ntype->mType == DT_TYPE_BOOL || ntype->mType == DT_TYPE_ENUM) + { + if (mType == DT_TYPE_FLOAT) + { + Declaration* pdec = this->Clone(); + pdec->mInteger = int64(mNumber); + pdec->mBase = ntype; + pdec->mSize = ntype->mSize; + return pdec; + } + else + { + Declaration* pdec = this->Clone(); + pdec->mBase = ntype; + pdec->mSize = ntype->mSize; + return pdec; + } + } + else if (ntype->mType == DT_TYPE_FLOAT) + { + if (mType == DT_TYPE_FLOAT) + { + Declaration* pdec = this->Clone(); + pdec->mBase = ntype; + return pdec; + } + else + { + Declaration* pdec = this->Clone(); + pdec->mNumber = float(mInteger); + pdec->mBase = ntype; + pdec->mSize = ntype->mSize; + return pdec; + } + } + else + return this; +} + Declaration* Declaration::BuildPointer(const Location& loc) { Declaration* pdec = new Declaration(loc, DT_TYPE_POINTER); @@ -2263,6 +2335,7 @@ Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheConstVoidPo Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration; Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration; Expression* TheVoidExpression; +Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration; void InitDeclarations(void) { @@ -2345,4 +2418,16 @@ void InitDeclarations(void) TheVoidExpression = new Expression(noloc, EX_CONSTANT); TheVoidExpression->mDecType = TheConstVoidTypeDeclaration; TheVoidExpression->mDecValue = TheConstVoidValueDeclaration; + + + TheNullptrConstDeclaration = new Declaration(noloc, DT_CONST_ADDRESS); + TheNullptrConstDeclaration->mBase = TheVoidPointerTypeDeclaration; + TheNullptrConstDeclaration->mSize = 2; + TheZeroIntegerConstDeclaration = new Declaration(noloc, DT_CONST_INTEGER); + TheZeroIntegerConstDeclaration->mBase = TheSignedIntTypeDeclaration; + TheZeroIntegerConstDeclaration->mSize = 2; + TheZeroFloatConstDeclaration = new Declaration(noloc, DT_CONST_FLOAT); + TheZeroFloatConstDeclaration->mBase = TheFloatTypeDeclaration; + TheZeroFloatConstDeclaration->mSize = 4; + } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 17bb110..1c8ab25 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -116,6 +116,7 @@ static const uint64 DTF_VAR_ADDRESS = (1ULL << 46); static const uint64 DTF_FUNC_THIS = (1ULL << 47); static const uint64 DTF_VAR_ALIASING = (1ULL << 48); +static const uint64 DTF_FPARAM_UNUSED = (1ULL << 49); class Declaration; @@ -196,6 +197,7 @@ enum ExpressionType EX_VCALL, EX_DISPATCH, EX_LIST, + EX_COMMA, EX_RETURN, EX_SEQUENCE, EX_WHILE, @@ -267,13 +269,13 @@ public: Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; Declaration * mVTable, * mClass, * mTemplate; - Expression* mValue; + Expression* mValue, * mReturn; DeclarationScope* mScope; int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe; uint8 mShift, mBits; int64 mInteger, mMinValue, mMaxValue; double mNumber; - uint64 mFlags, mCompilerOptions; + uint64 mFlags, mCompilerOptions, mOptFlags; const Ident * mIdent, * mQualIdent, * mMangleIdent; LinkerSection * mSection; const uint8 * mData; @@ -322,6 +324,7 @@ public: Declaration* NonRefBase(void); Declaration* BuildArrayPointer(void); Declaration* DeduceAuto(Declaration* dec); + Declaration* ConstCast(Declaration* ntype); bool IsAuto(void) const; DecType ValueType(void) const; @@ -343,5 +346,6 @@ extern Declaration* TheVoidTypeDeclaration, * TheConstVoidTypeDeclaration, * The extern Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheConstVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration; extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration; extern Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration; +extern Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration; extern Expression* TheVoidExpression; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 1d50024..bc2b778 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -219,6 +219,8 @@ void GlobalAnalyzer::AutoInline(void) { if (pdec->mFlags & DTF_FPARAM_CONST) { + pdec->mFlags |= DTF_FPARAM_UNUSED; + pdec->mVarIndex = dec->mNumVars++; Expression* aexp = new Expression(pdec->mLocation, EX_INITIALIZATION); @@ -897,6 +899,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo } break; case EX_LIST: + case EX_COMMA: RegisterProc(Analyze(exp->mLeft, procDec, false)); return Analyze(exp->mRight, procDec, false); case EX_RETURN: diff --git a/oscar64/GlobalOptimizer.cpp b/oscar64/GlobalOptimizer.cpp new file mode 100644 index 0000000..a3b20a5 --- /dev/null +++ b/oscar64/GlobalOptimizer.cpp @@ -0,0 +1,925 @@ +#include "GlobalOptimizer.h" +#include "Constexpr.h" + + +#define DUMP_OPTS 0 + + +static const uint64 OPTF_ANALYZED = (1ULL << 0); +static const uint64 OPTF_ANALYZING = (1ULL << 1); +static const uint64 OPTF_RECURSIVE = (1ULL << 2); +static const uint64 OPTF_FUNC_VARIABLE = (1ULL << 3); +static const uint64 OPTF_CALLED = (1ULL << 4); +static const uint64 OPTF_CALLING = (1ULL << 5); +static const uint64 OPTF_VAR_MODIFIED = (1ULL << 6); +static const uint64 OPTF_VAR_ADDRESS = (1ULL << 7); +static const uint64 OPTF_VAR_USED = (1ULL << 8); +static const uint64 OPTF_VAR_CONST = (1ULL << 9); +static const uint64 OPTF_VAR_NOCONST = (1ULL << 10); +static const uint64 OPTF_SINGLE_RETURN = (1ULL << 11); +static const uint64 OPTF_MULTI_RETURN = (1ULL << 12); + + +GlobalOptimizer::GlobalOptimizer(Errors* errors, Linker* linker) + : mErrors(errors), mLinker(linker) +{ + +} + +GlobalOptimizer::~GlobalOptimizer(void) +{ + +} + +void GlobalOptimizer::Reset(void) +{ + for (int i = 0; i < mFunctions.Size(); i++) + { + Declaration* func = mFunctions[i]; + Declaration* ftype = func->mBase; + func->mOptFlags = 0; + ftype->mOptFlags = 0; + func->mReturn = nullptr; + + Declaration* pdec = ftype->mParams; + while (pdec) + { + pdec->mOptFlags = 0; + pdec = pdec->mNext; + } + } + + for (int i = 0; i < mGlobalVariables.Size(); i++) + { + mGlobalVariables[i]->mOptFlags = 0; + } + + mFunctions.SetSize(0); + mGlobalVariables.SetSize(0); + mCalledFunctions.SetSize(0); + mCalledFunctions.SetSize(0); +} + +void GlobalOptimizer::PropagateParamCommas(Expression*& fexp, Expression*& exp) +{ + PropagateCommas(exp); + if (exp->mType == EX_COMMA) + { + Expression* cexp = exp; + exp = cexp->mRight; + cexp->mRight = fexp; + fexp = cexp; + fexp->mDecType = cexp->mRight->mDecType; + } +} + +void GlobalOptimizer::PropagateCommas(Expression*& exp) +{ + if (exp->mType == EX_PREFIX && exp->mLeft->mType == EX_COMMA) + { + Expression* cexp = exp->mLeft; + exp->mLeft = cexp->mRight; + cexp->mDecType = exp->mDecType; + cexp->mRight = exp->ConstantFold(mErrors, nullptr); + exp = cexp; + } + else if (exp->mType == EX_CALL) + { + Expression* pexp = exp; + Expression* rexp = pexp->mRight; + if (rexp) + { + while (rexp && rexp->mType == EX_LIST) + { + PropagateParamCommas(exp, rexp->mLeft); + if (rexp->mLeft-> mType == EX_COMMA) + pexp = rexp; + rexp = rexp->mRight; + } + if (rexp) + PropagateParamCommas(exp, pexp->mRight); + } + } + else + { + if (exp->mLeft) + PropagateCommas(exp->mLeft); + if (exp->mRight) + PropagateCommas(exp->mRight); + } + +} + +bool GlobalOptimizer::CheckConstReturns(Expression*& exp) +{ + bool changed = false; + + if (exp->mType == EX_CALL && exp->mDecType && exp->mDecType->mType != DT_TYPE_VOID) + { + if (exp->mLeft->mType == EX_CONSTANT) + { + Declaration* pcall = exp->mLeft->mDecValue; + if ((pcall->mOptFlags & OPTF_SINGLE_RETURN) && pcall->mReturn->mLeft) + { + Expression * rexp = pcall->mReturn->mLeft; + if (rexp->mType == EX_CONSTANT) + { +#if DUMP_OPTS + printf("Extract const return\n"); +#endif + + Expression* lexp = new Expression(exp->mLocation, EX_COMMA); + lexp->mLeft = exp; + lexp->mRight = new Expression(pcall->mReturn->mLocation, EX_CONSTANT); + lexp->mRight->mDecValue = pcall->mReturn->mLeft->mDecValue; + lexp->mRight->mDecType = exp->mDecType; + lexp->mDecType = exp->mDecType; + exp->mDecType = TheVoidTypeDeclaration; + exp = lexp; + return true; + } + else if (rexp->mType == EX_PREFIX && rexp->mToken == TK_MUL && rexp->mLeft->mType == EX_VARIABLE && rexp->mLeft->mDecValue->mType == DT_ARGUMENT) + { + Declaration* pdec = rexp->mLeft->mDecValue; + if (pdec->mVarIndex == 0 && !(pdec->mOptFlags & OPTF_VAR_ADDRESS)) + { + Expression* pex = exp->mRight; + if (pex->mType == EX_LIST) + pex = pex->mLeft; + if (pex->mType == EX_CONSTANT) + { +#if DUMP_OPTS + printf("Forward this pointer\n"); +#endif + Expression* lexp = new Expression(exp->mLocation, EX_COMMA); + lexp->mLeft = exp; + lexp->mRight = new Expression(pcall->mReturn->mLocation, EX_PREFIX); + lexp->mRight->mToken = TK_MUL; + lexp->mRight->mLeft = pex; + lexp->mRight->mDecType = pcall->mBase->mBase; + exp->mDecType = TheVoidTypeDeclaration; + exp = lexp; + return true; + } + } + } + } + } + } + + if (exp->mLeft && CheckConstReturns(exp->mLeft)) + changed = true; + if (exp->mRight && CheckConstReturns(exp->mRight)) + changed = true; + + return changed; +} + +bool GlobalOptimizer::CheckUnusedLocals(Expression*& exp) +{ + bool changed = false; + + if (exp->mType == EX_INITIALIZATION) + { + Expression* vexp = exp->mLeft; + if (vexp->mType == EX_VARIABLE) + { + Declaration* vdec = vexp->mDecValue; + if (vdec->mType == DT_VARIABLE && !(vdec->mFlags & (DTF_GLOBAL | DTF_STATIC)) && !(vdec->mOptFlags & OPTF_VAR_USED)) + { + exp = exp->mRight; + return true; + } + } + } + + if (exp->mLeft && CheckUnusedLocals(exp->mLeft)) + changed = true; + if (exp->mRight && CheckUnusedLocals(exp->mRight)) + changed = true; + + return changed; +} + +void GlobalOptimizer::RemoveValueReturn(Expression* exp) +{ + if (exp->mType == EX_RETURN && exp->mLeft) + { + if (exp->mLeft->HasSideEffects()) + { + exp->mType = EX_SEQUENCE; + exp->mRight = new Expression(exp->mLocation, EX_RETURN); + } + else + exp->mLeft = nullptr; + } + + if (exp->mLeft) + RemoveValueReturn(exp->mLeft); + if (exp->mRight) + RemoveValueReturn(exp->mRight); +} + +void GlobalOptimizer::UndoParamReference(Expression* exp, Declaration* param) +{ + if (exp) + { + if (exp->mType == EX_VARIABLE && exp->mDecValue == param) + { + exp->mDecType = param->mBase; + } + + UndoParamReference(exp->mLeft, param); + UndoParamReference(exp->mRight, param); + } +} + +bool GlobalOptimizer::ReplaceParamConst(Expression* exp, Declaration* param) +{ + bool changed = false; + if (exp) + { + if (exp->mType == EX_VARIABLE && exp->mDecValue == param) + { + exp->mType = EX_CONSTANT; + exp->mDecType = param->mBase; + exp->mDecValue = param->mValue->mDecValue->ConstCast(param->mBase); + changed = true; + } + + if (ReplaceParamConst(exp->mLeft, param)) + changed = true; + if (ReplaceParamConst(exp->mRight, param)) + changed = true; + } + return changed; +} + +bool GlobalOptimizer::Optimize(void) +{ + bool changed = false; + +#if DUMP_OPTS + printf("OPT---\n"); +#endif + for (int i = 0; i < mFunctions.Size(); i++) + { + Declaration* func = mFunctions[i]; + Declaration* ftype = func->mBase; + + if (func->mValue && func->mValue->mType != EX_DISPATCH) + { +#if DUMP_OPTS + printf("%s %08llx\n", mFunctions[i]->mQualIdent->mString, mFunctions[i]->mOptFlags); +#endif + if (CheckUnusedLocals(func->mValue)) + changed = true; + + if (CheckConstReturns(func->mValue)) + changed = true; + + if (!(func->mOptFlags & OPTF_FUNC_VARIABLE) && !(func->mBase->mFlags & DTF_VIRTUAL)) + { + if (!(func->mOptFlags & OPTF_VAR_USED) && func->mBase->mBase && (func->mBase->mBase->IsSimpleType() || func->mBase->mBase->IsReference())) + { +#if DUMP_OPTS + printf("Remove return value\n"); +#endif + RemoveValueReturn(func->mValue); + func->mBase->mBase = TheVoidTypeDeclaration; + changed = true; + } + else if (!(func->mOptFlags & OPTF_VAR_ADDRESS) && func->mBase->mBase && func->mBase->mBase->IsReference() && func->mBase->mBase->mBase->IsSimpleType()) + { +#if DUMP_OPTS + printf("Demote reference return\n"); +#endif + func->mBase->mBase = func->mBase->mBase->mBase; + changed = true; + } + + + Declaration* pdec = ftype->mParams; + int vi = 0; + while (pdec) + { + pdec->mVarIndex += vi; + if (!(pdec->mOptFlags & OPTF_VAR_USED) && !(pdec->mFlags & DTF_FPARAM_UNUSED)) + { + if (!pdec->mBase->IsReference() || !(pdec->mOptFlags & OPTF_VAR_ADDRESS)) + { +#if DUMP_OPTS + printf("Unused parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_"); +#endif + vi -= pdec->mSize; + + pdec->mFlags |= DTF_FPARAM_UNUSED; + changed = true; + } + } + else if (!(pdec->mOptFlags & OPTF_VAR_ADDRESS) && pdec->mBase->IsReference() && pdec->mBase->mBase->IsSimpleType()) + { +#if DUMP_OPTS + printf("Reference parameter %s to value\n", pdec->mIdent ? pdec->mIdent->mString : "_"); +#endif + vi += pdec->mSize - 2; + + pdec->mBase = pdec->mBase->mBase; + pdec->mSize = pdec->mBase->mSize; + + UndoParamReference(func->mValue, pdec); + + changed = true; + } + else if ((pdec->mOptFlags & OPTF_VAR_CONST) && !(pdec->mOptFlags & OPTF_VAR_ADDRESS)) + { + if (ReplaceParamConst(func->mValue, pdec)) + { +#if DUMP_OPTS + printf("Const parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_"); +#endif + changed = true; + } + } + + pdec->mOptFlags = 0; + pdec = pdec->mNext; + } + } + + PropagateCommas(func->mValue); + } + else if (func->mValue && func->mValue->mType == EX_DISPATCH) + { + if (!(func->mOptFlags & OPTF_FUNC_VARIABLE)) + { + Declaration* pdec = ftype->mParams; + while (pdec) + { + if ((pdec->mOptFlags & OPTF_VAR_CONST) && !(pdec->mOptFlags & OPTF_VAR_ADDRESS)) + { + if (ReplaceParamConst(func->mValue, pdec)) + { +#if DUMP_OPTS + printf("Const parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_"); +#endif + changed = true; + } + } + + pdec->mOptFlags = 0; + pdec = pdec->mNext; + } + } + } + } + + return changed; +} + +void GlobalOptimizer::AnalyzeProcedure(Expression* exp, Declaration* procDec) +{ + if (procDec->mOptFlags & OPTF_ANALYZING) + { + procDec->mOptFlags |= OPTF_RECURSIVE; + } + else if (!(procDec->mOptFlags & OPTF_ANALYZED)) + { + procDec->mOptFlags |= OPTF_ANALYZING | OPTF_ANALYZED; + + mFunctions.Push(procDec); + + if ((procDec->mFlags & DTF_INTRINSIC) && !procDec->mValue) + ; + else if (procDec->mFlags & DTF_DEFINED) + { + Analyze(exp, procDec, false); + } + else + mErrors->Error(procDec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", procDec->mQualIdent); + + procDec->mOptFlags &= ~OPTF_ANALYZING; + } +} + +void GlobalOptimizer::AnalyzeAssembler(Expression* exp, Declaration* procDec) +{ + while (exp) + { + if (exp->mLeft && exp->mLeft->mDecValue) + { + Declaration* adec = exp->mLeft->mDecValue; + if (adec->mType == DT_LABEL_REF) + { + + } + else if (adec->mType == DT_VARIABLE_REF) + { + if (adec->mBase->mFlags & DTF_GLOBAL) + AnalyzeGlobalVariable(adec->mBase); + else + adec->mBase->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS; + } + else if (adec->mType == DT_LABEL) + { + + } + else if (adec->mType == DT_VARIABLE) + { + if (adec->mFlags & DTF_GLOBAL) + AnalyzeGlobalVariable(adec); + else + adec->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS; + } + else if (adec->mType == DT_ARGUMENT) + { + adec->mOptFlags |= OPTF_VAR_USED; + } + else if (adec->mType == DT_FUNCTION_REF) + { + adec->mBase->mOptFlags |= OPTF_VAR_USED; + AnalyzeProcedure(adec->mBase->mValue, adec->mBase); + RegisterProc(adec->mBase); + } + else if (adec->mType == DT_CONST_FUNCTION) + { + adec->mOptFlags |= OPTF_VAR_USED; + AnalyzeProcedure(adec->mValue, adec); + RegisterCall(procDec, adec); + } + } + + exp = exp->mRight; + } + +} + +void GlobalOptimizer::AnalyzeGlobalVariable(Declaration* dec) +{ + while (dec->mType == DT_VARIABLE_REF) + dec = dec->mBase; + + if (!(dec->mOptFlags & OPTF_ANALYZED)) + { + dec->mOptFlags |= OPTF_ANALYZED; + + if (dec->mValue && dec->mValue->mType == EX_CONSTRUCT) + { + if (dec->mValue->mLeft->mLeft->mType == EX_CALL && (dec->mValue->mLeft->mLeft->mLeft->mDecValue->mFlags & DTF_CONSTEXPR)) + { + ConstexprInterpreter cinter(dec->mLocation, mErrors, dec->mSection); + dec->mValue = cinter.EvalConstructor(dec->mValue->mLeft->mLeft); + } + } + + mGlobalVariables.Push(dec); + + if (dec->mValue) + { + Analyze(dec->mValue, dec, false); + } + } +} + +void GlobalOptimizer::AnalyzeInit(Declaration* mdec) +{ + while (mdec) + { + if (mdec->mValue) + RegisterProc(Analyze(mdec->mValue, mdec, false)); + else if (mdec->mParams) + AnalyzeInit(mdec->mParams); + mdec = mdec->mNext; + } +} + + +void GlobalOptimizer::RegisterCall(Declaration* from, Declaration* to) +{ + if (from) + { + if (to->mType == DT_VARIABLE || to->mType == DT_ARGUMENT) + to = to->mBase; + + if (to->mType == DT_CONST_FUNCTION) + { + if (!(to->mOptFlags & OPTF_CALLED)) + { + to->mOptFlags |= OPTF_CALLED; + mCalledFunctions.Push(to); + } + + if (!(from->mOptFlags & OPTF_CALLING)) + { + from->mOptFlags |= OPTF_CALLING; + mCallingFunctions.Push(from); + } + } + else if (to->mType == DT_TYPE_FUNCTION) + { + if (!(from->mOptFlags & OPTF_CALLING)) + { + from->mOptFlags |= OPTF_CALLING; + mCallingFunctions.Push(from); + } + } + else if (to->mType == DT_TYPE_POINTER && to->mBase->mType == DT_TYPE_FUNCTION) + { + if (!(from->mOptFlags & OPTF_CALLING)) + { + from->mOptFlags |= OPTF_CALLING; + mCallingFunctions.Push(from); + } + } + } +} + +void GlobalOptimizer::RegisterProc(Declaration* to) +{ + if (to->mType == DT_CONST_FUNCTION) + { + if (to->mBase->mFlags & DTF_VIRTUAL) + { + + } + else if (!(to->mOptFlags & OPTF_FUNC_VARIABLE)) + { + to->mOptFlags |= OPTF_FUNC_VARIABLE; + mVariableFunctions.Push(to); + } + } +} + +static const uint32 ANAFL_LHS = (1U << 0); +static const uint32 ANAFL_RHS = (1U << 1); + +Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uint32 flags) +{ + Declaration* ldec, * rdec; + + switch (exp->mType) + { + case EX_ERROR: + case EX_VOID: + break; + case EX_CONSTANT: + if (exp->mDecValue->mType == DT_CONST_FUNCTION) + { + AnalyzeProcedure(exp->mDecValue->mValue, exp->mDecValue); + } + else if (exp->mDecValue->mType == DT_CONST_STRUCT) + { + AnalyzeInit(exp->mDecValue->mParams); + } + else if (exp->mDecValue->mType == DT_CONST_POINTER) + { + ldec = Analyze(exp->mDecValue->mValue, procDec, ANAFL_LHS | ANAFL_RHS); + RegisterProc(ldec); + } + else if (exp->mDecValue->mType == DT_CONST_ADDRESS) + { + } + else if (exp->mDecValue->mType == DT_CONST_ASSEMBLER) + { + AnalyzeAssembler(exp->mDecValue->mValue, procDec); + } + + return exp->mDecValue; + case EX_VARIABLE: + if ((exp->mDecValue->mFlags & DTF_STATIC) || (exp->mDecValue->mFlags & DTF_GLOBAL)) + { + Declaration* type = exp->mDecValue->mBase; + while (type->mType == DT_TYPE_ARRAY) + type = type->mBase; + + AnalyzeGlobalVariable(exp->mDecValue); + } + else + { + if (flags & ANAFL_RHS) + exp->mDecValue->mOptFlags |= OPTF_VAR_USED; + if (flags & ANAFL_LHS) + exp->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS; + } + return exp->mDecValue; + case EX_INITIALIZATION: + case EX_ASSIGNMENT: + ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | flags); + rdec = Analyze(exp->mRight, procDec, ANAFL_RHS); + RegisterProc(rdec); + return ldec; + + case EX_BINARY: + ldec = Analyze(exp->mLeft, procDec, flags); + rdec = Analyze(exp->mRight, procDec, flags); + return ldec; + + case EX_RELATIONAL: + ldec = Analyze(exp->mLeft, procDec, flags); + rdec = Analyze(exp->mRight, procDec, flags); + return TheBoolTypeDeclaration; + + case EX_PREINCDEC: + return Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS); + case EX_PREFIX: + if (exp->mToken == TK_BINARY_AND) + ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS); + else if (exp->mToken == TK_MUL) + { + ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS); + return exp->mDecType; + } + else + return Analyze(exp->mLeft, procDec, flags); + break; + case EX_POSTFIX: + break; + case EX_POSTINCDEC: + return Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS); + case EX_INDEX: + ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS); + if (ldec->mType == DT_VARIABLE || ldec->mType == DT_ARGUMENT) + ldec = ldec->mBase; + rdec = Analyze(exp->mRight, procDec, ANAFL_RHS); + if (ldec->mBase) + return ldec->mBase; + break; + case EX_QUALIFY: + Analyze(exp->mLeft, procDec, flags); + return exp->mDecValue->mBase; + case EX_DISPATCH: + Analyze(exp->mLeft, procDec, flags); + break; + case EX_VCALL: + exp->mType = EX_CALL; + exp->mLeft->mDecValue = exp->mLeft->mDecValue->mVTable; + // intentional fall through + case EX_CALL: + case EX_INLINE: + if (exp->mLeft->mType == EX_CONSTANT) + { + if (flags & ANAFL_RHS) + exp->mLeft->mDecValue->mOptFlags |= OPTF_VAR_USED; + if (flags & ANAFL_LHS) + exp->mLeft->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS; + } + + ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS); + if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue) + { + + } + else + { + RegisterCall(procDec, ldec); + } + + if (exp->mRight) + { + // Check for struct to struct forwarding + + Expression* rex = exp->mRight; + if (rex) + { + Expression* prex = exp; + while (rex && rex->mType == EX_LIST) + { + rex->mLeft = rex->mLeft->ConstantFold(mErrors, nullptr); + prex = rex; + rex = rex->mRight; + } + if (rex) + prex->mRight = rex->ConstantFold(mErrors, nullptr); + rex = exp->mRight; + } + + Declaration* pdec = ldec->mBase->mParams; + while (rex) + { + Expression* pex = rex->mType == EX_LIST ? rex->mLeft : rex; + + if (pdec) + { + if ((pdec->mFlags & DTF_FPARAM_UNUSED) && !pex->HasSideEffects() && pex->mType != EX_CONSTANT) + { + if (pdec->mBase->IsSimpleType()) + { + pex->mType = EX_CONSTANT; + pex->mLeft = nullptr; + pex->mRight = nullptr; + switch (pex->mDecType->mType) + { + case DT_TYPE_INTEGER: + case DT_TYPE_ENUM: + case DT_TYPE_BOOL: + pex->mDecValue = TheZeroIntegerConstDeclaration; + break; + case DT_TYPE_FLOAT: + pex->mDecValue = TheZeroFloatConstDeclaration; + break; + case DT_TYPE_POINTER: + pex->mDecValue = TheNullptrConstDeclaration; + break; + } + } + } + if (!(pdec->mFlags & DTF_FPARAM_UNUSED) && !(pdec->mOptFlags & OPTF_VAR_NOCONST)) + { + if (pex->mType == EX_CONSTANT && pdec->mBase->IsSimpleType()) + { + if (pdec->mOptFlags & OPTF_VAR_CONST) + { + if (!pex->mDecValue->IsSameValue(pdec->mValue->mDecValue)) + { + pdec->mOptFlags |= OPTF_VAR_NOCONST; + pdec->mOptFlags &= ~OPTF_VAR_CONST; + } + } + else + { + pdec->mValue = pex; + pdec->mOptFlags |= OPTF_VAR_CONST; + } + } + else + { + pdec->mOptFlags |= OPTF_VAR_NOCONST; + pdec->mOptFlags &= ~OPTF_VAR_CONST; + } + } + + if (pdec->mBase->mType == DT_TYPE_STRUCT && pdec->mBase->mCopyConstructor) + { + if (pdec->mBase->mMoveConstructor) + { + AnalyzeProcedure(pdec->mBase->mMoveConstructor->mValue, pdec->mBase->mMoveConstructor); + RegisterCall(procDec, pdec->mBase->mMoveConstructor); + } + AnalyzeProcedure(pdec->mBase->mCopyConstructor->mValue, pdec->mBase->mCopyConstructor); + RegisterCall(procDec, pdec->mBase->mCopyConstructor); + } + } + + if (pdec && (pdec->mFlags & DTF_FPARAM_UNUSED)) + RegisterProc(Analyze(pex, procDec, 0)); + else if (pdec && pdec->mBase->IsReference()) + RegisterProc(Analyze(pex, procDec, ANAFL_LHS | ANAFL_RHS)); + else + RegisterProc(Analyze(pex, procDec, ANAFL_RHS)); + + if (pdec) + pdec = pdec->mNext; + + if (rex->mType == EX_LIST) + rex = rex->mRight; + else + rex = nullptr; + } + } + break; + case EX_LIST: + case EX_COMMA: + { + RegisterProc(Analyze(exp->mLeft, procDec, 0)); + Declaration* dec = Analyze(exp->mRight, procDec, flags); + RegisterProc(dec); + return dec; + } + case EX_RETURN: + if (exp->mLeft) + { + exp->mLeft = exp->mLeft->ConstantFold(mErrors, nullptr); + + if (procDec->mOptFlags & OPTF_SINGLE_RETURN) + { + procDec->mOptFlags &= ~OPTF_SINGLE_RETURN; + procDec->mOptFlags |= OPTF_MULTI_RETURN; + } + else if (!(procDec->mOptFlags & OPTF_MULTI_RETURN)) + { + procDec->mOptFlags |= OPTF_SINGLE_RETURN; + procDec->mReturn = exp; + } + + if (procDec->mBase->mBase->IsReference()) + RegisterProc(Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS)); + else + RegisterProc(Analyze(exp->mLeft, procDec, ANAFL_RHS)); + + if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor) + { + if (procDec->mBase->mBase->mMoveConstructor) + { + AnalyzeProcedure(procDec->mBase->mBase->mMoveConstructor->mValue, procDec->mBase->mBase->mMoveConstructor); + RegisterCall(procDec, procDec->mBase->mBase->mMoveConstructor); + } + AnalyzeProcedure(procDec->mBase->mBase->mCopyConstructor->mValue, procDec->mBase->mBase->mCopyConstructor); + RegisterCall(procDec, procDec->mBase->mBase->mCopyConstructor); + } + } + break; + case EX_SEQUENCE: + do + { + if (exp->mType == EX_SEQUENCE) + { + if (exp->mLeft) + ldec = Analyze(exp->mLeft, procDec, 0); + exp = exp->mRight; + } + else + return Analyze(exp, procDec, 0); + + } while (exp); + break; + + case EX_SCOPE: + Analyze(exp->mLeft, procDec, 0); + break; + + case EX_CONSTRUCT: + if (exp->mLeft->mLeft) + Analyze(exp->mLeft->mLeft, procDec, 0); + if (exp->mLeft->mRight) + Analyze(exp->mLeft->mRight, procDec, 0); + if (exp->mRight) + return Analyze(exp->mRight, procDec, ANAFL_RHS); + break; + + case EX_CLEANUP: + Analyze(exp->mRight, procDec, 0); + return Analyze(exp->mLeft, procDec, flags); + + case EX_WHILE: + ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS); + rdec = Analyze(exp->mRight, procDec, 0); + break; + case EX_IF: + ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS); + rdec = Analyze(exp->mRight->mLeft, procDec, 0); + if (exp->mRight->mRight) + rdec = Analyze(exp->mRight->mRight, procDec, 0); + break; + case EX_ELSE: + break; + case EX_FOR: + if (exp->mLeft->mRight) + ldec = Analyze(exp->mLeft->mRight, procDec, 0); + if (exp->mLeft->mLeft->mLeft) + ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec, ANAFL_RHS); + rdec = Analyze(exp->mRight, procDec, 0); + if (exp->mLeft->mLeft->mRight) + ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, 0); + break; + case EX_DO: + ldec = Analyze(exp->mLeft, procDec, 0); + rdec = Analyze(exp->mRight, procDec, ANAFL_RHS); + break; + case EX_BREAK: + case EX_CONTINUE: + case EX_ASSUME: + break; + case EX_TYPE: + break; + case EX_TYPECAST: + return Analyze(exp->mLeft, procDec, ANAFL_RHS); + break; + case EX_LOGICAL_AND: + ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS); + rdec = Analyze(exp->mRight, procDec, ANAFL_RHS); + break; + case EX_LOGICAL_OR: + ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS); + rdec = Analyze(exp->mRight, procDec, ANAFL_RHS); + break; + case EX_LOGICAL_NOT: + ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS); + break; + case EX_ASSEMBLER: + AnalyzeAssembler(exp, procDec); + break; + case EX_UNDEFINED: + break; + case EX_SWITCH: + ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS); + exp = exp->mRight; + while (exp) + { + if (exp->mLeft->mRight) + rdec = Analyze(exp->mLeft->mRight, procDec, 0); + exp = exp->mRight; + } + break; + case EX_CASE: + break; + case EX_DEFAULT: + break; + case EX_CONDITIONAL: + ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS); + RegisterProc(Analyze(exp->mRight->mLeft, procDec, flags)); + RegisterProc(Analyze(exp->mRight->mRight, procDec, flags)); + break; + } + + return TheVoidTypeDeclaration; +} diff --git a/oscar64/GlobalOptimizer.h b/oscar64/GlobalOptimizer.h new file mode 100644 index 0000000..c03a1bc --- /dev/null +++ b/oscar64/GlobalOptimizer.h @@ -0,0 +1,43 @@ +#pragma once + +#include "Declaration.h" +#include "Linker.h" +#include "CompilerTypes.h" + +class GlobalOptimizer +{ +public: + GlobalOptimizer(Errors* errors, Linker* linker); + ~GlobalOptimizer(void); + + void Reset(void); + bool Optimize(void); + + void AnalyzeProcedure(Expression* exp, Declaration* dec); + void AnalyzeAssembler(Expression* exp, Declaration* dec); + void AnalyzeGlobalVariable(Declaration* dec); + + uint64 mCompilerOptions; + +protected: + Errors* mErrors; + Linker* mLinker; + + ExpandingArray mCalledFunctions, mCallingFunctions, mVariableFunctions, mFunctions; + ExpandingArray mGlobalVariables; + + void AnalyzeInit(Declaration* mdec); + Declaration* Analyze(Expression* exp, Declaration* procDec, uint32 flags); + + void RegisterCall(Declaration* from, Declaration* to); + void RegisterProc(Declaration* to); + + void RemoveValueReturn(Expression* exp); + bool CheckConstReturns(Expression*& exp); + bool CheckUnusedLocals(Expression*& exp); + void UndoParamReference(Expression* exp, Declaration* param); + bool ReplaceParamConst(Expression* exp, Declaration* param); + void PropagateCommas(Expression*& exp); + void PropagateParamCommas(Expression *& fexp, Expression*& exp); + +}; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 1599ca1..59a1115 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4379,7 +4379,12 @@ void InterOperand::Disassemble(FILE* file, InterCodeProcedure* proc) else if (mMemory == IM_GLOBAL) { if (mVarIndex < 0) - vname = ""; + { + if (mLinkerObject && mLinkerObject->mIdent) + vname = mLinkerObject->mIdent->mString; + else + vname = ""; + } else if (!proc->mModule->mGlobalVars[mVarIndex]) vname = "null"; else if (!proc->mModule->mGlobalVars[mVarIndex]->mIdent) @@ -4563,7 +4568,12 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc) else if (mConst.mMemory == IM_GLOBAL) { if (mConst.mVarIndex < 0) - vname = ""; + { + if (mConst.mLinkerObject && mConst.mLinkerObject->mIdent) + vname = mConst.mLinkerObject->mIdent->mString; + else + vname = ""; + } else if (!proc->mModule->mGlobalVars[mConst.mVarIndex]) vname = "null"; else if (!proc->mModule->mGlobalVars[mConst.mVarIndex]->mIdent) @@ -6415,7 +6425,10 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(bool initial, const Growin else { for (int i = 0; i < mLocalValueRange.Size(); i++) - mLocalValueRange[i].Merge(range[i], mLoopHead, initial); + { + if (this != from || IsTempModified(i)) + mLocalValueRange[i].Merge(range[i], mLoopHead, initial); + } for (int i = 0; i < mLocalParamValueRange.Size(); i++) mLocalParamValueRange[i].Merge(prange[i], mLoopHead, initial); } @@ -12262,6 +12275,45 @@ static InterInstruction * FindSourceInstruction(InterCodeBasicBlock* block, int } } +bool InterCodeBasicBlock::MoveLoopHeadCheckToTail(void) +{ + bool modified = false; + if (!mVisited) + { + mVisited = true; + + if (mLoopHead && mEntryBlocks.Size() == 2 && mInstructions.Size() == 2) + { + if (mInstructions[0]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[1]->mCode == IC_BRANCH && + mInstructions[1]->mSrc[0].mTemp == mInstructions[0]->mDst.mTemp) + { + if (mFalseJump != this && mTrueJump->mTrueJump == this && !mTrueJump->mFalseJump) + { + mTrueJump->mInstructions.SetSize(mTrueJump->mInstructions.Size() - 1); + mTrueJump->mInstructions.Push(mInstructions[0]->Clone()); + mTrueJump->mInstructions.Push(mInstructions[1]->Clone()); + mTrueJump->mTrueJump = mTrueJump; + mTrueJump->mFalseJump = mFalseJump; + mTrueJump->mEntryBlocks.Push(mTrueJump); + mTrueJump->mNumEntries++; + mFalseJump->mEntryBlocks.Push(mTrueJump); + mFalseJump->mNumEntries++; + mNumEntries--; + mEntryBlocks.Remove(mEntryBlocks.IndexOf(mTrueJump)); + modified = true; + } + } + } + + if (mTrueJump && mTrueJump->MoveLoopHeadCheckToTail()) + modified = true; + if (mFalseJump && mFalseJump->MoveLoopHeadCheckToTail()) + modified = true; + } + + return modified; +} + bool InterCodeBasicBlock::SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars) { bool modified = false; @@ -17606,6 +17658,12 @@ void InterCodeProcedure::Close(void) #endif +#if 1 + ResetVisited(); + mEntryBlock->MoveLoopHeadCheckToTail(); + +#endif + #if 1 BuildLoopPrefix(); DisassembleDebug("added dominators"); @@ -18110,7 +18168,7 @@ void InterCodeProcedure::Close(void) #if 1 case IC_CONSTANT: - if (ins->mConst.mType == IT_POINTER && (ins->mConst.mMemory == IM_FPARAM || ins->mConst.mMemory == IM_PARAM || ins->mConst.mMemory == IM_LOCAL)) + if (ins->mDst.mType == IT_POINTER && (ins->mConst.mMemory == IM_FPARAM || ins->mConst.mMemory == IM_PARAM || ins->mConst.mMemory == IM_LOCAL)) nother++; else nconst++; diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 9fcf1eb..8e8378a 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -543,6 +543,7 @@ public: void PeepholeOptimization(const GrowingVariableArray& staticVars); bool PeepholeReplaceOptimization(const GrowingVariableArray& staticVars); + bool MoveLoopHeadCheckToTail(void); void SingleBlockLoopOptimisation(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars); void SingleBlockLoopUnrolling(void); bool SingleBlockLoopPointerSplit(int& spareTemps); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 39ca8ee..c20bdbe 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1,4 +1,5 @@ #include "InterCodeGenerator.h" +#include "Constexpr.h" InterCodeGenerator::InterCodeGenerator(Errors* errors, Linker* linker) : mErrors(errors), mLinker(linker), mCompilerOptions(COPT_DEFAULT) @@ -1200,7 +1201,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro if (pdec) { - if (!(pdec->mFlags & DTF_FPARAM_CONST)) + if (!(pdec->mFlags & DTF_FPARAM_UNUSED)) nmapper.mParams[pdec->mVarIndex] = nindex; vdec->mVarIndex = nindex; @@ -1317,7 +1318,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro else wins->mSrc[1].mOperandSize = 2; - if (!pdec || !(pdec->mFlags & DTF_FPARAM_CONST)) + if (!pdec || !(pdec->mFlags & DTF_FPARAM_UNUSED)) block->Append(wins); } @@ -1444,7 +1445,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I ains->mConst.mMemory = IM_LOCAL; ains->mConst.mVarIndex = nindex; - if (!(pdec->mFlags & DTF_FPARAM_CONST)) + if (!(pdec->mFlags & DTF_FPARAM_UNUSED)) nmapper.mParams[pdec->mVarIndex] = nindex; vdec->mVarIndex = nindex; @@ -1463,7 +1464,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I wins->mSrc[1].mType = IT_POINTER; wins->mSrc[1].mTemp = ains->mDst.mTemp; wins->mSrc[1].mOperandSize = 2; - if (!(pdec->mFlags & DTF_FPARAM_CONST)) + if (!(pdec->mFlags & DTF_FPARAM_UNUSED)) block->Append(wins); pdec = pdec->mNext; @@ -1479,7 +1480,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I ains->mConst.mMemory = IM_LOCAL; ains->mConst.mVarIndex = nindex; - if (!(pdec->mFlags & DTF_FPARAM_CONST)) + if (!(pdec->mFlags & DTF_FPARAM_UNUSED)) nmapper.mParams[pdec->mVarIndex] = nindex; vdec->mVarIndex = nindex; @@ -1498,7 +1499,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I wins->mSrc[1].mType = IT_POINTER; wins->mSrc[1].mTemp = ains->mDst.mTemp; wins->mSrc[1].mOperandSize = 2; - if (!(pdec->mFlags & DTF_FPARAM_CONST)) + if (!(pdec->mFlags & DTF_FPARAM_UNUSED)) block->Append(wins); TranslateExpression(ftype, proc, block, fexp, destack, BranchTarget(), BranchTarget(), &nmapper); @@ -1620,6 +1621,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_SEQUENCE: case EX_LIST: + case EX_COMMA: if (exp->mLeft) vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); exp = exp->mRight; @@ -1948,7 +1950,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* int ref = 1; if (dec->mType == DT_ARGUMENT) { - if (dec->mFlags & DTF_FPARAM_CONST) + if (dec->mFlags & DTF_FPARAM_UNUSED) { ins->mConst.mMemory = IM_LOCAL; if (inlineMapper) @@ -3543,7 +3545,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (pdec) { - if (!pdec->mBase->CanAssign(vr.mType)) + if (!(pdec->mFlags & DTF_FPARAM_UNUSED) && !pdec->mBase->CanAssign(vr.mType)) { pdec->mBase->CanAssign(vr.mType); mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); @@ -3577,7 +3579,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else wins->mSrc[1].mOperandSize = 2; - if (!pdec || !(pdec->mFlags & DTF_FPARAM_CONST)) + if (!pdec || !(pdec->mFlags & DTF_FPARAM_UNUSED)) { if (ftype->mFlags & DTF_FASTCALL) defins.Push(wins); @@ -3702,7 +3704,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vdec->mType == DT_ARGUMENT) { vins->mConst.mVarIndex = vdec->mVarIndex; - if (vdec->mFlags & DTF_FPARAM_CONST) + if (vdec->mFlags & DTF_FPARAM_UNUSED) { vins->mConst.mMemory = IM_LOCAL; if (inlineMapper) @@ -5016,10 +5018,15 @@ void InterCodeGenerator::TranslateLogic(Declaration* procType, InterCodeProcedur default: { ExValue vr = TranslateExpression(procType, proc, block, exp, destack, BranchTarget(), BranchTarget(), inlineMapper); - vr = Dereference(proc, exp, block, vr); - if (!vr.mType->IsSimpleType()) - mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Not a valid condition value"); + if (vr.mType->mType == DT_TYPE_ARRAY) + vr = Dereference(proc, exp, block, vr, 1); + else + { + vr = Dereference(proc, exp, block, vr); + if (!vr.mType->IsSimpleType()) + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Not a valid condition value"); + } InterInstruction* ins = new InterInstruction(exp->mLocation, IC_BRANCH); ins->mSrc[0].mType = InterTypeOf(vr.mType); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 313b047..44d06d6 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -2,6 +2,7 @@ #include #include "Assembler.h" #include "MachineTypes.h" +#include "Constexpr.h" Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUnits) : mErrors(errors), mScanner(scanner), mCompilationUnits(compilationUnits) @@ -3455,13 +3456,10 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) // A simple constant is passed by const ref if (pex->mDecValue->mType == DT_CONST_INTEGER || pex->mDecValue->mType == DT_CONST_FLOAT || pex->mDecValue->mType == DT_CONST_POINTER || pex->mDecValue->mType == DT_CONST_ADDRESS) { - int nindex = mLocalIndex++; + if (pdec->mType == DT_TYPE_REFERENCE && !(pdec->mBase->mFlags & DTF_CONST)) + mErrors->Error(pex->mLocation, EERR_INCOMPATIBLE_TYPES, "Can't pass constant as non constante reference"); - Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); - - vdec->mVarIndex = nindex; - vdec->mBase = pdec->mBase->mBase; - vdec->mSize = pdec->mBase->mBase->mSize; + Declaration* vdec = AllocTempVar(pdec->mBase->mBase); Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE); vexp->mDecType = pdec->mBase->mBase; @@ -3771,7 +3769,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - ctdec->mFlags |= storageFlags & DTF_VIRTUAL; + ctdec->mFlags |= storageFlags & (DTF_REQUEST_INLINE | DTF_CONSTEXPR | DTF_VIRTUAL); cdec->mSection = mCodeSection; cdec->mBase->mFlags |= typeFlags; @@ -3821,7 +3819,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); - ctdec->mFlags |= storageFlags & DTF_VIRTUAL; + ctdec->mFlags |= storageFlags & (DTF_REQUEST_INLINE | DTF_CONSTEXPR | DTF_VIRTUAL); cdec->mSection = mCodeSection; cdec->mBase->mFlags |= typeFlags; @@ -3866,6 +3864,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec->mBase = ctdec; cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); + cdec->mFlags |= storageFlags & (DTF_INLINE | DTF_CONSTEXPR); cdec->mSection = mCodeSection; cdec->mBase->mFlags |= typeFlags; @@ -3964,7 +3963,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (cdec) { - cdec->mFlags |= storageFlags & DTF_REQUEST_INLINE; + cdec->mFlags |= storageFlags & (DTF_REQUEST_INLINE | DTF_CONSTEXPR); // Initializer list if (mScanner->mToken == TK_COLON) @@ -4042,7 +4041,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (bdec->mDestructor) { - bdec->mDestructor->mFlags |= storageFlags & DTF_REQUEST_INLINE; + bdec->mDestructor->mFlags |= storageFlags & (DTF_REQUEST_INLINE | DTF_CONSTEXPR); Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); bthis->mFlags |= DTF_CONST | DTF_DEFINED; @@ -4411,7 +4410,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { ParseVariableInit(ndec); } - else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mType == DT_VARIABLE && !pthis) + else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mType == DT_VARIABLE && !pthis && !(storageFlags & DTF_EXTERN)) { // Find default constructor @@ -4445,6 +4444,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex fexp->mLeft = cexp; fexp->mRight = texp; + if (bdec->mDefaultConstructor->mFlags & DTF_CONSTEXPR) + ndec->mSection = mDataSection; + Expression* dexp = nullptr; if (ndec->mBase->mDestructor) { diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index cb0e4db..4e6688d 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -205,6 +205,8 @@ int main2(int argc, const char** argv) compiler->mCompilerOptions |= COPT_OPTIMIZE_AUTO_ZEROPAGE; else if (arg[2] == 'p') compiler->mCompilerOptions |= COPT_OPTIMIZE_CONST_PARAMS; + else if (arg[2] == 'g') + compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL; } else if (arg[1] == 'e') { @@ -276,6 +278,11 @@ int main2(int argc, const char** argv) compiler->AddDefine(Ident::Unique("OSCAR_NATIVE_ALL"), "1"); } + + // REMOVE ME + // compiler->mCompilerOptions |= COPT_OPTIMIZE_GLOBAL; + // REMOVE ME + char basicStart[10]; strcpy_s(basicStart, "0x0801"); diff --git a/oscar64/oscar64.vcxproj b/oscar64/oscar64.vcxproj index a87fe01..56e143c 100644 --- a/oscar64/oscar64.vcxproj +++ b/oscar64/oscar64.vcxproj @@ -165,6 +165,7 @@ + @@ -192,6 +193,7 @@ + diff --git a/oscar64/oscar64.vcxproj.filters b/oscar64/oscar64.vcxproj.filters index cbde344..98e8470 100644 --- a/oscar64/oscar64.vcxproj.filters +++ b/oscar64/oscar64.vcxproj.filters @@ -81,6 +81,9 @@ Source Files + + Source Files + @@ -158,6 +161,9 @@ Header Files + + Header Files + From cda66f3ec44acc594a4ee7b4a7fd482ddd57697f Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 23 Sep 2023 18:01:28 +0200 Subject: [PATCH 127/169] Function pointer forwarding --- oscar64/GlobalOptimizer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/oscar64/GlobalOptimizer.cpp b/oscar64/GlobalOptimizer.cpp index a3b20a5..d934d35 100644 --- a/oscar64/GlobalOptimizer.cpp +++ b/oscar64/GlobalOptimizer.cpp @@ -700,14 +700,14 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin if (pdec) { - if ((pdec->mFlags & DTF_FPARAM_UNUSED) && !pex->HasSideEffects() && pex->mType != EX_CONSTANT) + if ((pdec->mFlags & DTF_FPARAM_UNUSED) && !pex->HasSideEffects())// && pex->mType != EX_CONSTANT) { if (pdec->mBase->IsSimpleType()) { pex->mType = EX_CONSTANT; pex->mLeft = nullptr; pex->mRight = nullptr; - switch (pex->mDecType->mType) + switch (pdec->mBase->mType) { case DT_TYPE_INTEGER: case DT_TYPE_ENUM: @@ -718,6 +718,7 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin pex->mDecValue = TheZeroFloatConstDeclaration; break; case DT_TYPE_POINTER: + case DT_TYPE_FUNCTION: pex->mDecValue = TheNullptrConstDeclaration; break; } From bba8931860d06eee7d13dc83f233b8e01d8e31a8 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 23 Sep 2023 18:52:26 +0200 Subject: [PATCH 128/169] Fix const node polution in const param optimization --- oscar64/Declaration.cpp | 10 ++++++++++ oscar64/Declaration.h | 1 + oscar64/GlobalOptimizer.cpp | 11 +++++------ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 2772d84..c1b1f35 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -967,6 +967,16 @@ Declaration* Declaration::BuildArrayPointer(void) return this; } +bool Declaration::IsNullConst(void) const +{ + if (mType == DT_CONST_INTEGER || mType == DT_CONST_ADDRESS) + return mInteger == 0; + else if (mType == DT_CONST_FLOAT) + return mNumber == 0; + else + return false; +} + Declaration* Declaration::ConstCast(Declaration* ntype) { if (ntype == mBase) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 1c8ab25..b390d2c 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -325,6 +325,7 @@ public: Declaration* BuildArrayPointer(void); Declaration* DeduceAuto(Declaration* dec); Declaration* ConstCast(Declaration* ntype); + bool IsNullConst(void) const; bool IsAuto(void) const; DecType ValueType(void) const; diff --git a/oscar64/GlobalOptimizer.cpp b/oscar64/GlobalOptimizer.cpp index d934d35..1f7034f 100644 --- a/oscar64/GlobalOptimizer.cpp +++ b/oscar64/GlobalOptimizer.cpp @@ -696,17 +696,15 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin Declaration* pdec = ldec->mBase->mParams; while (rex) { - Expression* pex = rex->mType == EX_LIST ? rex->mLeft : rex; + Expression *& pex(rex->mType == EX_LIST ? rex->mLeft : rex); if (pdec) { - if ((pdec->mFlags & DTF_FPARAM_UNUSED) && !pex->HasSideEffects())// && pex->mType != EX_CONSTANT) + if ((pdec->mFlags & DTF_FPARAM_UNUSED) && !pex->HasSideEffects() && (pex->mType != EX_CONSTANT || !pex->mDecValue->IsNullConst())) { if (pdec->mBase->IsSimpleType()) { - pex->mType = EX_CONSTANT; - pex->mLeft = nullptr; - pex->mRight = nullptr; + pex = new Expression(pex->mLocation, EX_CONSTANT); switch (pdec->mBase->mType) { case DT_TYPE_INTEGER: @@ -720,8 +718,9 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin case DT_TYPE_POINTER: case DT_TYPE_FUNCTION: pex->mDecValue = TheNullptrConstDeclaration; - break; + break; } + pex->mDecType = pdec->mBase; } } if (!(pdec->mFlags & DTF_FPARAM_UNUSED) && !(pdec->mOptFlags & OPTF_VAR_NOCONST)) From da29a8747710d41e1dbf7c28bdc79177a9836e71 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 24 Sep 2023 11:03:54 +0200 Subject: [PATCH 129/169] Fix address of array in const declaration to return correct pointer type --- include/c64/sprites.c | 16 ++++++++++++++++ include/c64/sprites.h | 4 ++++ oscar64/Declaration.cpp | 8 ++++++++ oscar64/Declaration.h | 1 + oscar64/Parser.cpp | 6 +----- 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/include/c64/sprites.c b/include/c64/sprites.c index e2902be..664648c 100644 --- a/include/c64/sprites.c +++ b/include/c64/sprites.c @@ -108,6 +108,22 @@ void spr_color(char sp, char color) vic.spr_color[sp] = color; } +void spr_expand(char sp, bool xexpand, bool yexpand) +{ + __assume (sp < 8); + + char m = 1 << sp; + + if (xexpand) + vic.spr_expand_x |= m; + else + vic.spr_expand_x &= ~m; + + if (yexpand) + vic.spr_expand_y |= m; + else + vic.spr_expand_y &= ~m; +} static char vspriteYLow[VSPRITES_MAX], vspriteXLow[VSPRITES_MAX], vspriteXHigh[VSPRITES_MAX]; static char vspriteImage[VSPRITES_MAX], vspriteColor[VSPRITES_MAX]; diff --git a/include/c64/sprites.h b/include/c64/sprites.h index 69f7cee..a676614 100644 --- a/include/c64/sprites.h +++ b/include/c64/sprites.h @@ -39,6 +39,10 @@ inline void spr_image(char sp, char image); inline void spr_color(char sp, char color); +// change the image of a sprite + +inline void spr_expand(char sp, bool xexpand, bool yexpand); + // The virtual sprite system works with the rasterirq library to multiplex // 16 virtual sprites onto the actual eight hardware sprites. It uses the slots // 0 to 8 of the rasterirq library to switch the sprites mid screen. The diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index c1b1f35..6336f1e 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -967,6 +967,14 @@ Declaration* Declaration::BuildArrayPointer(void) return this; } +Declaration* Declaration::BuildAddressOfPointer(void) +{ + if (mType == DT_TYPE_ARRAY) + return BuildArrayPointer(); + else + return BuildPointer(mLocation); +} + bool Declaration::IsNullConst(void) const { if (mType == DT_CONST_INTEGER || mType == DT_CONST_ADDRESS) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index b390d2c..c4da608 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -323,6 +323,7 @@ public: Declaration* BuildConstRValueRef(const Location& loc); Declaration* NonRefBase(void); Declaration* BuildArrayPointer(void); + Declaration* BuildAddressOfPointer(void); Declaration* DeduceAuto(Declaration* dec); Declaration* ConstCast(Declaration* ntype); bool IsNullConst(void) const; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 44d06d6..9a6643a 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -7010,11 +7010,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs) } else if (nexp->mToken == TK_BINARY_AND) { - Declaration* pdec = new Declaration(nexp->mLocation, DT_TYPE_POINTER); - pdec->mBase = nexp->mLeft->mDecType; - pdec->mSize = 2; - pdec->mFlags |= DTF_DEFINED; - nexp->mDecType = pdec; + nexp->mDecType = nexp->mLeft->mDecType->BuildAddressOfPointer(); } else if (nexp->mToken == TK_BANKOF) { From 619c4f8962e8a42bc619cfc437951cba80a18854 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 24 Sep 2023 22:22:48 +0200 Subject: [PATCH 130/169] Join consecutive functions in linker --- README.md | 2 +- include/c64/sprites.c | 2 +- oscar64/Linker.cpp | 55 +++++++++++++++++++++++++++++++++++++++---- oscar64/Linker.h | 4 +++- 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d0d1876..35cf7cc 100644 --- a/README.md +++ b/README.md @@ -222,7 +222,7 @@ Each type has up to five attributes: * size : size of a variable of this type in bytes * type : base type or composition method for this type * int : signed Integer - * unit : unsigned integer + * uint : unsigned integer * bool : boolean value * enum : enumeration * ptr : pointer to diff --git a/include/c64/sprites.c b/include/c64/sprites.c index 664648c..6da4307 100644 --- a/include/c64/sprites.c +++ b/include/c64/sprites.c @@ -1,7 +1,7 @@ #include "sprites.h" #include "rasterirq.h" -static char * vspriteScreen; +static volatile char * vspriteScreen; void spr_init(char * screen) diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index 8bc60d5..092dedf 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -4,7 +4,7 @@ #include "CompilerTypes.h" LinkerRegion::LinkerRegion(void) - : mSections(nullptr), mFreeChunks(FreeChunk{ 0, 0 } ) + : mSections(nullptr), mFreeChunks(FreeChunk{ 0, 0 } ), mLastObject(nullptr) {} LinkerSection::LinkerSection(void) @@ -413,7 +413,31 @@ void Linker::ReferenceObject(LinkerObject* obj) } } -bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj) +static bool Forwards(LinkerObject* pobj, LinkerObject* lobj) +{ + if (lobj->mAlignment == 1 && pobj && lobj->mType == LOT_NATIVE_CODE && pobj->mType == LOT_NATIVE_CODE) + { + if (pobj->mSize >= 3 && pobj->mData[pobj->mSize - 3] == 0x4c && pobj->mReferences.Size() > 0) + { + int i = 0; + while (i < pobj->mReferences.Size() && pobj->mReferences[i]->mOffset != pobj->mSize - 2) + i++; + if (i < pobj->mReferences.Size() && pobj->mReferences[i]->mRefObject == lobj && pobj->mReferences[i]->mRefOffset == 0) + { + printf("Direct %s -> %s\n", pobj->mIdent->mString, lobj->mIdent->mString); + + pobj->mReferences[i]->mFlags = 0; + pobj->mSize -= 3; + + return true; + } + } + } + + return false; +} + +bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge) { int i = 0; while (i < mFreeChunks.Size()) @@ -425,6 +449,13 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj) ; else if (end <= mFreeChunks[i].mEnd) { + // Check if directly follows an object that jumps to this new object + if (merge && Forwards(mFreeChunks[i].mLastObject, lobj)) + { + start -= 3; + end -= 3; + } + lobj->mFlags |= LOBJF_PLACED; lobj->mAddress = start; lobj->mRefAddress = start + mReloc; @@ -435,7 +466,10 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj) if (end == mFreeChunks[i].mEnd) mFreeChunks.Remove(i); else + { mFreeChunks[i].mStart = end; + mFreeChunks[i].mLastObject = lobj; + } } else if (end == mFreeChunks[i].mEnd) { @@ -443,7 +477,7 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj) } else { - mFreeChunks.Insert(i + 1, FreeChunk{ end, mFreeChunks[i].mEnd } ); + mFreeChunks.Insert(i + 1, FreeChunk{ end, mFreeChunks[i].mEnd, lobj } ); mFreeChunks[i].mEnd = start; } @@ -463,16 +497,27 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj) if (end <= mEnd) { + // Check if directly follows an object that jumps to this new object + if (merge && Forwards(mLastObject, lobj)) + { + start -= 3; + end -= 3; + mLastObject = nullptr; + } + lobj->mFlags |= LOBJF_PLACED; lobj->mAddress = start; lobj->mRefAddress = start + mReloc; lobj->mRegion = this; + #if 1 if (start != mStart + mUsed) - mFreeChunks.Push( FreeChunk{ mStart + mUsed, start } ); + mFreeChunks.Push( FreeChunk{ mStart + mUsed, start, mLastObject } ); #endif mUsed = end - mStart; + mLastObject = lobj; + return true; } @@ -538,7 +583,7 @@ void Linker::Link(void) for (int k = 0; k < lsec->mObjects.Size(); k++) { LinkerObject* lobj = lsec->mObjects[k]; - if ((lobj->mFlags & LOBJF_REFERENCED) && !(lobj->mFlags & LOBJF_PLACED) && lrgn->Allocate(this, lobj)) + if ((lobj->mFlags & LOBJF_REFERENCED) && !(lobj->mFlags & LOBJF_PLACED) && lrgn->Allocate(this, lobj, mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)) { if (lobj->mIdent && lobj->mIdent->mString && (mCompilerOptions & COPT_VERBOSE2)) printf("Placed object <%s> $%04x - $%04x\n", lobj->mIdent->mString, lobj->mAddress, lobj->mAddress + lobj->mSize); diff --git a/oscar64/Linker.h b/oscar64/Linker.h index c87a689..c9d9348 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -90,11 +90,13 @@ public: struct FreeChunk { int mStart, mEnd; + LinkerObject* mLastObject; }; GrowingArray mFreeChunks; + LinkerObject * mLastObject; - bool Allocate(Linker * linker, LinkerObject* obj); + bool Allocate(Linker * linker, LinkerObject* obj, bool merge); void PlaceStackSection(LinkerSection* stackSection, LinkerSection* section); }; From d93cffaa300da5e7f5a2e26ebc472d0a03545799 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 25 Sep 2023 19:18:22 +0200 Subject: [PATCH 131/169] Fix const pointers in vic_setmode --- include/c64/vic.c | 2 +- include/c64/vic.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/c64/vic.c b/include/c64/vic.c index 28d6827..43894a1 100644 --- a/include/c64/vic.c +++ b/include/c64/vic.c @@ -21,7 +21,7 @@ int vic_sprgetx(byte s) return vic.spr_pos[s].x | ((vic.spr_msbx & (1 << s)) ? 256 : 0); } -void vic_setmode(VicMode mode, char * text, char * font) +void vic_setmode(VicMode mode, const char * text, const char * font) { switch (mode) { diff --git a/include/c64/vic.h b/include/c64/vic.h index 718ae88..430de53 100644 --- a/include/c64/vic.h +++ b/include/c64/vic.h @@ -91,7 +91,7 @@ enum VicMode // set the display mode and base address. This will also // adapt the bank. -void vic_setmode(VicMode mode, char * text, char * font); +void vic_setmode(VicMode mode, const char * text, const char * font); // put a sprite at the given x/y location, taking care of the // x MSB From e6b865130ac24b9817e4497d2aa6ea4e80828909 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 25 Sep 2023 19:20:30 +0200 Subject: [PATCH 132/169] Fix volatile in vsprites --- include/c64/sprites.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/c64/sprites.c b/include/c64/sprites.c index 6da4307..912d3da 100644 --- a/include/c64/sprites.c +++ b/include/c64/sprites.c @@ -233,7 +233,7 @@ void vspr_sort(void) void vspr_update(void) { char xymask = 0; - char * vsprs = vspriteScreen; + volatile char * vsprs = vspriteScreen; #pragma unroll(full) for(char ui=0; ui<8; ui++) From c98ff08f563c2f7c8ee3c4b6018bb2f274c57824 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 27 Sep 2023 18:53:35 +0200 Subject: [PATCH 133/169] Fix infinite loop eating the entry block --- oscar64/NativeCodeGenerator.cpp | 9 ++++++++- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 6 +++--- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index a6f8280..de61ba9 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -12762,7 +12762,7 @@ bool NativeCodeBasicBlock::FindSameBlocks(NativeCodeProcedure* nproc) { mVisited = true; - if (!mSameBlock) + if (!mSameBlock && this != mProc->mEntryBlock) { for (int i = 0; i < nproc->mBlocks.Size(); i++) { @@ -40512,6 +40512,9 @@ void NativeCodeBasicBlock::CheckBlocks(bool sequence) if (!mVisited) { mVisited = true; + + assert(this != mProc->mEntryBlock || mNumEntries < 2); + CheckLive(); if (sequence) @@ -41823,6 +41826,7 @@ void NativeCodeProcedure::Optimize(void) RebuildEntry(); + assert(mEntryBlock->mNumEntries < 2); #if 1 if (step > 3) { @@ -41834,6 +41838,8 @@ void NativeCodeProcedure::Optimize(void) } } #endif + RebuildEntry(); + assert(mEntryBlock->mNumEntries < 2); if (step == 4) { @@ -41848,6 +41854,7 @@ void NativeCodeProcedure::Optimize(void) } RebuildEntry(); + assert(mEntryBlock->mNumEntries < 2); #if 1 if (step > 3) diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 4e6688d..5c3d405 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.26.219"); + strcpy(strProductVersion, "1.26.220"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index bd4392e..8363333 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,26,219,0 - PRODUCTVERSION 1,26,219,0 + FILEVERSION 1,26,220,0 + PRODUCTVERSION 1,26,220,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.26.219.0" + VALUE "FileVersion", "1.26.220.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.26.219.0" + VALUE "ProductVersion", "1.26.220.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index abcda9f..843e433 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5686,15 +5686,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{CBCAE13D-B17A-44B2-8FC3-38EE53B02C31}" - "PackageCode" = "8:{75E5F5B4-AE17-4214-ADB6-18D9177E8E1B}" + "ProductCode" = "8:{532AC6ED-3D25-48DC-91FD-DBE96AF0026F}" + "PackageCode" = "8:{9C57F5C1-1D7C-4915-8DD9-DFE81E950DCA}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.26.219" + "ProductVersion" = "8:1.26.220" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 078d14861ccf5b06b1351e5d4a013e36a51fc502 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 30 Sep 2023 18:10:03 +0200 Subject: [PATCH 134/169] Some data path optimizations --- oscar64/InterCode.cpp | 28 ++++++++----- oscar64/NativeCodeGenerator.cpp | 73 +++++++++++++++++++++++++++++++-- oscar64/NativeCodeGenerator.h | 2 +- 3 files changed, 88 insertions(+), 15 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 59a1115..74233f8 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -6820,18 +6820,26 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray case IA_EXT8TO16U: case IA_EXT8TO32U: vr = ins->mSrc[0].mRange; - if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < 0 || vr.mMaxValue > 255 || vr.mMinValue < 0 || - vr.mMinState != IntegerValueRange::S_BOUND) + if (vr.mMaxState != IntegerValueRange::S_UNKNOWN && vr.mMinState == IntegerValueRange::S_BOUND && vr.mMinValue > 0) { vr.mMaxState = IntegerValueRange::S_BOUND; vr.mMaxValue = 255; - vr.mMinState = IntegerValueRange::S_BOUND; - vr.mMinValue = 0; } - if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < 0 || vr.mMinValue > 255) + else { - vr.mMinState = IntegerValueRange::S_BOUND; - vr.mMinValue = 0; + if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < 0 || vr.mMaxValue > 255 || vr.mMinValue < 0 || + vr.mMinState != IntegerValueRange::S_BOUND) + { + vr.mMaxState = IntegerValueRange::S_BOUND; + vr.mMaxValue = 255; + vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMinValue = 0; + } + if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < 0 || vr.mMinValue > 255) + { + vr.mMinState = IntegerValueRange::S_BOUND; + vr.mMinValue = 0; + } } break; case IA_EXT16TO32U: @@ -7700,7 +7708,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray if (s0 < 0) { mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); - mTrueValueRange[s1].LimitMin(0); + mTrueValueRange[s1].LimitMinWeak(0); if (mFalseValueRange[s1].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[s1].mMinValue >= 0) { @@ -7710,7 +7718,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray else if (mInstructions[sz - 2]->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND) { mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue - 1); - mTrueValueRange[s1].LimitMin(0); + mTrueValueRange[s1].LimitMinWeak(0); if (mFalseValueRange[s1].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[s1].mMinValue >= 0) { @@ -17276,7 +17284,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "test"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index de61ba9..59faa84 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -12791,6 +12791,16 @@ bool NativeCodeBasicBlock::MergeSameBlocks(NativeCodeProcedure* nproc) { mVisited = true; + if (this == mProc->mEntryBlock && mSameBlock && mIns.Size() > 1) + { + mTrueJump = mSameBlock; + mFalseJump = nullptr; + mBranch = ASMIT_JMP; + mIns.SetSize(0); + changed = true; + mSameBlock = nullptr; + } + if (mTrueJump && mTrueJump->mSameBlock) { mTrueJump = mTrueJump->mSameBlock; @@ -15796,9 +15806,9 @@ bool NativeCodeBasicBlock::CanHoistStore(const NativeCodeInstruction& ains) cons return true; } -bool NativeCodeBasicBlock::CanBytepassLoad(const NativeCodeInstruction& ains) const +bool NativeCodeBasicBlock::CanBytepassLoad(const NativeCodeInstruction& ains, int from) const { - for (int i = 0; i < mIns.Size(); i++) + for (int i = from; i < mIns.Size(); i++) { if (ains.MayBeChangedOnAddress(mIns[i])) return false; @@ -15849,7 +15859,7 @@ bool NativeCodeBasicBlock::SimplifyDiamond(NativeCodeProcedure* proc) sz--; if (sz >= 0 && mIns[sz].mType == ASMIT_LDY && (mIns[sz].mMode == ASMIM_ZERO_PAGE || mIns[sz].mMode == ASMIM_ABSOLUTE) && !(mIns[sz].mLive & LIVE_CPU_REG_Z)) { - if (mTrueJump->CanBytepassLoad(mIns[sz]) && mFalseJump->CanBytepassLoad(mIns[sz])) + if (this->CanBytepassLoad(mIns[sz], sz + 1) && mTrueJump->CanBytepassLoad(mIns[sz]) && mFalseJump->CanBytepassLoad(mIns[sz])) { mTrueJump->mTrueJump->mIns.Insert(0, NativeCodeInstruction(mIns[sz].mIns, ASMIT_LDY, mIns[sz])); changed = true; @@ -15864,7 +15874,7 @@ bool NativeCodeBasicBlock::SimplifyDiamond(NativeCodeProcedure* proc) sz--; if (sz >= 0 && mIns[sz].mType == ASMIT_LDX && (mIns[sz].mMode == ASMIM_ZERO_PAGE || mIns[sz].mMode == ASMIM_ABSOLUTE) && !(mIns[sz].mLive & LIVE_CPU_REG_Z)) { - if (mTrueJump->CanBytepassLoad(mIns[sz]) && mFalseJump->CanBytepassLoad(mIns[sz])) + if (this->CanBytepassLoad(mIns[sz], sz + 1) && mTrueJump->CanBytepassLoad(mIns[sz]) && mFalseJump->CanBytepassLoad(mIns[sz])) { mTrueJump->mTrueJump->mIns.Insert(0, NativeCodeInstruction(mIns[sz].mIns, ASMIT_LDX, mIns[sz])); changed = true; @@ -17535,6 +17545,34 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) } + if (mIns.Size() >= 2 && mFalseJump && mBranch == ASMIT_BMI) + { + int sz = mIns.Size(); + if (mIns[sz - 2].mType == ASMIT_LDA && mIns[sz - 2].mMode == ASMIM_IMMEDIATE && mIns[sz - 2].mAddress == 0 && + mIns[sz - 1].mType == ASMIT_SBC && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && mIns[sz - 1].mAddress == 0) + { + if (mExitRequiredRegs[CPU_REG_Z]) + { + if (mFalseJump->mIns.Size() == 0 && mFalseJump->mBranch == ASMIT_BNE) + { + mFalseJump = mFalseJump->mFalseJump; + changed = true; + } + else if (mFalseJump->mIns.Size() == 0 && mFalseJump->mBranch == ASMIT_BEQ) + { + mFalseJump = mFalseJump->mTrueJump; + changed = true; + } + } + else if (!mExitRequiredRegs[CPU_REG_A]) + { + mBranch = ASMIT_BCC; + mIns.SetSize(sz - 2); + changed = true; + } + } + } + #if 1 if (mIns.Size() >= 1 && mFalseJump) { @@ -38685,6 +38723,33 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED; progress = true; } +#if 1 + else if ( + mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) && + (mIns[i + 1].mType == ASMIT_TAY || mIns[i + 1].mType == ASMIT_TAX) && + mIns[i + 2].mType == ASMIT_CLC && + mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && (mIns[i + 3].mAddress == 0xff || mIns[i + 3].mAddress == 0x01) && + mIns[i + 4].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 4]) && !(mIns[i + 4].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) + { + if (mIns[i + 1].mType == ASMIT_TAY) + { + mIns[i + 0].mType = ASMIT_LDY; mIns[i + 0].mLive |= LIVE_CPU_REG_Y; + } + else + { + mIns[i + 0].mType = ASMIT_LDX; mIns[i + 0].mLive |= LIVE_CPU_REG_X; + } + + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED; + if (mIns[i + 3].mAddress == 0x01) + mIns[i + 4].mType = ASMIT_INC; + else + mIns[i + 4].mType = ASMIT_DEC; + progress = true; + } +#endif #endif } #endif diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index eb72c46..61a3687 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -575,7 +575,7 @@ public: bool SimplifyLoopEnd(NativeCodeProcedure* proc); bool CrossBlockStoreLoadBypass(NativeCodeProcedure* proc); - bool CanBytepassLoad(const NativeCodeInstruction& ains) const; + bool CanBytepassLoad(const NativeCodeInstruction& ains, int from = 0) const; bool CanHoistStore(const NativeCodeInstruction& ains) const; bool MoveAccuTrainUp(int at, int end); From 235437be561bce07f569771364c50d14d9ac435a Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 30 Sep 2023 22:22:33 +0200 Subject: [PATCH 135/169] Fix absolute address high byte propagation error --- oscar64/NativeCodeGenerator.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 59faa84..51a9911 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -23597,17 +23597,17 @@ bool NativeCodeBasicBlock::PatchGlobalAddressSumYPointer(const NativeCodeBasicBl int naddr = address + mIns[at + 2].mAddress + 256 * mIns[at + 5].mAddress; mIns[at + 2].mType = ASMIT_ADC; - mIns[at + 2].mMode = ASMIM_IMMEDIATE_ADDRESS; + mIns[at + 2].mMode = lobj ? ASMIM_IMMEDIATE_ADDRESS : ASMIM_IMMEDIATE; mIns[at + 2].mLinkerObject = lobj; - mIns[at + 2].mAddress = naddr; + mIns[at + 2].mAddress = lobj ? naddr : naddr & 0xff; mIns[at + 2].mFlags = NCIF_LOWER; mIns[at + 4].mMode = ASMIM_IMMEDIATE; mIns[at + 4].mAddress = 0; - mIns[at + 5].mMode = ASMIM_IMMEDIATE_ADDRESS; + mIns[at + 5].mMode = lobj ? ASMIM_IMMEDIATE_ADDRESS : ASMIM_IMMEDIATE;; mIns[at + 5].mLinkerObject = lobj; - mIns[at + 5].mAddress = naddr; + mIns[at + 5].mAddress = lobj ? naddr : naddr >> 8; mIns[at + 5].mFlags = NCIF_UPPER; at += 6; @@ -27746,6 +27746,11 @@ bool NativeCodeBasicBlock::MoveCLCLoadAddZPStoreDown(int at) mIns.Insert(j, mIns[at + 1]); // LDA mIns.Insert(j, mIns[at + 0]); // CLC + mIns[j + 0].mLive |= mIns[j - 1].mLive; + mIns[j + 1].mLive |= mIns[j - 1].mLive; + mIns[j + 2].mLive |= mIns[j - 1].mLive; + mIns[j + 3].mLive |= mIns[j - 1].mLive; + mIns[at + 0].mType = ASMIT_NOP; mIns[at + 0].mMode = ASMIM_IMPLIED; mIns[at + 1].mType = ASMIT_NOP; mIns[at + 1].mMode = ASMIM_IMPLIED; mIns[at + 2].mType = ASMIT_NOP; mIns[at + 2].mMode = ASMIM_IMPLIED; @@ -41269,7 +41274,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "dungeon_rand_path"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41958,7 +41963,6 @@ void NativeCodeProcedure::Optimize(void) } #endif - int t = 0; #if 1 do From c53a288d0bb58368f174f2f0f2586703d9a911af Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 1 Oct 2023 21:48:09 +0200 Subject: [PATCH 136/169] Optimize index chains --- include/c64/iecbus.c | 22 +++++++++++ include/c64/iecbus.h | 5 +++ oscar64/NativeCodeGenerator.cpp | 67 +++++++++++++++++++++++++++++++++ oscar64/NativeCodeGenerator.h | 2 + 4 files changed, 96 insertions(+) diff --git a/include/c64/iecbus.c b/include/c64/iecbus.c index 1a93755..aef034a 100644 --- a/include/c64/iecbus.c +++ b/include/c64/iecbus.c @@ -233,6 +233,28 @@ void iec_close(char dev, char sec) iec_unlisten(); } +int iec_write_bytes(const char * data, int num) +{ + for(int i=0; i= 4) + { + int si = at - 4; + + while (si >= 0) + { + if (mIns[si + 3].ReferencesZeroPage(mIns[at].mAddress)) + { + if (mIns[si + 0].mType == ASMIT_CLC && + mIns[si + 1].mType == ASMIT_LDA && mIns[si + 1].mMode == ASMIM_ZERO_PAGE && + mIns[si + 2].mType == ASMIT_ADC && mIns[si + 2].mMode == ASMIM_IMMEDIATE && (mIns[si + 2].mAddress >= 0 && mIns[si + 2].mAddress <= 4) && + mIns[si + 3].mType == ASMIT_STA && !(mIns[si + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) + { + int i = si + 4; + while (i < at && !mIns[i].ChangesZeroPage(mIns[si + 1].mAddress)) + i++; + if (i != at) + return false; + + AsmInsType t = mIns[at].mType == ASMIT_LDX ? ASMIT_INX : ASMIT_INY; + + mIns[at].mAddress = mIns[si + 1].mAddress; + for (int i = 0; i < mIns[si + 2].mAddress; i++) + mIns.Insert(at + 1, NativeCodeInstruction(mIns[si].mIns, t)); + + mIns[si + 0].mType = ASMIT_NOP; mIns[si + 0].mMode = ASMIM_IMPLIED; + mIns[si + 1].mType = ASMIT_NOP; mIns[si + 1].mMode = ASMIM_IMPLIED; + mIns[si + 2].mType = ASMIT_NOP; mIns[si + 2].mMode = ASMIM_IMPLIED; + mIns[si + 3].mType = ASMIT_NOP; mIns[si + 3].mMode = ASMIM_IMPLIED; + + return true; + } + else + return false; + } + + si--; + } + + } + + return false; +} + bool NativeCodeBasicBlock::CombineImmediateADCUp(int at) { int addr = mIns[at].mAddress; @@ -34379,6 +34434,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass } CheckLive(); +#endif + +#if 1 + for (int i = 0; i < mIns.Size(); i++) + { + if ((mIns[i + 0].mType == ASMIT_LDX || mIns[i + 0].mType == ASMIT_LDY) && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 0].mLive & LIVE_MEM)) + { + if (MoveSimpleADCToINCDECDown(i)) + changed = true; + } + } + #endif // diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 61a3687..aab4daf 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -442,6 +442,8 @@ public: bool MoveTXADCDown(int at); bool FoldShiftORAIntoLoadImmUp(int at); + bool MoveSimpleADCToINCDECDown(int at); + bool MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction & lins, const NativeCodeInstruction & sins); bool ShortcutCrossBlockMoves(NativeCodeProcedure* proc); From 4e6769d81c795862ffd61a36ae1aa87c91b042f9 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:43:58 +0200 Subject: [PATCH 137/169] Add header file --- include/new | 11 +++++++++++ include/opp/vector.h | 1 + oscar64/Scanner.cpp | 7 +++++++ oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 32 +++++++++++++++++++++++++++++--- 6 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 include/new diff --git a/include/new b/include/new new file mode 100644 index 0000000..24cda01 --- /dev/null +++ b/include/new @@ -0,0 +1,11 @@ +#pragma once + +#include "stddef.h" + +namespace std +{ + + void * operator new(size_t size); + void * operator new(void * ptr, size_t size); + +} diff --git a/include/opp/vector.h b/include/opp/vector.h index f1fa8dd..57f07d8 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -1,6 +1,7 @@ #ifndef OPP_VECTOR_H #define OPP_VECTOR_H +#include #include #include diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 472c04e..5393807 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1722,6 +1722,13 @@ void Scanner::NextRawToken(void) mTokenIdent = Ident::Unique("operator->"); break; + case TK_NEW: + mTokenIdent = Ident::Unique("operator-new"); + break; + case TK_DELETE: + mTokenIdent = Ident::Unique("operator-delete"); + break; + default: // dirty little hack to implement token preview, got to fix // this with an infinit preview sequence at one point diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 5c3d405..b64e26d 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.26.220"); + strcpy(strProductVersion, "1.26.221"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 8363333..c3ab1c5 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,26,220,0 - PRODUCTVERSION 1,26,220,0 + FILEVERSION 1,26,221,0 + PRODUCTVERSION 1,26,221,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.26.220.0" + VALUE "FileVersion", "1.26.221.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.26.220.0" + VALUE "ProductVersion", "1.26.221.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 843e433..a772017 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -202,6 +202,12 @@ } "Entry" { + "MsmKey" = "8:_26E38AB4F85C4C9DB284803C4A3473F3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_29ED5D9B606D45DA80CFF329A7643DC8" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1933,6 +1939,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_26E38AB4F85C4C9DB284803C4A3473F3" + { + "SourcePath" = "8:..\\include\\new" + "TargetName" = "8:new" + "Tag" = "8:" + "Folder" = "8:_7C0D28C244F14A21B5F72213BBE59B6F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_29ED5D9B606D45DA80CFF329A7643DC8" { "SourcePath" = "8:..\\samples\\kernalio\\diskdir.c" @@ -5686,15 +5712,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{532AC6ED-3D25-48DC-91FD-DBE96AF0026F}" - "PackageCode" = "8:{9C57F5C1-1D7C-4915-8DD9-DFE81E950DCA}" + "ProductCode" = "8:{76114EBF-11A9-4AB2-9F9C-04180A284C4B}" + "PackageCode" = "8:{A38D2D44-B7EB-49A4-ACA8-8974DC5EB905}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.26.220" + "ProductVersion" = "8:1.26.221" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 313b6dcf939510494377ab657ac8ffe32dfa5e28 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 3 Oct 2023 12:47:24 +0200 Subject: [PATCH 138/169] Fix struct assign in constexpr --- oscar64/Constexpr.cpp | 11 ++++++++--- oscar64/Parser.cpp | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index 6f52b05..a0de135 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -418,8 +418,13 @@ void ConstexprInterpreter::Value::Assign(const Value& v) case DT_TYPE_STRUCT: case DT_TYPE_UNION: case DT_TYPE_ARRAY: - memcpy(GetAddr(), v.GetAddr(), mDecType->mSize); - break; + { + const ConstexprInterpreter::ValueItem* sp = v.GetAddr(); + ConstexprInterpreter::ValueItem* dp = GetAddr(); + + for (int i = 0; i < mDecType->mSize; i++) + dp[i] = sp[i]; + } break; case DT_TYPE_POINTER: PutPtr(v.GetPtr()); break; @@ -1260,7 +1265,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) mErrors->Error(exp->mLocation, EERR_INVALID_CONSTEXPR, "Invalid constexpr"); - return exp; + return Value(); } ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 9a6643a..5650e0d 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -6301,6 +6301,8 @@ Expression* Parser::ParsePostfixExpression(bool lhs) if (exp->mDecType->ValueType() == DT_TYPE_STRUCT) { nexp = CheckOperatorOverload(nexp); + if (nexp->mType == EX_INDEX) + mErrors->Error(mScanner->mLocation, EERR_INVALID_INDEX, "No indexing operator found"); } else if (exp->mDecType->mType == DT_TYPE_ARRAY || exp->mDecType->mType == DT_TYPE_POINTER) { From e084035a713e3f4f897d36ca7562cabd8396d63a Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 3 Oct 2023 15:21:33 +0200 Subject: [PATCH 139/169] Common sub expression across if --- oscar64/InterCode.cpp | 125 +++++++++++++++++++++++++++++++++++++++++- oscar64/InterCode.h | 3 + 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 74233f8..50a1068 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -10902,6 +10902,91 @@ static bool CanMoveInstructionBeforePath(const GrowingInterCodeBasicBlockPtrArra return true; } +bool InterCodeBasicBlock::IsDirectDominatorBlock(InterCodeBasicBlock* block) +{ + if (this == block) + return true; + + if (block->mLoopHead) + return false; + + if (block->mEntryBlocks.Size() == 0) + return false; + + for (int i = 0; i < block->mEntryBlocks.Size(); i++) + if (!IsDirectDominatorBlock(block->mEntryBlocks[i])) + return false; + + return true; +} + +bool InterCodeBasicBlock::HoistCommonConditionalPath(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + if (mFalseJump) + { + InterCodeBasicBlock* cblock = nullptr, * eblock = nullptr; + + if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump && IsDirectDominatorBlock(mTrueJump->mTrueJump)) + { + cblock = mTrueJump; + eblock = mTrueJump->mTrueJump; + } + else if (!mFalseJump->mFalseJump && mFalseJump->mTrueJump && IsDirectDominatorBlock(mFalseJump->mTrueJump)) + { + cblock = mFalseJump; + eblock = mFalseJump->mTrueJump; + } + + if (cblock && cblock->mNumEntries == 1) + { + for (int i = 0; i < cblock->mInstructions.Size(); i++) + { + InterInstruction* ins = cblock->mInstructions[i]; + + if (cblock->CanMoveInstructionBeforeBlock(i) && !HasSideEffect(ins->mCode) && ins->mDst.mTemp >= 0 && !cblock->IsTempModifiedInRange(i + 1, cblock->mInstructions.Size(), ins->mDst.mTemp)) + { + int j = 0; + while (j < eblock->mInstructions.Size() && !eblock->mInstructions[j]->IsEqualSource(ins)) + j++; + + if (j < eblock->mInstructions.Size() && !eblock->IsTempModifiedInRange(0, j, ins->mDst.mTemp) && eblock->CanMoveInstructionBeforeBlock(j) && cblock->CanMoveInstructionBeforeBlock(cblock->mInstructions.Size(), eblock->mInstructions[j])) + { + eblock->mInstructions[j]->mCode = IC_LOAD_TEMPORARY; + eblock->mInstructions[j]->mSrc[0] = ins->mDst; + eblock->mInstructions[j]->mNumOperands = 1; + + mInstructions.Insert(mInstructions.Size() - 1, ins); + cblock->mInstructions.Remove(i); + + mExitRequiredTemps += ins->mDst.mTemp; + cblock->mEntryRequiredTemps += ins->mDst.mTemp; + cblock->mExitRequiredTemps += ins->mDst.mTemp; + eblock->mEntryRequiredTemps += ins->mDst.mTemp; + i--; + changed = true; + } + } + } + } + } + + if (mTrueJump && mTrueJump->HoistCommonConditionalPath()) + changed = true; + if (mFalseJump && mFalseJump->HoistCommonConditionalPath()) + changed = true; + } + + return changed; +} + + + bool InterCodeBasicBlock::MoveTrainCrossBlock(void) { bool changed = false; @@ -15115,6 +15200,27 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 1]->mCode = IC_NONE; mInstructions[i + 1]->mNumOperands = 0; changed = true; } +#endif +#if 1 + else if ( + mInstructions[i + 0]->mCode == IC_LEA && mInstructions[i + 0]->mSrc[0].mTemp >= 0 && + mInstructions[i + 1]->mCode == IC_LEA && mInstructions[i + 1]->mSrc[0].mTemp >= 0 && + mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && + mInstructions[i + 1]->mSrc[1].mFinal && + mInstructions[i + 0]->mSrc[0].IsUByte() && mInstructions[i + 1]->mSrc[0].IsUByte() && mInstructions[i + 0]->mSrc[0].mRange.mMaxValue + mInstructions[i + 1]->mSrc[0].mRange.mMaxValue < 256) + { + mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1]; + + mInstructions[i + 0]->mCode = IC_BINARY_OPERATOR; + mInstructions[i + 0]->mOperator = IA_ADD; + mInstructions[i + 0]->mDst.mType = IT_INT16; + mInstructions[i + 0]->mSrc[1] = mInstructions[i + 1]->mSrc[0]; + mInstructions[i + 0]->mDst.mRange = mInstructions[i + 0]->mSrc[0].mRange; + mInstructions[i + 0]->mDst.mRange.mMaxValue += mInstructions[i + 0]->mSrc[1].mRange.mMaxValue; + + mInstructions[i + 1]->mSrc[0] = mInstructions[i + 0]->mDst; + changed = true; + } #endif else if ( mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_ADD && mInstructions[i + 0]->mSrc[1].mTemp < 0 && mInstructions[i + 0]->mSrc[0].mType == IT_INT16 && @@ -16129,7 +16235,6 @@ void InterCodeBasicBlock::WarnUsedUndefinedVariables(void) } } - void InterCodeBasicBlock::CollectVariables(GrowingVariableArray& globalVars, GrowingVariableArray& localVars, GrowingVariableArray& paramVars, InterMemory paramMemory) { int i; @@ -17284,7 +17389,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "test"); + CheckFunc = !strcmp(mIdent->mString, "tile_row"); mEntryBlock = mBlocks[0]; @@ -17666,6 +17771,9 @@ void InterCodeProcedure::Close(void) #endif + HoistCommonConditionalPath(); + DisassembleDebug("HoistCommonConditionalPath"); + #if 1 ResetVisited(); mEntryBlock->MoveLoopHeadCheckToTail(); @@ -18640,6 +18748,19 @@ bool InterCodeProcedure::GlobalConstantPropagation(void) return mEntryBlock->PropagateConstTemps(ctemps); } +void InterCodeProcedure::HoistCommonConditionalPath(void) +{ + for(;;) + { + ResetVisited(); + if (!mEntryBlock->HoistCommonConditionalPath()) + return; + TempForwarding(); + RemoveUnusedInstructions(); + } +} + + void InterCodeProcedure::ReduceTemporaries(void) { NumberSet* collisionSet; diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 8e8378a..4699e7d 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -499,6 +499,8 @@ public: bool ForwardLoopMovedTemp(void); bool MoveTrainCrossBlock(void); + bool HoistCommonConditionalPath(void); + bool IsDirectDominatorBlock(InterCodeBasicBlock* block); void MarkRelevantStatics(void); void RemoveNonRelevantStatics(void); @@ -679,6 +681,7 @@ protected: void RebuildIntegerRangeSet(void); void CombineIndirectAddressing(void); void SingleTailLoopOptimization(InterMemory paramMemory); + void HoistCommonConditionalPath(void); void MergeBasicBlocks(void); void CheckUsedDefinedTemps(void); From 33d692194ade82700282f9d083ea0fc15d3bf153 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 8 Oct 2023 16:27:52 +0200 Subject: [PATCH 140/169] Add iterators to string --- include/ctype.c | 17 ++ include/ctype.h | 3 + include/opp/iostream.cpp | 13 ++ include/opp/iostream.h | 1 + include/opp/string.cpp | 37 +++++ include/opp/string.h | 10 ++ oscar64/Declaration.cpp | 15 +- oscar64/InterCodeGenerator.cpp | 1 + oscar64/NativeCodeGenerator.cpp | 129 ++++++++------- oscar64/NativeCodeGenerator.h | 2 +- oscar64/Parser.cpp | 269 ++++++++++++++++++++------------ oscar64/Scanner.cpp | 72 ++++----- 12 files changed, 371 insertions(+), 198 deletions(-) diff --git a/include/ctype.c b/include/ctype.c index bac6f8e..650cb36 100644 --- a/include/ctype.c +++ b/include/ctype.c @@ -1,4 +1,5 @@ #include "ctype.h" +#include "conio.h" #define CC_CTRL 0x00 #define CC_BREAK 0x01 @@ -86,3 +87,19 @@ bool isxdigit(char c) { return (c < 128) && (_cinfo[c] & CC_HEX); } + +char tolower(char c) +{ + if (c >= 'A' && c <= 'Z') + return c + ('a' - 'A'); + else + return c; +} + +char toupper(char c) +{ + if (c >= 'a' && c <= 'z') + return c + ('A' - 'a'); + else + return c; +} diff --git a/include/ctype.h b/include/ctype.h index 3da3a47..f4f9a61 100644 --- a/include/ctype.h +++ b/include/ctype.h @@ -25,6 +25,9 @@ inline bool isdigit(char c); inline bool isxdigit(char c); +char tolower(char c); + +char toupper(char c); #pragma compile("ctype.c") diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp index ed44e08..0516c5a 100644 --- a/include/opp/iostream.cpp +++ b/include/opp/iostream.cpp @@ -965,6 +965,19 @@ istream & istream::operator>>(char * p) return *this; } +istream & istream::operator>>(string & s) +{ + doskipws(); + s.clear(); + char c = get(); + while (c > ' ') + { + s += c; + c = get(); + } + return *this; +} + cistream::cistream(void) {} diff --git a/include/opp/iostream.h b/include/opp/iostream.h index 5d43bc6..f42d1e5 100644 --- a/include/opp/iostream.h +++ b/include/opp/iostream.h @@ -132,6 +132,7 @@ public: istream & operator>>(float & val); istream & operator>>(char * p); + istream & operator>>(string & s); istream(void); protected: diff --git a/include/opp/string.cpp b/include/opp/string.cpp index b5732a4..f72d1c4 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -94,6 +94,12 @@ string::~string(void) { free(cstr); } + +void string::clear(void) +{ + free(cstr); + cstr = nullptr; +} void string::copyseg(char * p, char at, char num) const { @@ -476,6 +482,37 @@ inline char string::operator[](char t) const return cstr[t + 1]; } +char * string::begin(void) +{ + return cstr ? cstr + 1 : nullptr; +} + +const char * string::begin(void) const +{ + return cstr ? cstr + 1 : nullptr; +} + +const char * string::cbegin(void) const +{ + return cstr ? cstr + 1 : nullptr; +} + +char * string::end(void) +{ + return cstr ? cstr + 1 + cstr[0] : nullptr; +} + +const char * string::end(void) const +{ + return cstr ? cstr + 1 + cstr[0] : nullptr; +} + +const char * string::cend(void) const +{ + return cstr ? cstr + 1 + cstr[0] : nullptr; +} + + string string::substr(char pos, char len) const { if (!cstr || len == 0 || pos >= cstr[0]) diff --git a/include/opp/string.h b/include/opp/string.h index 35ccd47..7bbb167 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -21,6 +21,8 @@ public: unsigned size(void) const; + void clear(void); + string & operator=(const string & s); string & operator=(string && s); string & operator=(const char * s); @@ -57,6 +59,14 @@ public: char & operator[](char t); char operator[](char t) const; + char * begin(void); + const char * begin(void) const; + const char * cbegin(void) const; + + char * end(void); + const char * end(void) const; + const char * cend(void) const; + const char * tocstr(void) const; string substr(char pos, char len) const; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 6336f1e..a24e0bc 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1501,7 +1501,7 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) } else if (tdec->mType == DT_TYPE_POINTER) { - if (fdec->mType == DT_TYPE_POINTER) + if (fdec->mType == DT_TYPE_POINTER || fdec->mType == DT_TYPE_ARRAY) return ResolveTemplate(fdec->mBase, tdec->mBase); else return false; @@ -1510,6 +1510,8 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) { if (fdec->mType == DT_TYPE_ARRAY) fdec = fdec->mBase->BuildPointer(fdec->mLocation); + else if (fdec->mType == DT_TYPE_FUNCTION) + fdec = fdec->BuildPointer(fdec->mLocation); Declaration* pdec; if (tdec->mBase) @@ -1816,6 +1818,9 @@ bool Declaration::IsSubType(const Declaration* dec) const if (this == dec) return true; + if (mType == DT_TYPE_VOID) + return true; + if (IsReference() && dec->IsReference()) return mBase->IsSubType(dec->mBase); @@ -1996,8 +2001,10 @@ bool Declaration::IsTemplateSameParams(const Declaration* dec, const Declaration { if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION) { - // Skip this pointer for now - Declaration* ld = mParams->mNext, * rd = dec->mParams; + Declaration* ld = mParams, * rd = dec->mParams; + if (mFlags & DTF_FUNC_THIS) + ld = ld->mNext; + while (ld && rd) { if (!ld->mBase->IsTemplateSame(rd->mBase, tdec)) @@ -2112,7 +2119,7 @@ bool Declaration::IsSame(const Declaration* dec) const return mInteger == dec->mInteger; else if (mType == DT_TYPE_INTEGER) return true; - else if (mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_VOID) + else if (mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_VOID || mType == DT_TYPE_AUTO) return true; else if (mType == DT_TYPE_ENUM) return mIdent == dec->mIdent; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index c20bdbe..f3ecaa6 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -3539,6 +3539,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { vr.mReference++; vr = Dereference(proc, texp, block, vr); + vr.mType = vr.mType->mBase; } else vr = Dereference(proc, texp, block, vr); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 885615a..97f6ace 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -25968,7 +25968,7 @@ bool NativeCodeBasicBlock::Check16BitSum(int at, NativeRegisterSum16Info& info) return false; } -bool NativeCodeBasicBlock::IsFinalZeroPageUse(const NativeCodeBasicBlock* block, int at, int from, int to, bool pair) +bool NativeCodeBasicBlock::IsFinalZeroPageUse(const NativeCodeBasicBlock* block, int at, int from, int to, bool pair, bool fchanged) { if (at == 0 && mVisited) return false; @@ -25977,70 +25977,80 @@ bool NativeCodeBasicBlock::IsFinalZeroPageUse(const NativeCodeBasicBlock* block, { mPatched = true; - if (at == 0) + if (at != 0 || (mEntryRequiredRegs[from] || mEntryRequiredRegs[to] || (pair && (mEntryRequiredRegs[from + 1] || mEntryRequiredRegs[to + 1])))) { - mPatched = true; + if (at == 0) + { + mPatched = true; - if (mNumEntries > 1) - { - for (int i = 0; i < mEntryBlocks.Size(); i++) - if (!mEntryBlocks[i]->IsDominatedBy(block)) - return false; - } - } - - while (at < mIns.Size()) - { - if (mIns[at].mMode == ASMIM_ZERO_PAGE) - { - if (mIns[at].mAddress == to) - return false; - if (pair && mIns[at].mAddress == to + 1) - return false; - } - else if (mIns[at].mMode == ASMIM_INDIRECT_Y) - { - if (mIns[at].mAddress == to) - return false; - if (mIns[at].mAddress + 1 == to) - return false; - if (pair && mIns[at].mAddress == to + 1) - return false; - if (!pair && mIns[at].mAddress == from) - return false; - if (mIns[at].mAddress + 1 == from) - return false; - if (pair && mIns[at].mAddress == from + 1) - return false; - } - else if (mIns[at].mType == ASMIT_JSR) - { - LinkerObject* lo = mIns[at].mLinkerObject; - if (lo) + if (mNumEntries > 1) { - for (int i = 0; i < lo->mNumTemporaries; i++) + fchanged = true; + for (int i = 0; i < mEntryBlocks.Size(); i++) + if (mEntryBlocks[i] != block && !mEntryBlocks[i]->IsDominatedBy(block)) + return false; + } + } + + while (at < mIns.Size()) + { + if (mIns[at].mMode == ASMIM_ZERO_PAGE) + { + if (mIns[at].mAddress == to && (fchanged || mIns[at].ChangesAddress())) + return false; + if (pair && mIns[at].mAddress == to + 1 && (fchanged || mIns[at].ChangesAddress())) + return false; + if (mIns[at].mAddress == from && mIns[at].ChangesAddress()) + fchanged = true; + if (pair && mIns[at].mAddress == from + 1 && mIns[at].ChangesAddress()) + fchanged = true; + } + else if (mIns[at].mMode == ASMIM_INDIRECT_Y) + { + if (mIns[at].mAddress == to) + return false; + if (mIns[at].mAddress + 1 == to) + return false; + if (pair && mIns[at].mAddress == to + 1) + return false; + if (!pair && mIns[at].mAddress == from) + return false; + if (mIns[at].mAddress + 1 == from) + return false; + if (pair && mIns[at].mAddress == from + 1) + return false; + } + else if (mIns[at].mType == ASMIT_JSR) + { + fchanged = true; + + LinkerObject* lo = mIns[at].mLinkerObject; + if (lo) { - if (from >= lo->mTemporaries[i] && from < lo->mTemporaries[i] + lo->mTempSizes[i] || - to >= lo->mTemporaries[i] && to < lo->mTemporaries[i] + lo->mTempSizes[i]) + for (int i = 0; i < lo->mNumTemporaries; i++) + { + if (from >= lo->mTemporaries[i] && from < lo->mTemporaries[i] + lo->mTempSizes[i] || + to >= lo->mTemporaries[i] && to < lo->mTemporaries[i] + lo->mTempSizes[i]) return false; + } + } + + if (mIns[at].mFlags & NCIF_USE_ZP_32_X) + { + if (to >= mIns[at].mParam && to < mIns[at].mParam + 4 || + from >= mIns[at].mParam && from < mIns[at].mParam + 4) + return false; } } - if (mIns[at].mFlags & NCIF_USE_ZP_32_X) - { - if (to >= mIns[at].mParam && to < mIns[at].mParam + 4 || - from >= mIns[at].mParam && from < mIns[at].mParam + 4) - return false; - } + at++; } - at++; + if (mTrueJump && !mTrueJump->IsFinalZeroPageUse(block, 0, from, to, pair, fchanged)) + return false; + if (mFalseJump && !mFalseJump->IsFinalZeroPageUse(block, 0, from, to, pair, fchanged)) + return false; } - - if (mTrueJump && !mTrueJump->IsFinalZeroPageUse(block, 0, from, to, pair)) - return false; - if (mFalseJump && !mFalseJump->IsFinalZeroPageUse(block, 0, from, to, pair)) - return false; } return true; @@ -26065,7 +26075,7 @@ bool NativeCodeBasicBlock::ReplaceFinalZeroPageUse(NativeCodeProcedure* nproc) mIns[i + 1].mAddress >= BC_REG_TMP) { nproc->ResetPatched(); - if (IsFinalZeroPageUse(this, i + 2, mIns[i + 1].mAddress, mIns[i + 0].mAddress, false)) + if (IsFinalZeroPageUse(this, i + 2, mIns[i + 1].mAddress, mIns[i + 0].mAddress, false, false)) { nproc->ResetPatched(); if (ForwardReplaceZeroPage(i + 2, mIns[i + 1].mAddress, mIns[i + 0].mAddress)) @@ -26084,7 +26094,7 @@ bool NativeCodeBasicBlock::ReplaceFinalZeroPageUse(NativeCodeProcedure* nproc) mIns[i + 1].mAddress >= BC_REG_TMP) { nproc->ResetPatched(); - if (IsFinalZeroPageUse(this, i + 4, mIns[i + 1].mAddress, mIns[i + 0].mAddress, true)) + if (IsFinalZeroPageUse(this, i + 4, mIns[i + 1].mAddress, mIns[i + 0].mAddress, true, false)) { nproc->ResetPatched(); if (ForwardReplaceZeroPage(i + 4, mIns[i + 1].mAddress, mIns[i + 0].mAddress)) @@ -26110,7 +26120,7 @@ bool NativeCodeBasicBlock::ReplaceFinalZeroPageUse(NativeCodeProcedure* nproc) mIns[i + 2].mAddress >= BC_REG_TMP) { nproc->ResetPatched(); - if (IsFinalZeroPageUse(this, i + 6, mIns[i + 2].mAddress, mIns[i + 0].mAddress, true)) + if (IsFinalZeroPageUse(this, i + 6, mIns[i + 2].mAddress, mIns[i + 0].mAddress, true, false)) { nproc->ResetPatched(); if (ForwardReplaceZeroPage(i + 6, mIns[i + 2].mAddress, mIns[i + 0].mAddress)) @@ -26135,7 +26145,7 @@ bool NativeCodeBasicBlock::ReplaceFinalZeroPageUse(NativeCodeProcedure* nproc) mIns[i + 1].mAddress >= BC_REG_TMP) { nproc->ResetPatched(); - if (IsFinalZeroPageUse(this, i + 5, mIns[i + 1].mAddress, mIns[i + 0].mAddress, true)) + if (IsFinalZeroPageUse(this, i + 5, mIns[i + 1].mAddress, mIns[i + 0].mAddress, true, false)) { nproc->ResetPatched(); if (ForwardReplaceZeroPage(i + 5, mIns[i + 1].mAddress, mIns[i + 0].mAddress)) @@ -41341,7 +41351,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "dungeon_rand_path"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "mod"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -42025,6 +42035,7 @@ void NativeCodeProcedure::Optimize(void) #if 1 if (step == 2) { + BuildDataFlowSets(); ResetVisited(); mEntryBlock->ReplaceFinalZeroPageUse(this); } diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index aab4daf..c674169 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -543,7 +543,7 @@ public: bool Check16BitSum(const NativeCodeBasicBlock* block, int origin, int at, int reg); bool EliminateUpper16BitSum(NativeCodeProcedure* nproc); - bool IsFinalZeroPageUse(const NativeCodeBasicBlock* block, int at, int from, int to, bool pair); + bool IsFinalZeroPageUse(const NativeCodeBasicBlock* block, int at, int from, int to, bool pair, bool fchanged); bool ReplaceFinalZeroPageUse(NativeCodeProcedure* nproc); bool ForwardReplaceZeroPage(int at, int from, int to); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 5650e0d..7657234 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -297,7 +297,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio mdec->mType = DT_CONST_FUNCTION; mdec->mSection = mCodeSection; mdec->mFlags |= DTF_GLOBAL; - mdec->mBase->mFlags |= DTF_FUNC_THIS; +// mdec->mBase->mFlags |= DTF_FUNC_THIS; if (mCompilerOptions & COPT_NATIVE) mdec->mFlags |= DTF_NATIVE; @@ -627,7 +627,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio 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)) + while (dec && (dec->mType == DT_NAMESPACE || (qualified && (dec->mType == DT_TYPE_STRUCT || dec->mType == DT_TYPE_TEMPLATE)) && !dec->mTemplate) && ConsumeTokenIf(TK_COLCOLON)) { if (ExpectToken(TK_IDENT)) { @@ -3168,7 +3168,7 @@ void Parser::PrependThisArgument(Declaration* fdec, Declaration* pthis) } fdec->mParams = adec; - + fdec->mClass = pthis; fdec->mFlags |= DTF_FUNC_THIS; } @@ -4161,12 +4161,15 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ndec->mBase->mType == DT_TYPE_FUNCTION) { - if (pthis) + ndec->mBase->mClass = pthis; + + if (pthis && !(storageFlags & DTF_STATIC)) { if (ConsumeTokenIf(TK_CONST)) PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildConstPointer(ndec->mLocation)); else PrependThisArgument(ndec->mBase, pthis); + ndec->mBase->mFlags |= DTF_FUNC_THIS; } } @@ -4236,30 +4239,41 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { if (pdec->mBase->mFlags & DTF_FUNC_THIS) { - Declaration* adec = pdec->mBase->mParams->Clone(); - adec->mNext = ndec->mBase->mParams; - - if (ConsumeTokenIf(TK_CONST)) + if (!(ndec->mBase->mFlags & DTF_FUNC_THIS)) { - if (!(adec->mBase->mBase->mFlags & DTF_CONST)) - adec->mBase = adec->mBase->mBase->ToConstType()->BuildConstPointer(adec->mLocation); + Declaration* adec = pdec->mBase->mParams->Clone(); + adec->mNext = ndec->mBase->mParams; + + if (ConsumeTokenIf(TK_CONST)) + { + if (!(adec->mBase->mBase->mFlags & DTF_CONST)) + adec->mBase = adec->mBase->mBase->ToConstType()->BuildConstPointer(adec->mLocation); + } + else + { + if (adec->mBase->mBase->mFlags & DTF_CONST) + adec->mBase = adec->mBase->mBase->ToMutableType()->BuildConstPointer(adec->mLocation); + } + + Declaration* p = adec->mBase->mParams; + while (p) + { + p->mVarIndex += 2; + p = p->mNext; + } + + ndec->mBase->mParams = adec; + + ndec->mBase->mFlags |= DTF_FUNC_THIS; } + } + else if (ndec->mBase->mFlags & DTF_FUNC_THIS) + { + if (pdec->mBase->mParams) + ndec->mBase->mParams = pdec->mBase->mParams->Clone(); else - { - if (adec->mBase->mBase->mFlags & DTF_CONST) - adec->mBase = adec->mBase->mBase->ToMutableType()->BuildConstPointer(adec->mLocation); - } - - Declaration* p = adec->mBase->mParams; - while (p) - { - p->mVarIndex += 2; - p = p->mNext; - } - - ndec->mBase->mParams = adec; - - ndec->mBase->mFlags |= DTF_FUNC_THIS; + ndec->mBase->mParams = nullptr; + ndec->mBase->mFlags &= ~DTF_FUNC_THIS; } if (mCompilerOptions & COPT_CPLUSPLUS) @@ -4777,10 +4791,14 @@ Expression* Parser::ParseLambdaExpression(void) pdec->mSize = 2; Expression* einit = nullptr; + + bool capture = false; ConsumeToken(TK_OPEN_BRACKET); if (!ConsumeTokenIf(TK_CLOSE_BRACKET)) { + capture = true; + // Parse capture list list do { bool reference = false; @@ -4880,7 +4898,8 @@ Expression* Parser::ParseLambdaExpression(void) fdec->mBase = TheConstVoidTypeDeclaration; } - PrependThisArgument(fdec->mBase, cpdec); + if (capture) + PrependThisArgument(fdec->mBase, cpdec); fdec->mFlags |= fdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE); @@ -5296,12 +5315,16 @@ Expression* Parser::ParseSimpleExpression(bool lhs) } } - if (mThisPointer && mThisPointer->mType == DT_ARGUMENT && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION)) + if (mThisPointer && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION)) { int offset; uint64 flags; - dec = MemberLookup(mThisPointer->mBase->mBase, mScanner->mTokenIdent, offset, flags); + if (mThisPointer->mType == DT_ARGUMENT) + dec = MemberLookup(mThisPointer->mBase->mBase, mScanner->mTokenIdent, offset, flags); + else if (mThisPointer->mType == DT_TYPE_POINTER) + dec = MemberLookup(mThisPointer->mBase, mScanner->mTokenIdent, offset, flags); + if (dec) { if (dec->mType == DT_ELEMENT || dec->mType == DT_CONST_FUNCTION) @@ -5670,55 +5693,65 @@ Expression* Parser::ParseQualify(Expression* exp) } else if (mdec->mType == DT_CONST_FUNCTION) { - ConsumeToken(TK_OPEN_PARENTHESIS); - - nexp = new Expression(mScanner->mLocation, EX_CALL); - if (mInlineCall) - nexp->mType = EX_INLINE; - mInlineCall = false; - - nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); - nexp->mLeft->mDecType = mdec->mBase; - nexp->mLeft->mDecValue = mdec; - - nexp->mDecType = mdec->mBase; - if (ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) - nexp->mRight = nullptr; - else + if (mdec->mBase->mFlags & DTF_FUNC_THIS) { - nexp->mRight = ParseListExpression(false); - ConsumeToken(TK_CLOSE_PARENTHESIS); - } + ConsumeToken(TK_OPEN_PARENTHESIS); - Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); - texp->mToken = TK_BINARY_AND; - texp->mLeft = exp; - texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); - texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - if (exp->mDecType->mType == DT_TYPE_REFERENCE) - texp->mDecType->mBase = exp->mDecType->mBase; - else - texp->mDecType->mBase = exp->mDecType; - texp->mDecType->mSize = 2; + nexp = new Expression(mScanner->mLocation, EX_CALL); + if (mInlineCall) + nexp->mType = EX_INLINE; + mInlineCall = false; - if (nexp->mRight) - { - Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp; - lexp->mRight = nexp->mRight; - nexp->mRight = lexp; + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + if (ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) + nexp->mRight = nullptr; + else + { + nexp->mRight = ParseListExpression(false); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + if (exp->mDecType->mType == DT_TYPE_REFERENCE) + texp->mDecType->mBase = exp->mDecType->mBase; + else + texp->mDecType->mBase = exp->mDecType; + texp->mDecType->mSize = 2; + + if (nexp->mRight) + { + Expression* lexp = new Expression(nexp->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = nexp->mRight; + nexp->mRight = lexp; + } + else + nexp->mRight = texp; + + nexp = ResolveOverloadCall(nexp); + + nexp->mDecType = nexp->mLeft->mDecType->mBase; + + if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL) + nexp->mType = EX_VCALL; + + exp = nexp; } else - nexp->mRight = texp; - - nexp = ResolveOverloadCall(nexp); - - nexp->mDecType = nexp->mLeft->mDecType->mBase; - - if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL) - nexp->mType = EX_VCALL; - - exp = nexp; + { + nexp = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mDecValue = mdec; + nexp->mDecType = mdec->mBase; + exp = nexp; + } } } else if (destructor) @@ -6499,37 +6532,40 @@ Expression* Parser::ParsePostfixExpression(bool lhs) } bool parentCall = false; - if (thisExp) + if (exp->mDecType->mFlags & DTF_FUNC_THIS) { - if (nexp->mRight) + if (thisExp) { - Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = thisExp; - lexp->mRight = nexp->mRight; - nexp->mRight = lexp; - } - else - nexp->mRight = thisExp; - } - else - { - if ((exp->mDecType->mFlags & DTF_FUNC_THIS) && mThisPointer && mThisPointer->mType == DT_ARGUMENT) - { - Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE); - texp->mDecType = mThisPointer->mBase; - texp->mDecValue = mThisPointer; - if (nexp->mRight) { Expression* lexp = new Expression(nexp->mLocation, EX_LIST); - lexp->mLeft = texp; + lexp->mLeft = thisExp; lexp->mRight = nexp->mRight; nexp->mRight = lexp; } else - nexp->mRight = texp; + nexp->mRight = thisExp; + } + else + { + if (mThisPointer && mThisPointer->mType == DT_ARGUMENT) + { + Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE); + texp->mDecType = mThisPointer->mBase; + texp->mDecValue = mThisPointer; - parentCall = true; + if (nexp->mRight) + { + Expression* lexp = new Expression(nexp->mLocation, EX_LIST); + lexp->mLeft = texp; + lexp->mRight = nexp->mRight; + nexp->mRight = lexp; + } + else + nexp->mRight = texp; + + parentCall = true; + } } } @@ -8210,6 +8246,8 @@ Expression* Parser::ParseFunction(Declaration * dec) if (dec->mFlags & DTF_FUNC_THIS) mThisPointer = dec->mParams; + else + mThisPointer = dec->mClass; mFunctionType = dec; @@ -9220,7 +9258,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE); pdec->mBase = exp->mDecValue; } - else if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) + else if (exp->mType == EX_CONSTANT && (exp->mDecValue->mType == DT_CONST_INTEGER || exp->mDecValue->mType == DT_CONST_TEMPLATE)) { pdec = new Declaration(exp->mLocation, DT_CONST_TEMPLATE); pdec->mBase = exp->mDecValue; @@ -9257,6 +9295,9 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp tdec->mBase = bdec; bdec->mTemplate = tdec; bdec->mBase = tmpld->mBase->mBase; + tdec->mIdent = tmpld->mIdent; + tdec->mQualIdent = tmpld->mQualIdent; + tdec->mScope->mName = tdec->mIdent; tdec->mNext = tmpld; bdec->mIdent = tdec->MangleIdent(); @@ -9511,6 +9552,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp tdec->mBase = ndec; ndec->mValue = p->ParseFunction(ndec->mBase); + ndec->mNumVars = mLocalIndex; ndec->mFlags |= DTF_DEFINED; ndec->mIdent = ndec->mIdent->Mangle(tdec->mScope->mName->mString); @@ -9518,7 +9560,13 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp } else { - tdec->mBase = p->ParseDeclaration(nullptr, true, false, tmpld->mClass, tdec); + Declaration* tpthis = nullptr; + if (tmpld->mClass) + tpthis = tmpld->mClass; + else if (expd && expd->mBase) + tpthis = expd->mBase->BuildConstPointer(tdec->mLocation); + + tdec->mBase = p->ParseDeclaration(nullptr, true, false, tpthis, tdec); } p->mTemplateScope = nullptr; @@ -9541,15 +9589,19 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp mpdec = mpdec->mNext; if (mpdec && mpdec->mTemplate) { + Declaration* rdec; if (mdec->mTemplate) { Declaration * mtdec = p->ParseTemplateExpansion(mpdec->mTemplate, tdec); mtdec->mClass = mdec->mTemplate->mClass; mdec->mTemplate = mtdec; mdec->mTemplate->mBase = mdec; + rdec = mtdec; } else - p->ParseTemplateExpansion(mpdec->mTemplate, tdec); + rdec = p->ParseTemplateExpansion(mpdec->mTemplate, tdec); + if (mdec->mBase->mBase->IsAuto()) + mdec->mBase->mBase = rdec->mBase->mBase; } } @@ -9824,9 +9876,30 @@ void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthi ConsumeTokenIf(TK_CONSTEXPR); Declaration* bdec = ParseBaseTypeDeclaration(0, true); - Declaration* adec = ParsePostfixDeclaration(); + Declaration* adec = nullptr; - adec = ReverseDeclaration(adec, bdec); + if (ConsumeTokenIf(TK_COLCOLON) && ExpectToken(TK_IDENT) && mScanner->mTokenIdent == bdec->mTemplate->mIdent) + { + mScanner->NextToken(); + + Declaration* ctdec = ParseFunctionDeclaration(TheVoidTypeDeclaration); + + adec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); + + adec->mBase = ctdec; + adec->mIdent = bdec->mTemplate->mIdent->PreMangle("+"); + + char buffer[200]; + strcpy_s(buffer, bdec->mTemplate->mQualIdent->mString); + strcat_s(buffer, "::"); + strcat_s(buffer, adec->mIdent->mString); + adec->mQualIdent = Ident::Unique(buffer); + } + else + { + adec = ParsePostfixDeclaration(); + adec = ReverseDeclaration(adec, bdec); + } mTemplateScope = tdec->mScope->mParent; diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 5393807..2a48e37 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -541,7 +541,7 @@ void Scanner::NextPreToken(void) mPreprocessorMode = true; mPrepCondFalse = 0; - NextToken(); + NextPreToken(); int64 v = PrepParseConditional(); if (v) { @@ -612,7 +612,7 @@ void Scanner::NextPreToken(void) if (mToken == TK_COMMA) { mPreprocessorMode = true; - NextToken(); + NextPreToken(); int64 loopCount = PrepParseConditional(); mPreprocessorMode = false; @@ -771,7 +771,7 @@ void Scanner::NextPreToken(void) else if (mToken == TK_PREP_IF) { mPreprocessorMode = true; - NextToken(); + NextPreToken(); int64 v = PrepParseConditional(); if (v) mPrepCondDepth++; @@ -789,7 +789,7 @@ void Scanner::NextPreToken(void) { const Ident* ident = mTokenIdent; - NextToken(); + NextPreToken(); int64 v = PrepParseConditional(); Macro* macro = mDefines->Lookup(ident); @@ -813,7 +813,7 @@ void Scanner::NextPreToken(void) else if (mToken == TK_PREP_UNTIL) { mPreprocessorMode = true; - NextToken(); + NextPreToken(); int64 v = PrepParseConditional(); if (mToken != TK_EOL) mErrors->Error(mLocation, ERRR_PREPROCESSOR, "End of line expected"); @@ -1136,14 +1136,14 @@ void Scanner::NextRawToken(void) } } NextChar(); - NextToken(); + NextPreToken(); } else if (mTokenChar == '/') { NextChar(); while (!IsLineBreak(mTokenChar) && NextChar()) ; - NextToken(); + NextPreToken(); } else if (mTokenChar == '=') { @@ -2237,32 +2237,32 @@ int64 Scanner::PrepParseSimple(void) case TK_INTEGERL: case TK_INTEGERUL: v = mTokenInteger; - NextToken(); + NextPreToken(); break; case TK_SUB: - NextToken(); + NextPreToken(); v = -PrepParseSimple(); break; case TK_LOGICAL_NOT: - NextToken(); + NextPreToken(); v = !PrepParseSimple(); break; case TK_BINARY_NOT: - NextToken(); + NextPreToken(); v = ~PrepParseSimple(); break; case TK_OPEN_PARENTHESIS: - NextToken(); + NextPreToken(); v = PrepParseConditional(); if (mToken == TK_CLOSE_PARENTHESIS) - NextToken(); + NextPreToken(); else mErrors->Error(mLocation, ERRR_PREPROCESSOR, "')' expected"); break; case TK_IDENT: if (strcmp(mTokenIdent->mString, "defined") == 0) { - NextToken(); + NextPreToken(); if (mToken == TK_OPEN_PARENTHESIS) { NextRawToken(); @@ -2277,13 +2277,13 @@ int64 Scanner::PrepParseSimple(void) v = 1; else v = 0; - NextToken(); + NextPreToken(); } else mErrors->Error(mLocation, ERRR_PREPROCESSOR, "Identifier expected"); if (mToken == TK_CLOSE_PARENTHESIS) - NextToken(); + NextPreToken(); else mErrors->Error(mLocation, ERRR_PREPROCESSOR, "')' expected"); } @@ -2296,7 +2296,7 @@ int64 Scanner::PrepParseSimple(void) default: mErrors->Error(mLocation, ERRR_PREPROCESSOR, "Invalid preprocessor token", TokenName(mToken)); if (mToken != TK_EOL) - NextToken(); + NextPreToken(); } return v; @@ -2311,11 +2311,11 @@ int64 Scanner::PrepParseMul(void) switch (mToken) { case TK_MUL: - NextToken(); + NextPreToken(); v *= PrepParseSimple(); break; case TK_DIV: - NextToken(); + NextPreToken(); u = PrepParseSimple(); if (u == 0) mErrors->Error(mLocation, ERRR_PREPROCESSOR, "Division by zero"); @@ -2343,11 +2343,11 @@ int64 Scanner::PrepParseAdd(void) switch (mToken) { case TK_ADD: - NextToken(); + NextPreToken(); v += PrepParseMul(); break; case TK_SUB: - NextToken(); + NextPreToken(); v -= PrepParseMul(); break; default: @@ -2364,11 +2364,11 @@ int64 Scanner::PrepParseShift(void) switch (mToken) { case TK_LEFT_SHIFT: - NextToken(); + NextPreToken(); v <<= PrepParseAdd(); break; case TK_RIGHT_SHIFT: - NextToken(); + NextPreToken(); v >>= PrepParseAdd(); break; default: @@ -2385,27 +2385,27 @@ int64 Scanner::PrepParseRel(void) switch (mToken) { case TK_LESS_THAN: - NextToken(); + NextPreToken(); v = v < PrepParseShift(); break; case TK_GREATER_THAN: - NextToken(); + NextPreToken(); v = v > PrepParseShift(); break; case TK_LESS_EQUAL: - NextToken(); + NextPreToken(); v = v <= PrepParseShift(); break; case TK_GREATER_EQUAL: - NextToken(); + NextPreToken(); v = v >= PrepParseShift(); break; case TK_EQUAL: - NextToken(); + NextPreToken(); v = v == PrepParseShift(); break; case TK_NOT_EQUAL: - NextToken(); + NextPreToken(); v = v != PrepParseShift(); break; default: @@ -2420,7 +2420,7 @@ int64 Scanner::PrepParseBinaryAnd(void) int64 v = PrepParseRel(); while (mToken == TK_BINARY_AND) { - NextToken(); + NextPreToken(); v &= PrepParseRel(); } return v; @@ -2431,7 +2431,7 @@ int64 Scanner::PrepParseBinaryXor(void) int64 v = PrepParseBinaryAnd(); while (mToken == TK_BINARY_XOR) { - NextToken(); + NextPreToken(); v ^= PrepParseBinaryAnd(); } return v; @@ -2442,7 +2442,7 @@ int64 Scanner::PrepParseBinaryOr(void) int64 v = PrepParseBinaryXor(); while (mToken == TK_BINARY_OR) { - NextToken(); + NextPreToken(); v |= PrepParseBinaryXor(); } return v; @@ -2453,7 +2453,7 @@ int64 Scanner::PrepParseLogicalAnd(void) int64 v = PrepParseBinaryOr(); while (mToken == TK_LOGICAL_AND) { - NextToken(); + NextPreToken(); if (!PrepParseBinaryOr()) v = 0; } @@ -2465,7 +2465,7 @@ int64 Scanner::PrepParseLogicalOr(void) int64 v = PrepParseLogicalAnd(); while (mToken == TK_LOGICAL_OR) { - NextToken(); + NextPreToken(); if (PrepParseLogicalAnd()) v = 1; } @@ -2477,10 +2477,10 @@ int64 Scanner::PrepParseConditional(void) int64 v = PrepParseLogicalOr(); if (mToken == TK_QUESTIONMARK) { - NextToken(); + NextPreToken(); int64 vt = PrepParseConditional(); if (mToken == TK_COLON) - NextToken(); + NextPreToken(); else mErrors->Error(mLocation, ERRR_PREPROCESSOR, "':' expected"); int64 vf = PrepParseConditional(); From d4f979b1bc009b92ca892bf45631a384b5717c0c Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 8 Oct 2023 21:30:53 +0200 Subject: [PATCH 141/169] Fix accu return with temp spilling --- include/opp/iostream.cpp | 9 ++-- oscar64/InterCode.cpp | 53 +++++++++++++++++-- oscar64/NativeCodeGenerator.cpp | 90 ++++++++++++++++++++++++++++++++- oscar64/NativeCodeGenerator.h | 2 + 4 files changed, 144 insertions(+), 10 deletions(-) diff --git a/include/opp/iostream.cpp b/include/opp/iostream.cpp index 0516c5a..d853de8 100644 --- a/include/opp/iostream.cpp +++ b/include/opp/iostream.cpp @@ -983,17 +983,18 @@ cistream::cistream(void) void cistream::refill(void) { - mBufferFill = 0; mBufferPos = 0; - char ch; - while (mBufferFill < 32) + char fill = 0; + while (fill < 32) { char ch = getchar(); - mBuffer[mBufferFill++] = ch; + mBuffer[fill++] = ch; if (ch == '\n') break; } + + mBufferFill = fill; } cistream cin; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 50a1068..90771e6 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -12837,6 +12837,10 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) for (int i = 0; i < block->mInstructions.Size(); i++) { InterInstruction* ins = block->mInstructions[i]; + InterInstruction* nins = nullptr; + if (i + 1 < block->mInstructions.Size()) + nins = block->mInstructions[i + 1]; + int t = ins->mDst.mTemp; if (t >= 0) { @@ -12866,6 +12870,8 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) ins->mExpensive = true; else if (ins->mSrc[0].mTemp >= 0 && ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND && ins->mSrc[0].mRange.mMaxValue >= 256) ins->mExpensive = true; + else if (nins && nins->mCode == IC_LEA && nins->mSrc[0].mTemp >= 0 && (nins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_UNBOUND || nins->mSrc[0].mRange.mMaxValue >= 255)) + ins->mExpensive = true; break; case IC_LOAD: case IC_STORE: @@ -15631,6 +15637,17 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray return changed; } +static int TempUseDelta(const InterInstruction* ins) +{ + int d = 0; + if (ins->mDst.mTemp >= 0) + d++; + for (int i = 0; i < ins->mNumOperands; i++) + if (ins->mSrc[i].mTemp >= 0 && ins->mSrc[i].mFinal) + d--; + return d; +} + void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& staticVars) { int i; @@ -15945,25 +15962,26 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati j--; while (j >= 0) { + InterInstruction* jins = mInstructions[j]; + if (j < ti - 1) { if (CanMoveInstructionDown(j, ti)) { - InterInstruction* jins = mInstructions[j]; for (int k = j; k < ti - 1; k++) { SwapInstructions(jins, mInstructions[k + 1]); mInstructions[k] = mInstructions[k + 1]; } mInstructions[ti - 1] = jins; - if (mInstructions[ti - 1]->NumUsedTemps() <= 1) - ti--; + if (jins->NumUsedTemps() <= 1 && !(jins->mCode == IC_CALL || jins->mCode == IC_CALL_NATIVE)) + ti--; // mInstructions.Insert(i, mInstructions[j]); // mInstructions.Remove(j); } } - else if (mInstructions[j]->NumUsedTemps() <= 1) + else if (jins->NumUsedTemps() <= 1 && !(jins->mCode == IC_CALL || jins->mCode == IC_CALL_NATIVE)) ti--; j--; @@ -15974,6 +15992,33 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati #endif CheckFinalLocal(); + // check move calls our of range to save register spilling + i = 0; + while (i < mInstructions.Size()) + { + InterInstruction* ins(mInstructions[i]); + if ((ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE) && ins->mSrc[0].mTemp < 0) + { + int j = i; + while (j > 0 && CanSwapInstructions(ins, mInstructions[j - 1]) && TempUseDelta(mInstructions[j - 1]) >= 0) + j--; + while (j < i && TempUseDelta(mInstructions[j]) == 0) + j++; + + if (j < i) + { + while (i > j) + { + i--; + SwapInstructions(mInstructions[i], ins); + mInstructions[i + 1] = mInstructions[i]; + } + mInstructions[j] = ins; + } + } + i++; + } + // sort stores up bool changed; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 97f6ace..642b288 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -5921,6 +5921,29 @@ void NativeCodeBasicBlock::StoreByteIndexedValue(InterCodeProcedure* proc, const } +void NativeCodeBasicBlock::StoreByteOffsetIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* wins) +{ + mIns.Push(NativeCodeInstruction(iins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[iins->mSrc[0].mTemp])); + mIns.Push(NativeCodeInstruction(iins, ASMIT_CLC)); + mIns.Push(NativeCodeInstruction(iins, ASMIT_ADC, ASMIM_IMMEDIATE, wins->mSrc[1].mIntConst)); + mIns.Push(NativeCodeInstruction(iins, ASMIT_TAY)); + + uint32 flags = NCIF_LOWER | NCIF_UPPER; + if (wins->mVolatile) + flags |= NCIF_VOLATILE; + + for (int i = 0; i < InterTypeSize[wins->mSrc[0].mType]; i++) + { + if (i != 0) + mIns.Push(NativeCodeInstruction(wins, ASMIT_INY, ASMIM_IMPLIED)); + if (wins->mSrc[0].mTemp < 0) + mIns.Push(NativeCodeInstruction(wins, ASMIT_LDA, ASMIM_IMMEDIATE, (wins->mSrc[0].mIntConst >> (8 * i)) & 0xff)); + else + mIns.Push(NativeCodeInstruction(wins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp] + i)); + mIns.Push(NativeCodeInstruction(wins, ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[iins->mSrc[1].mTemp], nullptr, flags)); + } +} + void NativeCodeBasicBlock::LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins) { int size = InterTypeSize[wins->mSrc[0].mType]; @@ -19830,6 +19853,55 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool } } +#if 1 + if (mTrueJump && mFalseJump && mIns.Size() >= 2) + { + int nins = mIns.Size(); + if (mIns[nins - 2].mType == ASMIT_LDA && mIns[nins - 2].mMode == ASMIM_IMMEDIATE && + mIns[nins - 1].mType == ASMIT_CMP && mIns[nins - 1].mMode == ASMIM_ZERO_PAGE && (mIns[nins - 1].mLive & LIVE_MEM) && !(mIns[nins - 1].mLive & LIVE_CPU_REG_A) && + !mTrueJump->mEntryRequiredRegs[CPU_REG_C] && !mFalseJump->mEntryRequiredRegs[CPU_REG_C] && !mTrueJump->mEntryRequiredRegs[CPU_REG_Z] && !mFalseJump->mEntryRequiredRegs[CPU_REG_Z]) + { + int im = mIns[nins - 2].mAddress; + + mIns[nins - 2].CopyMode(mIns[nins - 1]); + mIns[nins - 2].mLive |= LIVE_MEM; + mIns[nins - 1].mMode = ASMIM_IMMEDIATE; + mIns[nins - 1].mFlags = NCIF_LOWER | NCIF_UPPER; + + if (mBranch == ASMIT_BCC) + { + if (im == 255) + { + mIns[nins - 1].mType = ASMIT_SEC; + mIns[nins - 1].mMode = ASMIM_IMPLIED; + } + else + { + mIns[nins - 1].mAddress = im + 1; + mBranch = ASMIT_BCS; + } + } + else if (mBranch == ASMIT_BCS) + { + if (im == 255) + { + mIns[nins - 1].mType = ASMIT_SEC; + mIns[nins - 1].mMode = ASMIM_IMPLIED; + } + else + { + mIns[nins - 1].mAddress = im + 1; + mBranch = ASMIT_BCC; + } + } + else + mIns[nins - 1].mAddress = im; + + + changed = true; + } + } +#endif CheckLive(); if (mTrueJump && mFalseJump) @@ -26343,6 +26415,9 @@ bool NativeCodeBasicBlock::ForwardReplaceZeroPage(int at, int from, int to) changed = true; if (mFalseJump && mFalseJump->ForwardReplaceZeroPage(0, from, to)) changed = true; + + if (changed) + mEntryRequiredRegs += to; } return changed; @@ -41351,7 +41426,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "mod"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "fill_row"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -41429,7 +41504,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mEntryBlock->mTrueJump = CompileBlock(mInterProc, mInterProc->mBlocks[0]); mEntryBlock->mBranch = ASMIT_JMP; - if (proc->mLeafProcedure && proc->mFastCallProcedure && !proc->mInterrupt && !proc->mDispatchedCall && mNoFrame && mStackExpand == 0 && commonFrameSize == 0 && (mGenerator->mCompilerOptions & COPT_NATIVE)) + if (proc->mLeafProcedure && proc->mFastCallProcedure && !proc->mInterrupt && !proc->mDispatchedCall && mNoFrame && mStackExpand == 0 && commonFrameSize == 0 && proc->mTempSize <= BC_REG_TMP_SAVED - BC_REG_TMP && (mGenerator->mCompilerOptions & COPT_NATIVE)) { #if 1 if (proc->mParamVars.Size() == 1 && proc->mParamVars[0]->mSize == 1) @@ -42712,6 +42787,7 @@ void NativeCodeProcedure::Optimize(void) else cnt++; + } while (changed); #if 1 @@ -43141,6 +43217,16 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode block->StoreByteIndexedValue(iproc, ins, iblock->mInstructions[i + 1]); i++; } + else if (i + 1 < iblock->mInstructions.Size() && + iblock->mInstructions[i + 1]->mCode == IC_STORE && iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[1].mFinal && + ins->mSrc[1].mTemp >= 0 && ins->mSrc[0].IsUByte() && ins->mSrc[0].mTemp >= 0 && + iblock->mInstructions[i + 1]->mSrc[1].mIntConst + ins->mSrc[0].mRange.mMaxValue + InterTypeSize[iblock->mInstructions[i + 1]->mSrc[0].mType] <= 256 && + (iblock->mInstructions[i + 1]->mSrc[0].mTemp >= 0 || iblock->mInstructions[i + 1]->mSrc[0].mType <= IT_INT32) && + (InterTypeSize[iblock->mInstructions[i + 1]->mSrc[0].mType] == 1 || iblock->mInstructions[i + 1]->mSrc[1].mStride == 1)) + { + block->StoreByteOffsetIndexedValue(iproc, ins, iblock->mInstructions[i + 1]); + i++; + } else if (i + 2 < iblock->mInstructions.Size() && ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_GLOBAL && ins->mSrc[1].mLinkerObject->mSize <= 256 && // ins->mSrc[0].IsUByte() && diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index c674169..5975eaf 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -331,6 +331,8 @@ public: bool LoadUnopStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* oins, const InterInstruction* wins); bool LoadLoadOpStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins1, const InterInstruction* rins0, const InterInstruction* oins, const InterInstruction* wins); void LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins); + void StoreByteOffsetIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* sins); + NativeCodeBasicBlock* BinaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0); void UnaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); void RelationalOperator(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure * nproc, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock * falseJump); From 312914d78c4fc7c481874acbaf361fb388b71ca1 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 8 Oct 2023 21:44:30 +0200 Subject: [PATCH 142/169] Bump version number --- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index b64e26d..a873b0d 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.26.221"); + strcpy(strProductVersion, "1.26.222"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index c3ab1c5..072b192 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,26,221,0 - PRODUCTVERSION 1,26,221,0 + FILEVERSION 1,26,222,0 + PRODUCTVERSION 1,26,222,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.26.221.0" + VALUE "FileVersion", "1.26.222.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.26.221.0" + VALUE "ProductVersion", "1.26.222.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index a772017..552d967 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5712,15 +5712,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{76114EBF-11A9-4AB2-9F9C-04180A284C4B}" - "PackageCode" = "8:{A38D2D44-B7EB-49A4-ACA8-8974DC5EB905}" + "ProductCode" = "8:{60E64F94-3BF3-4545-B26E-F1B5B0CD8A35}" + "PackageCode" = "8:{6087B4D3-6850-4189-ADED-AF3B0C252F07}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.26.221" + "ProductVersion" = "8:1.26.222" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 6a30a384153523ebf0d1426a19a1d10c9618f241 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 10 Oct 2023 09:02:30 +0200 Subject: [PATCH 143/169] Fix multi instantiation of inline constructors --- autotest/autotest.bat | 3 +++ autotest/opp_part1.cpp | 2 ++ autotest/opp_part1.h | 40 ++++++++++++++++++++++++++++++++++++++++ autotest/opp_part2.cpp | 13 +++++++++++++ autotest/opp_part2.h | 16 ++++++++++++++++ autotest/opp_parts.cpp | 25 +++++++++++++++++++++++++ oscar64/InterCode.cpp | 4 ++-- oscar64/Parser.cpp | 21 +++++++++++++++++++-- 8 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 autotest/opp_part1.cpp create mode 100644 autotest/opp_part1.h create mode 100644 autotest/opp_part2.cpp create mode 100644 autotest/opp_part2.h create mode 100644 autotest/opp_parts.cpp diff --git a/autotest/autotest.bat b/autotest/autotest.bat index a5eaf07..567bea6 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -21,6 +21,9 @@ rem @echo off @call :test opp_pairtest.cpp @if %errorlevel% neq 0 goto :error +@call :test opp_parts.cpp +@if %errorlevel% neq 0 goto :error + @call :test operatoroverload.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/opp_part1.cpp b/autotest/opp_part1.cpp new file mode 100644 index 0000000..8fc18fb --- /dev/null +++ b/autotest/opp_part1.cpp @@ -0,0 +1,2 @@ +#include "opp_part1.h" + diff --git a/autotest/opp_part1.h b/autotest/opp_part1.h new file mode 100644 index 0000000..7b227ff --- /dev/null +++ b/autotest/opp_part1.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +class A +{ +protected: + int a, b; + +public: + A(int a_, int b_) + : a(a_), b(b_) + {} + + int sum(void) const + { + return a * b; + } +}; + +class AS +{ +protected: + opp::vector va; +public: + AS(const opp::vector & v) + : va(v) + {} + + int sum(void) + { + int s = 0; + for(const auto & a : va) + s += a.sum(); + return s; + } +}; + +#pragma compile("opp_part1.cpp") + diff --git a/autotest/opp_part2.cpp b/autotest/opp_part2.cpp new file mode 100644 index 0000000..f30400c --- /dev/null +++ b/autotest/opp_part2.cpp @@ -0,0 +1,13 @@ +#include "opp_part2.h" + +BS::BS(const opp::vector & v) + : va(v) + {} + +int BS::sum(void) +{ + int s = 0; + for(const auto & a : va) + s += a.sum(); + return s; +} diff --git a/autotest/opp_part2.h b/autotest/opp_part2.h new file mode 100644 index 0000000..5606e0e --- /dev/null +++ b/autotest/opp_part2.h @@ -0,0 +1,16 @@ +#pragma once + +#include "opp_part1.h" + +class BS +{ +protected: + opp::vector va; +public: + BS(const opp::vector & v); + int sum(void); +}; + + + +#pragma compile("opp_part2.cpp") diff --git a/autotest/opp_parts.cpp b/autotest/opp_parts.cpp new file mode 100644 index 0000000..364753e --- /dev/null +++ b/autotest/opp_parts.cpp @@ -0,0 +1,25 @@ +#include + +#include "opp_part1.h" +#include "opp_part2.h" + + +int main(void) +{ + opp::vector va; + va.push_back(A(1, 2)); + va.push_back(A(3, 4)); + va.push_back(A(6, 4)); + va.push_back(A(0, 9)); + + AS as(va); + + va.push_back(A(7, 1)); + + BS bs(va); + + assert(bs.sum() == 2 + 12 + 24 + 7); + assert(as.sum() == 2 + 12 + 24); + + return 0; +} diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 90771e6..98b702b 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -15997,7 +15997,7 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati while (i < mInstructions.Size()) { InterInstruction* ins(mInstructions[i]); - if ((ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE) && ins->mSrc[0].mTemp < 0) + if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE) { int j = i; while (j > 0 && CanSwapInstructions(ins, mInstructions[j - 1]) && TempUseDelta(mInstructions[j - 1]) >= 0) @@ -17434,7 +17434,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "tile_row"); + CheckFunc = !strcmp(mIdent->mString, "mod"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 7657234..5005ce4 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3879,6 +3879,8 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex pdec = pdec->mNext; } + Declaration* dec = cdec; + if (pdec) { if (!cdec->mBase->IsSame(pdec->mBase)) @@ -3903,7 +3905,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } } - cdec = pdec; + dec = pdec; + if (!(pdec->mFlags & DTF_DEFINED)) + cdec = pdec; } cdec->mIdent = pthis->mBase->mIdent->PreMangle("+"); @@ -3931,7 +3935,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex cdec->mNumVars = mLocalIndex; } - return cdec; + return dec; } if (bdec && bdec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON)) @@ -6097,6 +6101,19 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) return nexp; } } + + if (type->mType == DT_TYPE_POINTER && type->mBase->mType == DT_TYPE_FUNCTION) + { + Declaration* fr = tdec->mScope->Lookup(Ident::Unique("operator()")); + if (fr && !(fr->mBase->mFlags & DTF_FUNC_THIS)) + { + Expression* nexp = new Expression(exp->mLocation, EX_CONSTANT); + nexp->mDecType = fr->mBase; + nexp->mDecValue = fr; + + return nexp; + } + } } if (type->mType == DT_TYPE_STRUCT) From 020afb8722c951798e9253e1d57c5871fa791a31 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 10 Oct 2023 09:06:31 +0200 Subject: [PATCH 144/169] bump version number --- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index a873b0d..351368c 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.26.222"); + strcpy(strProductVersion, "1.26.223"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 072b192..32c8681 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,26,222,0 - PRODUCTVERSION 1,26,222,0 + FILEVERSION 1,26,223,0 + PRODUCTVERSION 1,26,223,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.26.222.0" + VALUE "FileVersion", "1.26.223.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.26.222.0" + VALUE "ProductVersion", "1.26.223.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 552d967..0392c28 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5712,15 +5712,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{60E64F94-3BF3-4545-B26E-F1B5B0CD8A35}" - "PackageCode" = "8:{6087B4D3-6850-4189-ADED-AF3B0C252F07}" + "ProductCode" = "8:{8947A625-BB69-4660-BD2A-A58BD90E541C}" + "PackageCode" = "8:{A4C4A88C-A11E-4AD7-8EE8-99887AD5731F}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.26.222" + "ProductVersion" = "8:1.26.223" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 2027ac5d4c8b234577f6774c6d79a6d261af4c4f Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 12 Oct 2023 14:10:34 +0200 Subject: [PATCH 145/169] Fix template expansion in multiple cpp --- autotest/opp_vector.cpp | 41 ++++++++++++++++ include/opp/algorithm.h | 19 +++++--- include/opp/utility.h | 8 +++- include/opp/vector.h | 101 ++++++++++++++++++++++++++++++---------- oscar64/Declaration.cpp | 2 + oscar64/InterCode.cpp | 6 +-- oscar64/Parser.cpp | 44 ++++++++--------- 7 files changed, 166 insertions(+), 55 deletions(-) diff --git a/autotest/opp_vector.cpp b/autotest/opp_vector.cpp index 5e82699..f2d56a1 100644 --- a/autotest/opp_vector.cpp +++ b/autotest/opp_vector.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include int main(void) { @@ -23,5 +25,44 @@ int main(void) assert(s == 1 + 3 + 5 + 7 + 9); + opp::vector v; + + for(int i=0; i<10; i++) + v.push_back(i); + + assert(v.size() == 10); + v.insert(0, 20); + assert(v.size() == 11); + v.insert(6, 21); + assert(v.size() == 12); + v.insert(12, 22); + + int * fi = opp::find(v.begin(), v.end(), 21); + + fi = v.insert(fi, 30); + fi = v.insert(fi, 31); + fi = v.insert(fi, 32); + + assert(v.size() == 16); + assert(v[0] == 20); + assert(v[15] == 22); + assert(v[8] == 32); + + fi = opp::find(v.begin(), v.end(), 32); + + for(int i=0; i<30; i++) + { + fi = v.insert(fi, i + 40); + } + + assert(v.size() == 46); + assert(v[28] == 60); + + v.erase(10, 10); + + for(int i : v) + opp::cout << i << ", "; + opp::cout << "\n"; + return 0; } diff --git a/include/opp/algorithm.h b/include/opp/algorithm.h index b1d8807..a6f5a19 100644 --- a/include/opp/algorithm.h +++ b/include/opp/algorithm.h @@ -1,14 +1,9 @@ #ifndef OPP_ALGORITHM_H #define OPP_ALGORITHM_H +#include "utility.h" namespace opp { -template -inline void swap(T & x, T & y) -{ - T t(x); x = y; y = t; -} - template void sort(T s, T e) { @@ -72,6 +67,18 @@ OI copy(II first, II last, OI result) return result; } + +template +II find (II first, II last, const T& val) +{ + while (first != last) + { + if (*first == val) return first; + ++first; + } + return last; +} + } #endif diff --git a/include/opp/utility.h b/include/opp/utility.h index b09c0aa..503aa8d 100644 --- a/include/opp/utility.h +++ b/include/opp/utility.h @@ -4,11 +4,17 @@ namespace opp { template -T && move(T & m) +inline T && move(T & m) { return (T &&)m; } +template +inline void swap(T & x, T & y) +{ + T t(x); x = y; y = move(t); +} + template struct pair diff --git a/include/opp/vector.h b/include/opp/vector.h index 57f07d8..c18c96c 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -12,22 +12,22 @@ class vector { protected: T * _data; - int _size, _capacity; + size_t _size, _capacity; public: typedef T element_type; vector(void) : _data(nullptr), _size(0), _capacity(0) {} - vector(int n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n) + vector(size_t n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n) { - for(int i=0; i void emplace_back(const P&... p); @@ -174,13 +204,13 @@ protected: template -void vector::reserve(int n) +void vector::reserve(size_t n) { if (n > _capacity) { _capacity = n; T * d = (T *)malloc(_capacity * sizeof(T)); - for(int i=0; i<_size; i++) + for(size_t i=0; i<_size; i++) { new (d + i)T(move(_data[i])); _data[i].~T(); @@ -191,17 +221,17 @@ void vector::reserve(int n) } template -void vector::resize(int n) +void vector::resize(size_t n) { if (n < _size) { - for(int i=n; i<_size; i++) + for(size_t i=n; i<_size; i++) _data[i].~T(); _size = n; } else if (n < _capacity) { - for(int i=_size; i::shrink_to_fit(void) { _capacity = _size; T * d = (T *)malloc(_capacity * sizeof(T)); - for(int i=0; i<_size; i++) + for(size_t i=0; i<_size; i++) { new (d + i)T(move(_data[i])); _data[i].~T(); @@ -257,23 +287,46 @@ void vector::emplace_back(const P&... p) } template -void vector::insert(int at, const T & t) +void vector::insert(size_t at, const T & t) { if (_size == _capacity) reserve(_size + 1 + (_size >> 1)); new (_data + _size)T; - for(int i=_size; i>at; i--) + for(size_t i=_size; i>at; i--) _data[i] = move(_data[i - 1]); _data[at] = t; + _size++; } template -void vector::erase(int at, int n) +void vector::erase(size_t at, size_t n) { _size -= n; - for(int i=at; i<_size; i++) + for(size_t i=at; i<_size; i++) _data[i] = move(_data[i + n]); - _data[_size].~T(); + for(size_t i=0; i +T * vector::insert(T * at, const T & t) +{ + if (_size == _capacity) + { + unsigned f = unsigned(at) - unsigned(_data); + reserve(_size + 1 + (_size >> 1)); + at = (T *)(f + unsigned(_data)); + } + T * dp = _data + _size; + new (dp)T; + while (dp != at) + { + dp--; + dp[1] = move(dp[0]); + } + dp[0] = t; + _size++; + return dp + 1; } } diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index a24e0bc..24a399a 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -2221,6 +2221,8 @@ bool Declaration::IsTemplateSame(const Declaration* dec, const Declaration * tde else return false; } + else if (dec->mBase->mType == DT_TYPE_TEMPLATE) + return mBase->IsTemplateSame(dec->mBase, tdec); else return this->Stride() == dec->Stride() && mBase->IsTemplateSame(dec->mBase, tdec); } diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 98b702b..87e17d8 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -7631,9 +7631,9 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray else { if (mLocalValueRange[s0].mMaxState == IntegerValueRange::S_BOUND) - mTrueValueRange[s1].LimitMax(mLocalValueRange[s0].mMaxValue - 1); + mTrueValueRange[s1].LimitMaxWeak(mLocalValueRange[s0].mMaxValue - 1); if (mLocalValueRange[s0].mMinState == IntegerValueRange::S_BOUND) - mFalseValueRange[s1].LimitMin(mLocalValueRange[s0].mMinValue); + mFalseValueRange[s1].LimitMinWeak(mLocalValueRange[s0].mMinValue); } break; case IA_CMPLES: @@ -17434,7 +17434,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "mod"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 5005ce4..84e7f75 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1620,27 +1620,29 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "Identifier expected"); } - if (!mdec) + if (mdec) + { + Expression* texp = ParseInitExpression(mdec->mBase); + + Declaration* cdec = CopyConstantInitializer(mdec->mOffset, mdec->mBase, texp); + cdec->mBits = mdec->mBits; + cdec->mShift = mdec->mShift; + + if (last) + last->mNext = cdec; + else + dec->mParams = cdec; + last = cdec; + + if (!ConsumeTokenIf(TK_COMMA)) + break; + + mdec = mdec->mNext; + while (!mdec && path.Size()) + mdec = path.Pop()->mParams; + } + else if (!ConsumeTokenIf(TK_COMMA)) break; - - Expression* texp = ParseInitExpression(mdec->mBase); - - Declaration* cdec = CopyConstantInitializer(mdec->mOffset, mdec->mBase, texp); - cdec->mBits = mdec->mBits; - cdec->mShift = mdec->mShift; - - if (last) - last->mNext = cdec; - else - dec->mParams = cdec; - last = cdec; - - if (!ConsumeTokenIf(TK_COMMA)) - break; - - mdec = mdec->mNext; - while (!mdec && path.Size()) - mdec = path.Pop()->mParams; } } @@ -4555,7 +4557,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { if (ndec->mBase->mType == DT_TYPE_FUNCTION) { - if (ndec->mFlags & DTF_DEFINED) + if ((ndec->mFlags & DTF_DEFINED) && !(ndec->mFlags & DTF_REQUEST_INLINE)) mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition", ndec->mQualIdent); ndec->mCompilerOptions = mCompilerOptions; From ecf8e69cf20d695bbe9beb50a127ee4edb3aa476 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 13 Oct 2023 11:18:16 +0200 Subject: [PATCH 146/169] Add restricted pointer attribute to newly allocated memory --- autotest/opp_string.cpp | 13 +- oscar64/InterCode.cpp | 278 +++++++++++++++++++++++++++++--- oscar64/InterCode.h | 13 +- oscar64/InterCodeGenerator.cpp | 2 + oscar64/NativeCodeGenerator.cpp | 27 +++- oscar64/NativeCodeGenerator.h | 1 + 6 files changed, 306 insertions(+), 28 deletions(-) diff --git a/autotest/opp_string.cpp b/autotest/opp_string.cpp index bf2b789..3a52312 100644 --- a/autotest/opp_string.cpp +++ b/autotest/opp_string.cpp @@ -10,7 +10,7 @@ static const char AndBeyond[] = "And Beyond"; static const char And[] = "And"; static const char HelloWorldAndBeyond[] = "Hello World And Beyond"; -void test_create(void) +__noinline void test_create(void) { string s1(); string s2(HelloWorld); @@ -22,7 +22,7 @@ void test_create(void) assert(s4.size() == 1 && s4[0] == 'a'); } -void test_concat(void) +__noinline void test_concat(void) { string s1(); string s2(HelloWorld); @@ -51,7 +51,7 @@ __noinline void test_find(void) assert(s1.find(' ', 6) == 11); } -void test_assign(void) +__noinline void test_assign(void) { string s1(HelloWorld); string s2(AndBeyond); @@ -77,9 +77,12 @@ void test_assign(void) assert(!strcmp(s3.tocstr(), HelloWorld)); } +static char * test; + int main(void) { - char * p = new char; + test = new char; + unsigned avail = heapfree(); test_create(); @@ -94,5 +97,7 @@ int main(void) test_assign(); assert(avail == heapfree()); + delete test; + return 0; } diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 87e17d8..ee838e9 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -5,6 +5,7 @@ #include static bool CheckFunc; +static bool CheckCase; int InterTypeSize[] = { 0, @@ -445,7 +446,9 @@ bool InterCodeBasicBlock::CollidingMem(const InterOperand& op1, InterType type1, { if (op1.mMemory == IM_INDIRECT) { - if (op2.mMemory == IM_GLOBAL) + if (op1.mRestricted) + return false; + else if (op2.mMemory == IM_GLOBAL) return mProc->mModule->mGlobalVars[op2.mVarIndex]->mAliased; else if (op2.mMemory == IM_FPARAM || op2.mMemory == IM_FFRAME) return false; @@ -456,7 +459,9 @@ bool InterCodeBasicBlock::CollidingMem(const InterOperand& op1, InterType type1, } else if (op2.mMemory == IM_INDIRECT) { - if (op1.mMemory == IM_GLOBAL) + if (op2.mRestricted) + return false; + else if (op1.mMemory == IM_GLOBAL) return mProc->mModule->mGlobalVars[op1.mVarIndex]->mAliased; else if (op1.mMemory == IM_FPARAM || op1.mMemory == IM_FFRAME) return false; @@ -487,6 +492,8 @@ bool InterCodeBasicBlock::CollidingMem(const InterOperand& op1, InterType type1, return op1.mIntConst < op2.mIntConst + op2.mOperandSize && op2.mIntConst < op1.mIntConst + op1.mOperandSize; else if (op1.mLinkerObject && op2.mLinkerObject && op1.mLinkerObject != op2.mLinkerObject) return false; + else if (op1.mRestricted && op2.mRestricted && op1.mRestricted != op2.mRestricted) + return false; else return CollidingMemType(type1, type2); default: @@ -1235,12 +1242,12 @@ void ValueSet::InsertValue(InterInstruction * ins) static bool HasSideEffect(InterCode code) { - return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_MALLOC || code == IC_FREE; + return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_DISPATCH /* || code == IC_MALLOC || code == IC_FREE */; } static bool IsObservable(InterCode code) { - return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_STORE || code == IC_COPY || code == IC_STRCPY || code == IC_MALLOC || code == IC_FREE; + return code == IC_CALL || code == IC_CALL_NATIVE || code == IC_ASSEMBLER || code == IC_DISPATCH || code == IC_STORE || code == IC_COPY || code == IC_STRCPY || code == IC_MALLOC || code == IC_FREE; } static bool IsMoveable(InterCode code) @@ -2900,7 +2907,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr InterOperand::InterOperand(void) - : mTemp(INVALID_TEMPORARY), mType(IT_NONE), mFinal(false), mIntConst(0), mFloatConst(0), mVarIndex(-1), mOperandSize(0), mLinkerObject(nullptr), mMemory(IM_NONE), mStride(1) + : mTemp(INVALID_TEMPORARY), mType(IT_NONE), mFinal(false), mIntConst(0), mFloatConst(0), mVarIndex(-1), mOperandSize(0), mLinkerObject(nullptr), mMemory(IM_NONE), mStride(1), mRestricted(0) {} bool InterOperand::IsNotUByte(void) const @@ -2967,6 +2974,7 @@ void InterOperand::ForwardMem(const InterOperand& op) mType = op.mType; mRange = op.mRange; mStride = op.mStride; + mRestricted = op.mRestricted; mFinal = false; } @@ -4335,7 +4343,12 @@ void InterOperand::Disassemble(FILE* file, InterCodeProcedure* proc) fprintf(file, "R%d(%c)", mTemp, typechars[mType]); if (mType == IT_POINTER && mMemory == IM_INDIRECT) + { fprintf(file, "+%d", int(mIntConst)); + } + + if (mRestricted) + fprintf(file, "{%d}", mRestricted); if (mRange.mMinState >= IntegerValueRange::S_WEAK || mRange.mMaxState >= IntegerValueRange::S_WEAK) { @@ -4811,6 +4824,22 @@ void InterCodeBasicBlock::GenerateTraces(bool expand, bool compact) // Limit number of contractions for (int i = 0; i < 100; i++) { + int sz = mInstructions.Size(); + + if (mFalseJump && sz > 0 && mInstructions[sz - 1]->mCode == IC_BRANCH && mInstructions[sz - 1]->mSrc[0].mType == IT_BOOL && mInstructions[sz - 1]->mSrc[0].mTemp < 0) + { + mInstructions[sz - 1]->mCode = IC_JUMP; + mInstructions[sz - 1]->mNumOperands = 0; + if (!mInstructions[sz - 1]->mSrc[0].mIntConst) + { + mTrueJump->mNumEntries--; + mTrueJump = mFalseJump; + } + else + mFalseJump->mNumEntries--; + mFalseJump = nullptr; + } + if (mTrueJump && mTrueJump->mInstructions.Size() == 1 && mTrueJump->mInstructions[0]->mCode == IC_JUMP && !mTrueJump->mLoopHead && mTrueJump->mTraceIndex != mIndex) { mTrueJump->mTraceIndex = mIndex; @@ -5123,6 +5152,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI break; } } + break; case IC_LOAD: @@ -5149,6 +5179,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI break; } } + OptimizeAddress(ins, tvalue, 1); break; case IC_COPY: @@ -6204,6 +6235,10 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void) { constFalse = true; } + else if (cins->mSrc[1].IsUnsigned() && cins->mSrc[1].mRange.mMaxValue == 0) + { + constFalse = true; + } else if (cins->mSrc[1].IsUnsigned() && cins->mSrc[0].IsUnsigned()) { if (cins->mSrc[1].mRange.mMinValue > cins->mSrc[0].mRange.mMaxValue) @@ -10172,6 +10207,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& { ins->mCode = IC_LOAD_TEMPORARY; ins->mSrc[0] = lins->mDst; + ins->mSrc[0].mRestricted = ins->mDst.mRestricted = lins->mDst.mRestricted; ins->mNumOperands = 1; assert(ins->mSrc[0].mTemp >= 0); changed = true; @@ -10189,6 +10225,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& { ins->mCode = IC_LOAD_TEMPORARY; ins->mSrc[0] = lins->mSrc[0]; + ins->mSrc[0].mRestricted = ins->mDst.mRestricted = lins->mSrc[0].mRestricted; ins->mDst.mRange.Limit(ins->mSrc[0].mRange); ins->mNumOperands = 1; assert(ins->mSrc[0].mTemp >= 0); @@ -10252,6 +10289,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& assert(lins->mDst.mTemp >= 0); ins->mCode = IC_LOAD_TEMPORARY; ins->mSrc[0] = lins->mDst; + ins->mSrc[0].mRestricted = ins->mDst.mRestricted = lins->mDst.mRestricted; ins->mDst.mRange.Limit(ins->mSrc[0].mRange); ins->mNumOperands = 1; changed = true; @@ -10396,6 +10434,8 @@ void InterCodeBasicBlock::LocalRenameRegister(const GrowingIntArray& renameTable } } + RenameValueRanges(mEntryRenameTable, num); + for (i = 0; i < mInstructions.Size(); i++) { mInstructions[i]->LocalRenameRegister(mExitRenameTable, num); @@ -10440,11 +10480,29 @@ void InterCodeBasicBlock::GlobalRenameRegister(const GrowingIntArray& renameTabl mInstructions[i]->GlobalRenameRegister(renameTable, temporaries); } + RenameValueRanges(renameTable, temporaries.Size()); + if (mTrueJump) mTrueJump->GlobalRenameRegister(renameTable, temporaries); if (mFalseJump) mFalseJump->GlobalRenameRegister(renameTable, temporaries); } } +void InterCodeBasicBlock::RenameValueRanges(const GrowingIntArray& renameTable, int numTemps) +{ + if (mEntryValueRange.Size() > 0) + { + mLocalValueRange = mEntryValueRange; + mEntryValueRange.SetSize(numTemps, true); + for (int i = 0; i < mLocalValueRange.Size(); i++) + { + if (renameTable[i] >= 0) + { + mEntryValueRange[renameTable[i]].Limit(mLocalValueRange[i]); + } + } + } +} + void InterCodeBasicBlock::BuildCollisionTable(NumberSet* collisionSets) { if (!mVisited) @@ -13235,6 +13293,139 @@ bool InterCodeBasicBlock::CheapInlining(int & numTemps) return changed; } +void InterCodeBasicBlock::RemoveUnusedMallocs(void) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* mins = mInstructions[i]; + if (mins->mCode == IC_MALLOC) + { + int mtemp = mins->mDst.mTemp; + bool used = false; + int j = i + 1; + while (j < mInstructions.Size() && !used) + { + InterInstruction* fins = mInstructions[j]; + if (fins->mCode == IC_FREE && fins->mSrc[0].mTemp == mtemp) + break; + if (fins->ReferencesTemp(mtemp)) + { + if (fins->mCode != IC_STORE || fins->mSrc[1].mTemp != mtemp) + used = true; + } + j++; + } + + if (j < mInstructions.Size() && !used) + { + mins->mCode = IC_NONE; mins->mNumOperands = 0; + for (int k = i + 1; k <= j; k++) + { + InterInstruction* lins = mInstructions[k]; + if (lins->UsesTemp(mtemp)) + { + lins->mCode = IC_NONE; + lins->mNumOperands = 0; + } + } + } + } + } + + if (mTrueJump) mTrueJump->RemoveUnusedMallocs(); + if (mFalseJump) mFalseJump->RemoveUnusedMallocs(); + } +} + +void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue) +{ + if (!mVisited) + { + GrowingInstructionPtrArray ltvalue(tvalue); + + if (mLoopHead) + { + if (mNumEntries == 2 && (mTrueJump == this || mFalseJump == this)) + { + for (int i = 0; i < ltvalue.Size(); i++) + { + if (ltvalue[i]) + { + for (int j = 0; j < mInstructions.Size(); j++) + { + if (mInstructions[j]->mDst.mTemp == i) + { + if (mInstructions[j]->mCode == IC_LEA && mInstructions[j]->mSrc[1].mTemp == i) + ; + else + { + ltvalue[i] = nullptr; + break; + } + } + } + } + } + } + else + ltvalue.Clear(); + } + else if (mNumEntries > 0) + { + if (mNumEntered > 0) + { + for (int i = 0; i < ltvalue.Size(); i++) + { + if (mMergeTValues[i] != ltvalue[i]) + ltvalue[i] = nullptr; + } + } + + mNumEntered++; + + if (mNumEntered < mNumEntries) + { + mMergeTValues = ltvalue; + return; + } + } + + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* ins = mInstructions[i]; + + for (int j = 0; j < ins->mNumOperands; j++) + { + if (ins->mSrc[j].mTemp > 0 && ltvalue[ins->mSrc[j].mTemp] && ins->mSrc[j].mType == IT_POINTER) + ins->mSrc[j].mRestricted = ltvalue[ins->mSrc[j].mTemp]->mDst.mRestricted; + } + + if (ins->mDst.mTemp >= 0) + { + if (ins->mDst.mRestricted) + ltvalue[ins->mDst.mTemp] = ins; + else + ltvalue[ins->mDst.mTemp] = nullptr; + } + + if (ins->mCode == IC_LEA) + ins->mDst.mRestricted = ins->mSrc[1].mRestricted; + else if (ins->mCode == IC_LOAD_TEMPORARY) + ins->mDst.mRestricted = ins->mSrc[0].mRestricted; + } + + + if (mTrueJump) mTrueJump->PropagateMemoryAliasingInfo(ltvalue); + if (mFalseJump) mFalseJump->PropagateMemoryAliasingInfo(ltvalue); + } +} + void InterCodeBasicBlock::PushMoveOutOfLoop(void) { @@ -16570,7 +16761,8 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mAssembled(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), mCheckUnreachable(true), mReturnType(IT_NONE), mCheapInline(false), - mDeclaration(nullptr), mGlobalsChecked(false), mDispatchedCall(false) + mDeclaration(nullptr), mGlobalsChecked(false), mDispatchedCall(false), + mNumRestricted(1) { mID = mModule->mProcedures.Size(); mModule->mProcedures.Push(this); @@ -16636,6 +16828,11 @@ int InterCodeProcedure::AddTemporary(InterType type) return temp; } +int InterCodeProcedure::AddRestricted(void) +{ + return mNumRestricted++; +} + void InterCodeProcedure::CheckBlocks(void) { ResetVisited(); @@ -16699,6 +16896,10 @@ void InterCodeProcedure::BuildTraces(bool expand, bool dominators, bool compact) mBlocks[i]->mNumEntries = 0; mEntryBlock->CollectEntries(); + ResetEntryBlocks(); + ResetVisited(); + mEntryBlock->CollectEntryBlocks(nullptr); + ResetVisited(); for (int i = 0; i < mBlocks.Size(); i++) mBlocks[i]->mDominator = nullptr; @@ -16875,6 +17076,17 @@ void InterCodeProcedure::CheckUsedDefinedTemps(void) #endif } +void InterCodeProcedure::PropagateMemoryAliasingInfo(void) +{ + GrowingInstructionPtrArray tvalue(nullptr); + + ResetVisited(); + mEntryBlock->PropagateMemoryAliasingInfo(tvalue); + + Disassemble("PropagateMemoryAliasingInfo"); +} + + void InterCodeProcedure::WarnUsedUndefinedVariables(void) { ResetEntryBlocks(); @@ -17350,6 +17562,8 @@ void InterCodeProcedure::LoadStoreForwarding(InterMemory paramMemory) bool changed; do { + PropagateMemoryAliasingInfo(); + GrowingInstructionPtrArray gipa(nullptr); ResetVisited(); changed = mEntryBlock->LoadStoreForwarding(gipa, mModule->mGlobalVars); @@ -17358,11 +17572,15 @@ void InterCodeProcedure::LoadStoreForwarding(InterMemory paramMemory) RemoveUnusedStoreInstructions(paramMemory); + GlobalConstantPropagation(); + RemoveUnusedMallocs(); + TempForwarding(); RemoveUnusedInstructions(); DisassembleDebug("Load/Store forwarding"); } while (changed); + } void InterCodeProcedure::CombineIndirectAddressing(void) @@ -17434,7 +17652,8 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "atoi"); + CheckCase = false; mEntryBlock = mBlocks[0]; @@ -17589,6 +17808,8 @@ void InterCodeProcedure::Close(void) BuildDataFlowSets(); + LoadStoreForwarding(paramMemory); + ResetVisited(); mEntryBlock->OptimizeIntervalCompare(); @@ -17725,6 +17946,9 @@ void InterCodeProcedure::Close(void) Disassemble("gcp-"); #endif + BuildTraces(false); + DisassembleDebug("Rebuilt traces"); + BuildDataFlowSets(); TempForwarding(); @@ -17762,16 +17986,12 @@ void InterCodeProcedure::Close(void) ResetVisited(); mEntryBlock->SimplifyIntegerRangeRelops(); - DisassembleDebug("Simplified range limited relational ops"); + DisassembleDebug("Simplified range limited relational ops 1"); #endif BuildTraces(false); DisassembleDebug("Rebuilt traces"); - ResetEntryBlocks(); - ResetVisited(); - mEntryBlock->CollectEntryBlocks(nullptr); - #if 1 SimplifyIntegerNumeric(activeSet); @@ -17844,9 +18064,6 @@ void InterCodeProcedure::Close(void) #endif BuildTraces(false); - ResetEntryBlocks(); - ResetVisited(); - mEntryBlock->CollectEntryBlocks(nullptr); #if 1 SingleBlockLoopPointerSplit(activeSet); @@ -17927,7 +18144,7 @@ void InterCodeProcedure::Close(void) ResetVisited(); mEntryBlock->SimplifyIntegerRangeRelops(); - DisassembleDebug("Simplified range limited relational ops"); + DisassembleDebug("Simplified range limited relational ops 2"); #endif #if 1 @@ -17980,6 +18197,10 @@ void InterCodeProcedure::Close(void) LoadStoreForwarding(paramMemory); + CheckCase = true; + + RebuildIntegerRangeSet(); + #if 1 BuildLoopPrefix(); DisassembleDebug("added dominators"); @@ -18046,6 +18267,8 @@ void InterCodeProcedure::Close(void) mEntryBlock->CollectEntryBlocks(nullptr); BuildTraces(false); + BuildDataFlowSets(); + BuildTraces(false); #endif PropagateConstOperationsUp(); @@ -18057,6 +18280,11 @@ void InterCodeProcedure::Close(void) #endif + ResetVisited(); + mEntryBlock->SimplifyIntegerRangeRelops(); + + DisassembleDebug("Simplified range limited relational ops 3"); + #if 1 BuildDataFlowSets(); @@ -18111,7 +18339,7 @@ void InterCodeProcedure::Close(void) ResetVisited(); mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet, mModule->mGlobalVars); - DisassembleDebug("single block loop opt 3"); + DisassembleDebug("single block loop opt 4"); BuildDataFlowSets(); @@ -18130,6 +18358,8 @@ void InterCodeProcedure::Close(void) TempForwarding(); } while (GlobalConstantPropagation()); + BuildTraces(false); + DisassembleDebug("Rebuilt traces"); PeepholeOptimization(); TempForwarding(); @@ -18158,8 +18388,14 @@ void InterCodeProcedure::Close(void) CombineIndirectAddressing(); #if 1 - for (int i = 0; i < 4; i++) + for (int i = 0; i < 8; i++) { + BuildTraces(false); + + LoadStoreForwarding(paramMemory); + + RebuildIntegerRangeSet(); + PeepholeOptimization(); DisassembleDebug("Peephole Temp Check"); @@ -18793,6 +19029,12 @@ bool InterCodeProcedure::GlobalConstantPropagation(void) return mEntryBlock->PropagateConstTemps(ctemps); } +void InterCodeProcedure::RemoveUnusedMallocs(void) +{ + ResetVisited(); + mEntryBlock->RemoveUnusedMallocs(); +} + void InterCodeProcedure::HoistCommonConditionalPath(void) { for(;;) diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 4699e7d..a38b802 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -265,7 +265,7 @@ public: bool mFinal; int64 mIntConst; double mFloatConst; - int mVarIndex, mOperandSize, mStride; + int mVarIndex, mOperandSize, mStride, mRestricted; LinkerObject * mLinkerObject; InterMemory mMemory; IntegerValueRange mRange; @@ -457,6 +457,7 @@ public: void LocalRenameRegister(const GrowingIntArray& renameTable, int& num); void BuildGlobalRenameRegisterTable(const GrowingIntArray& renameTable, GrowingIntArray& globalRenameTable); void GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries); + void RenameValueRanges(const GrowingIntArray& renameTable, int numTemps); void CheckValueUsage(InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, const GrowingVariableArray& staticVars, FastNumberSet& fsingle); void PerformTempForwarding(const TempForwardingTable& forwardingTable, bool reverse, bool checkloops); @@ -555,7 +556,10 @@ public: void CollectLoopPath(const GrowingArray& body, GrowingArray& path); void InnerLoopOptimization(const NumberSet& aliasedParams); void PushMoveOutOfLoop(void); - + + void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue); + void RemoveUnusedMallocs(void); + bool CollectSingleHeadLoopBody(InterCodeBasicBlock* head, InterCodeBasicBlock* tail, GrowingArray& body); bool SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars); @@ -603,7 +607,7 @@ public: GrowingInterCodeBasicBlockPtrArray mBlocks; GrowingTypeArray mTemporaries; GrowingIntArray mTempOffset, mTempSizes; - int mTempSize, mCommonFrameSize, mCallerSavedTemps, mFreeCallerSavedTemps, mFastCallBase; + int mTempSize, mCommonFrameSize, mCallerSavedTemps, mFreeCallerSavedTemps, mFastCallBase, mNumRestricted; bool mLeafProcedure, mNativeProcedure, mCallsFunctionPointer, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode, mFastCallProcedure; bool mInterrupt, mHardwareInterrupt, mCompiled, mInterruptCalled, mValueReturn, mFramePointer, mDynamicStack, mAssembled; bool mDispatchedCall; @@ -633,6 +637,7 @@ public: ~InterCodeProcedure(void); int AddTemporary(InterType type); + int AddRestricted(void); void Close(void); @@ -682,10 +687,12 @@ protected: void CombineIndirectAddressing(void); void SingleTailLoopOptimization(InterMemory paramMemory); void HoistCommonConditionalPath(void); + void RemoveUnusedMallocs(void); void MergeBasicBlocks(void); void CheckUsedDefinedTemps(void); void WarnUsedUndefinedVariables(void); + void PropagateMemoryAliasingInfo(void); void PeepholeOptimization(void); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index f3ecaa6..28cd27c 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -2916,6 +2916,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mSrc[0].mTemp = vl.mTemp; ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ins->mDst.mRestricted = proc->AddRestricted(); block->Append(ins); return ExValue(exp->mDecType, ins->mDst.mTemp, 0); @@ -3141,6 +3142,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mNumOperands = 1; ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ins->mDst.mRestricted = proc->AddRestricted(); block->Append(ins); return ExValue(TheVoidPointerTypeDeclaration, ins->mDst.mTemp); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 642b288..8797913 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -32138,7 +32138,7 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(NativeCodeProcedure* proc) ExpandingArray lblocks; proc->ResetPatched(); - if (CollectGenericLoop(proc, lblocks)) + if (CollectSingleEntryGenericLoop(proc, lblocks)) { int yreg = -1, xreg = -1, areg = -1; int zyreg[NUM_REGS], zxreg[NUM_REGS], zareg[NUM_REGS]; @@ -32777,6 +32777,28 @@ bool NativeCodeBasicBlock::CollectGenericLoop(NativeCodeProcedure* proc, Expandi return lblocks.Size() > 0; } +bool NativeCodeBasicBlock::CollectSingleEntryGenericLoop(NativeCodeProcedure* proc, ExpandingArray& lblocks) +{ + if (CollectGenericLoop(proc, lblocks)) + { + for (int i = 0; i < lblocks.Size(); i++) + { + NativeCodeBasicBlock* block = lblocks[i]; + + if (block != this) + { + for (int j = 0; j < block->mEntryBlocks.Size(); j++) + if (!lblocks.Contains(block->mEntryBlocks[j])) + return false; + } + } + + return true; + } + else + return false; +} + bool NativeCodeBasicBlock::OptimizeFindLoop(NativeCodeProcedure* proc) { bool changed = false; @@ -41426,7 +41448,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "fill_row"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "atoi"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -42276,7 +42298,6 @@ void NativeCodeProcedure::Optimize(void) if (mEntryBlock->RemoveDoubleZPStore()) changed = true; } - if (step == 3 || step == 5 || step == 9) { ResetVisited(); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 5975eaf..6ec4307 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -307,6 +307,7 @@ public: bool OptimizeGenericLoop(NativeCodeProcedure* proc); bool CollectGenericLoop(NativeCodeProcedure* proc, ExpandingArray& lblocks); + bool CollectSingleEntryGenericLoop(NativeCodeProcedure* proc, ExpandingArray& lblocks); void CollectReachable(ExpandingArray& lblock); bool OptimizeFindLoop(NativeCodeProcedure* proc); From 9156db9c32fde1f93b3d54bc6dc7d5143b67d046 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 14 Oct 2023 13:43:11 +0200 Subject: [PATCH 147/169] Restart integer range estimation from full state --- oscar64/InterCode.cpp | 351 +++++++++++++++++++++++++++++--- oscar64/InterCode.h | 24 ++- oscar64/NativeCodeGenerator.cpp | 351 +++++++++++++++++++++++++++++++- oscar64/NativeCodeGenerator.h | 3 + oscar64/NumberSet.cpp | 28 +++ oscar64/NumberSet.h | 4 + 6 files changed, 728 insertions(+), 33 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index ee838e9..1b1b5f0 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -45,6 +45,14 @@ void IntegerValueRange::Reset(void) mMaxExpanded = 0; } +void IntegerValueRange::Restart(void) +{ + if (mMinState == IntegerValueRange::S_UNBOUND) + mMinState = IntegerValueRange::S_UNKNOWN; + if (mMaxState == IntegerValueRange::S_UNBOUND) + mMaxState = IntegerValueRange::S_UNKNOWN; +} + bool IntegerValueRange::Same(const IntegerValueRange& range) const { @@ -115,6 +123,26 @@ bool IntegerValueRange::IsConstant(void) const return mMinState == S_BOUND && mMaxState == S_BOUND && mMinValue == mMaxValue; } +void IntegerValueRange::MergeUnknown(const IntegerValueRange& range) +{ + if (mMinState != S_BOUND) + { + mMinState = range.mMinState; + mMinValue = range.mMinValue; + } + else if (range.mMinState == S_BOUND && mMinValue < range.mMinValue) + mMinValue = range.mMinValue; + + if (mMaxState != S_BOUND) + { + mMaxState = range.mMaxState; + mMaxValue = range.mMaxValue; + } + else if (range.mMaxState == S_BOUND && mMaxValue > range.mMaxValue) + mMaxValue = range.mMaxValue; +} + + void IntegerValueRange::Limit(const IntegerValueRange& range) { if (range.mMinState == S_BOUND) @@ -160,6 +188,30 @@ void IntegerValueRange::Expand(const IntegerValueRange& range) } } +void IntegerValueRange::Union(const IntegerValueRange& range) +{ + if (range.mMinState == S_UNBOUND || mMinState == S_UNBOUND) + mMinState = S_UNBOUND; + else if (range.mMinState == S_UNKNOWN || mMinState == S_UNKNOWN) + mMinState = S_UNKNOWN; + else + { + mMinValue = int64min(mMinValue, range.mMinValue); + if (range.mMinState == S_WEAK) + mMinState = S_WEAK; + } + if (range.mMaxState == S_UNBOUND || mMaxState == S_UNBOUND) + mMaxState = S_UNBOUND; + else if (range.mMaxState == S_UNKNOWN || mMaxState == S_UNKNOWN) + mMaxState = S_UNKNOWN; + else + { + mMaxValue = int64max(mMaxValue, range.mMaxValue); + if (range.mMaxState == S_WEAK) + mMaxState = S_WEAK; + } +} + bool IntegerValueRange::Merge(const IntegerValueRange& range, bool head, bool initial) { bool changed = false; @@ -3231,6 +3283,44 @@ void InterInstruction::FilterStaticVarsUsage(const GrowingVariableArray& staticV } } +void InterInstruction::FilterStaticVarsByteUsage(const GrowingVariableArray& staticVars, NumberSet& requiredVars, NumberSet& providedVars) +{ + if (mCode == IC_LOAD) + { + if (mSrc[0].mMemory == IM_INDIRECT) + { + if (!mSrc[0].mRestricted) + { + for (int i = 0; i < staticVars.Size(); i++) + { + if (staticVars[i]->mAliased && !providedVars[i]) + requiredVars.AddRange(staticVars[i]->mByteIndex, staticVars[i]->mSize); + } + } + } + else if (mSrc[0].mMemory == IM_GLOBAL) + { + if (mSrc[0].mVarIndex >= 0 && !providedVars.RangeFilled(staticVars[mSrc[0].mVarIndex]->mByteIndex + int(mSrc[0].mIntConst), InterTypeSize[mDst.mType])) + requiredVars.AddRange(staticVars[mSrc[0].mVarIndex]->mByteIndex + int(mSrc[0].mIntConst), InterTypeSize[mDst.mType]); + } + } + else if (mCode == IC_STORE) + { + if (mSrc[1].mMemory == IM_INDIRECT) + { + } + else if (mSrc[1].mMemory == IM_GLOBAL) + { + if (mSrc[1].mVarIndex >= 0) + providedVars.AddRange(staticVars[mSrc[1].mVarIndex]->mByteIndex + int(mSrc[1].mIntConst), InterTypeSize[mSrc[0].mType]); + } + } + else if (mCode == IC_COPY || mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE || mCode == IC_STRCPY || mCode == IC_DISPATCH) + { + requiredVars.OrNot(providedVars); + } +} + void InterInstruction::FilterVarsUsage(const GrowingVariableArray& localVars, NumberSet& requiredVars, NumberSet& providedVars, const GrowingVariableArray& params, NumberSet& requiredParams, NumberSet& providedParams, InterMemory paramMemory) { if (mCode == IC_LOAD) @@ -3878,6 +3968,57 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(InterCodeBasicBlock* return changed; } +bool InterInstruction::RemoveUnusedStaticStoreByteInstructions(InterCodeBasicBlock* block, const GrowingVariableArray& staticVars, NumberSet& requiredVars) +{ + bool changed = false; + + if (mCode == IC_LOAD) + { + if (mSrc[0].mMemory == IM_INDIRECT) + { + if (!mSrc[0].mRestricted) + { + for (int i = 0; i < staticVars.Size(); i++) + { + if (staticVars[i]->mAliased) + requiredVars.AddRange(staticVars[i]->mByteIndex, staticVars[i]->mSize); + } + } + } + else if (mSrc[0].mMemory == IM_GLOBAL) + { + if (mSrc[0].mVarIndex >= 0) + requiredVars.AddRange(staticVars[mSrc[0].mVarIndex]->mByteIndex + int(mSrc[0].mIntConst), InterTypeSize[mDst.mType]); + } + } + else if (mCode == IC_STORE) + { + if (mSrc[1].mMemory == IM_GLOBAL && mSrc[1].mVarIndex >= 0) + { + if (!requiredVars.RangeClear(staticVars[mSrc[1].mVarIndex]->mByteIndex + int(mSrc[1].mIntConst), InterTypeSize[mSrc[0].mType])) + { + requiredVars.SubRange(staticVars[mSrc[1].mVarIndex]->mByteIndex + int(mSrc[1].mIntConst), InterTypeSize[mSrc[0].mType]); + } + else if (!mVolatile) + { + mSrc[0].mTemp = -1; + mCode = IC_NONE; + changed = true; + } + } + } + else if (mCode == IC_COPY || mCode == IC_STRCPY) + { + requiredVars.Fill(); + } + else if (mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE || mCode == IC_DISPATCH) + { + requiredVars.Fill(); + } + + return changed; +} + int InterInstruction::NumUsedTemps(void) const { int n = 0; @@ -4112,6 +4253,13 @@ void InterInstruction::CollectSimpleLocals(FastNumberSet& complexLocals, FastNum } } +void InterInstruction::UnionRanges(InterInstruction* ins) +{ + mDst.mRange.Union(ins->mDst.mRange); + for(int i=0; imSrc[i].mRange); +} + void InterInstruction::SimpleLocalToTemp(int vindex, int temp) { switch (mCode) @@ -4644,7 +4792,7 @@ InterCodeBasicBlock::InterCodeBasicBlock(InterCodeProcedure * proc) mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mMergeAValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mLoopPrefix(nullptr), mDominator(nullptr), mEntryValueRange(IntegerValueRange()), mTrueValueRange(IntegerValueRange()), mFalseValueRange(IntegerValueRange()), mLocalValueRange(IntegerValueRange()), mEntryParamValueRange(IntegerValueRange()), mTrueParamValueRange(IntegerValueRange()), mFalseParamValueRange(IntegerValueRange()), mLocalParamValueRange(IntegerValueRange()), - mReverseValueRange(IntegerValueRange()), mEntryBlocks(nullptr), mLoadStoreInstructions(nullptr), mLoopPathBlocks(nullptr), mMemoryValueSize(0), mEntryMemoryValueSize(0) + mReverseValueRange(IntegerValueRange()), mLoadStoreInstructions(nullptr), mMemoryValueSize(0), mEntryMemoryValueSize(0) { mVisited = false; mInPath = false; @@ -4816,6 +4964,8 @@ void InterCodeBasicBlock::GenerateTraces(bool expand, bool compact) if (mInPath) mLoopHead = true; + assert(mIndex != 0 || !mLoopHead); + if (!mVisited) { mVisited = true; @@ -6559,6 +6709,29 @@ static int64 BuildLowerBitsMask(int64 v) return v; } +void InterCodeBasicBlock::UnionIntegerRanges(const InterCodeBasicBlock* block) +{ + if (mEntryValueRange.Size() > 0) + { + if (block->mEntryValueRange.Size()) + { + assert(mEntryValueRange.Size() == block->mEntryValueRange.Size()); + + for (int i = 0; i < mEntryValueRange.Size(); i++) + mEntryValueRange[i].Union(block->mEntryValueRange[i]); + } + else + mEntryValueRange.SetSize(0); + } + + for (int i = 0; i < mInstructions.Size(); i++) + { + assert(mInstructions[i]->IsEqual(block->mInstructions[i])); + mInstructions[i]->UnionRanges(block->mInstructions[i]); + } + +} + void InterCodeBasicBlock::MarkIntegerRangeBoundUp(int temp, int64 value, GrowingIntegerValueRangeArray& range) { range[temp].SetLimit(value, value); @@ -6675,7 +6848,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray { if (ins->mSrc[i].mTemp >= 0) { - ins->mSrc[i].mRange = mLocalValueRange[ins->mSrc[i].mTemp]; + ins->mSrc[i].mRange.MergeUnknown(mLocalValueRange[ins->mSrc[i].mTemp]); #if 1 if (ins->mCode != IC_ASSEMBLER&& ins->mSrc[i].mRange.mMinState == IntegerValueRange::S_BOUND && ins->mSrc[i].mRange.mMaxState == IntegerValueRange::S_BOUND && ins->mSrc[i].mRange.mMinValue == ins->mSrc[i].mRange.mMaxValue) { @@ -7324,7 +7497,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray vr.LimitMaxBound(65535); } #endif - ins->mDst.mRange = vr; + ins->mDst.mRange.MergeUnknown(vr); #if 1 if (vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMinState == IntegerValueRange::S_BOUND && vr.mMaxValue == vr.mMinValue) { @@ -7850,21 +8023,16 @@ void InterCodeBasicBlock::RestartLocalIntegerRangeSets(int num, const GrowingVar mLocalParamValueRange.SetSize(paramVars.Size(), false); for (int i = 0; i < mEntryValueRange.Size(); i++) - { - IntegerValueRange& vr(mEntryValueRange[i]); - if (vr.mMinState == IntegerValueRange::S_UNBOUND) - vr.mMinState = IntegerValueRange::S_UNKNOWN; - if (vr.mMaxState == IntegerValueRange::S_UNBOUND) - vr.mMaxState = IntegerValueRange::S_UNKNOWN; - } + mEntryValueRange[i].Restart(); for (int i = 0; i < mEntryParamValueRange.Size(); i++) + mEntryParamValueRange[i].Restart(); + + for (int i = 0; i < mInstructions.Size(); i++) { - IntegerValueRange& vr(mEntryParamValueRange[i]); - if (vr.mMinState == IntegerValueRange::S_UNBOUND) - vr.mMinState = IntegerValueRange::S_UNKNOWN; - if (vr.mMaxState == IntegerValueRange::S_UNBOUND) - vr.mMaxState = IntegerValueRange::S_UNKNOWN; + mInstructions[i]->mDst.mRange.Restart(); + for (int j = 0; j < mInstructions[i]->mNumOperands; j++) + mInstructions[i]->mSrc[j].mRange.Restart(); } UpdateLocalIntegerRangeSets(localVars, paramVars); @@ -8335,7 +8503,7 @@ void InterCodeBasicBlock::PerformTempForwarding(const TempForwardingTable& forwa } else if (mLoopPrefix && checkloops) { - GrowingArray body(nullptr); + ExpandingArray body; body.Push(this); bool innerLoop = true; @@ -8619,6 +8787,67 @@ bool InterCodeBasicBlock::RemoveUnusedStaticStoreInstructions(const GrowingVaria return changed; } + +void InterCodeBasicBlock::BuildStaticVariableByteSet(const GrowingVariableArray& staticVars, int bsize) +{ + if (!mVisited) + { + mVisited = true; + + mLocalRequiredStatics = NumberSet(bsize); + mLocalProvidedStatics = NumberSet(bsize); + + mEntryRequiredStatics = NumberSet(bsize); + mEntryProvidedStatics = NumberSet(bsize); + mExitRequiredStatics = NumberSet(bsize); + mExitProvidedStatics = NumberSet(bsize); + + for (int i = 0; i < mInstructions.Size(); i++) + mInstructions[i]->FilterStaticVarsByteUsage(staticVars, mLocalRequiredStatics, mLocalProvidedStatics); + + mEntryRequiredStatics = mLocalRequiredStatics; + mExitProvidedStatics = mLocalProvidedStatics; + + if (mTrueJump) mTrueJump->BuildStaticVariableByteSet(staticVars, bsize); + if (mFalseJump) mFalseJump->BuildStaticVariableByteSet(staticVars, bsize); + } +} + +bool InterCodeBasicBlock::RemoveUnusedStaticStoreByteInstructions(const GrowingVariableArray& staticVars, int bsize) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + NumberSet requiredVars(mExitRequiredStatics); + + int i; + + for (i = mInstructions.Size() - 1; i >= 0; i--) + { + if (mInstructions[i]->RemoveUnusedStaticStoreByteInstructions(this, staticVars, requiredVars)) + changed = true; + } + + if (mTrueJump) + { + if (mTrueJump->RemoveUnusedStaticStoreByteInstructions(staticVars, bsize)) + changed = true; + } + if (mFalseJump) + { + if (mFalseJump->RemoveUnusedStaticStoreByteInstructions(staticVars, bsize)) + changed = true; + } + } + + return changed; +} + + + void InterCodeBasicBlock::BuildLocalVariableSets(const GrowingVariableArray& localVars, const GrowingVariableArray& params, InterMemory paramMemory) { int i; @@ -11145,7 +11374,7 @@ bool InterCodeBasicBlock::ForwardLoopMovedTemp(void) else if (mTrueJump->mFalseJump == mTrueJump) eblock = mTrueJump->mTrueJump; - if (eblock) + if (eblock && eblock->mNumEntries == 1) { int i = mInstructions.Size() - 1; while (i >= 0) @@ -12277,7 +12506,7 @@ InterCodeBasicBlock* InterCodeBasicBlock::BuildLoopPrefix(void) return mLoopPrefix ? mLoopPrefix : this; } -bool InterCodeBasicBlock::CollectLoopBody(InterCodeBasicBlock* head, GrowingArray & body) +bool InterCodeBasicBlock::CollectLoopBody(InterCodeBasicBlock* head, ExpandingArray & body) { if (mLoopHead) return this == head; @@ -12293,7 +12522,7 @@ bool InterCodeBasicBlock::CollectLoopBody(InterCodeBasicBlock* head, GrowingArra return true; } -bool InterCodeBasicBlock::CollectLoopBodyRecursive(InterCodeBasicBlock* head, GrowingArray& body) +bool InterCodeBasicBlock::CollectLoopBodyRecursive(InterCodeBasicBlock* head, ExpandingArray& body) { if (this == head) return true; @@ -12309,7 +12538,7 @@ bool InterCodeBasicBlock::CollectLoopBodyRecursive(InterCodeBasicBlock* head, Gr return true; } -void InterCodeBasicBlock::CollectLoopPath(const GrowingArray& body, GrowingArray& path) +void InterCodeBasicBlock::CollectLoopPath(const ExpandingArray& body, ExpandingArray& path) { if (body.IndexOf(this) >= 0) { @@ -12320,7 +12549,7 @@ void InterCodeBasicBlock::CollectLoopPath(const GrowingArrayCollectLoopPath(body, mLoopPathBlocks); if (mFalseJump) { - GrowingArray fpath(nullptr); + ExpandingArray fpath; if (!mFalseJump->mLoopHead) mFalseJump->CollectLoopPath(body, fpath); @@ -12526,8 +12755,12 @@ bool InterCodeBasicBlock::SingleTailLoopOptimization(const NumberSet& aliasedPar mins->mConst.mType = ai->mDst.mType; mins->mConst.mIntConst = num; mins->mDst = ai->mDst; + mins->mDst.mRange.SetLimit(num, num); mLoopPrefix->mInstructions.Insert(mLoopPrefix->mInstructions.Size() - 1, mins); + if (mEntryValueRange.Size()) + mEntryValueRange[ai->mSrc[1].mTemp].SetLimit(1, num); + ai->mSrc[1].mRange.SetLimit(1, num); ai->mDst.mRange.SetLimit(0, num - 1); ci->mSrc[1].mRange.SetLimit(0, num - 1); @@ -12731,7 +12964,7 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) if (mLoopHead) { - GrowingArray body(nullptr), path(nullptr); + ExpandingArray body, path; body.Push(this); bool innerLoop = true; @@ -13541,7 +13774,7 @@ void InterCodeBasicBlock::PushMoveOutOfLoop(void) bool InterCodeBasicBlock::CheckSingleBlockLimitedLoop(InterCodeBasicBlock*& pblock, int64& nloop) { - if (mLoopHead && mNumEntries == 2 && mFalseJump && (mTrueJump == this || mFalseJump == this) && mInstructions.Size() > 3) + if (mLoopHead && mEntryBlocks.Size() == 2 && mFalseJump && (mTrueJump == this || mFalseJump == this) && mInstructions.Size() > 3) { int nins = mInstructions.Size(); @@ -14857,7 +15090,10 @@ void InterCodeBasicBlock::CheckBlocks(void) for (int i = 0; i < mInstructions.Size(); i++) assert(mInstructions[i] != nullptr); - + + assert(!mTrueJump || mTrueJump->mIndex > 0); + assert(!mFalseJump || mFalseJump->mIndex > 0); + if (mTrueJump) mTrueJump->CheckBlocks(); if (mFalseJump) mFalseJump->CheckBlocks(); } @@ -17163,6 +17399,43 @@ void InterCodeProcedure::RemoveUnusedLocalStoreInstructions(void) } } +void InterCodeProcedure::RemoveUnusedPartialStoreInstructions(void) +{ + if (mCompilerOptions & COPT_OPTIMIZE_BASIC) + { + if (mModule->mGlobalVars.Size()) + { + int byteIndex = 0; + for (int i = 0; i < mModule->mGlobalVars.Size(); i++) + { + if (mModule->mGlobalVars[i]) + { + mModule->mGlobalVars[i]->mByteIndex = byteIndex; + byteIndex += mModule->mGlobalVars[i]->mSize; + } + } + + do { + ResetVisited(); + mEntryBlock->BuildStaticVariableByteSet(mModule->mGlobalVars, byteIndex); + + ResetVisited(); + mEntryBlock->BuildGlobalProvidedStaticVariableSet(mModule->mGlobalVars, NumberSet(byteIndex)); + + NumberSet totalRequired2(byteIndex); + + do { + ResetVisited(); + } while (mEntryBlock->BuildGlobalRequiredStaticVariableSet(mModule->mGlobalVars, totalRequired2)); + + ResetVisited(); + } while (mEntryBlock->RemoveUnusedStaticStoreByteInstructions(mModule->mGlobalVars, byteIndex)); + + DisassembleDebug("removed unused static byte stores"); + } + } +} + void InterCodeProcedure::RemoveUnusedStoreInstructions(InterMemory paramMemory) { if (mCompilerOptions & COPT_OPTIMIZE_BASIC) @@ -17652,7 +17925,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "atoi"); + CheckFunc = !strcmp(mIdent->mString, "ftoa"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -18136,6 +18409,8 @@ void InterCodeProcedure::Close(void) Disassemble("gcp-"); #endif + CheckCase = true; + #if 1 RebuildIntegerRangeSet(); #endif @@ -18349,17 +18624,27 @@ void InterCodeProcedure::Close(void) } #endif + DisassembleDebug("PreLoopTemp"); BuildDataFlowSets(); ResetVisited(); mEntryBlock->ForwardLoopMovedTemp(); + DisassembleDebug("PostLoopTemp"); + CheckFinal(); + DisassembleDebug("PreConstP"); #if 1 do { + DisassembleDebug("InConstP"); + CheckFinal(); TempForwarding(); + CheckFinal(); } while (GlobalConstantPropagation()); + CheckFinal(); BuildTraces(false); DisassembleDebug("Rebuilt traces"); + CheckFinal(); + PeepholeOptimization(); TempForwarding(); @@ -18404,8 +18689,12 @@ void InterCodeProcedure::Close(void) ReduceTemporaries(); + CheckBlocks(); + MergeBasicBlocks(); + CheckBlocks(); + DisassembleDebug("TempForward Rev 1"); BuildDataFlowSets(); @@ -18414,6 +18703,8 @@ void InterCodeProcedure::Close(void) RemoveUnusedInstructions(); + CheckBlocks(); + BuildDataFlowSets(); DisassembleDebug("TempForward Rev 2"); @@ -18422,6 +18713,8 @@ void InterCodeProcedure::Close(void) DisassembleDebug("TempForward Rev 3"); + CheckBlocks(); + BuildLoopPrefix(); BuildDataFlowSets(); @@ -18467,6 +18760,8 @@ void InterCodeProcedure::Close(void) } #endif + RemoveUnusedPartialStoreInstructions(); + MapVariables(); DisassembleDebug("mapped variabled"); @@ -18824,9 +19119,11 @@ void InterCodeProcedure::MergeBasicBlocks(void) if (block->mNumEntries) { int j = 0; - while (j < i && !(mBlocks[j]->mNumEntries && mBlocks[j]->IsEqual(block))) + while (j < i && !(mBlocks[j]->mNumEntries && mBlocks[j]->IsEqual(block) && mBlocks[j]->mIndex != 0)) j++; blockMap[i] = mBlocks[j]; + if (i != j) + mBlocks[j]->UnionIntegerRanges(block); } } @@ -18934,6 +19231,8 @@ void InterCodeProcedure::MergeBasicBlocks(void) { assert(mblocks[j]->mInstructions[mblocks[j]->mInstructions.Size() - 1]->mCode == IC_JUMP); assert(mblocks[j]->mInstructions[mblocks[j]->mInstructions.Size() - 2]->IsEqual(ins)); + + ins->UnionRanges(mblocks[j]->mInstructions[mblocks[j]->mInstructions.Size() - 2]); mblocks[j]->mInstructions.Remove(mblocks[j]->mInstructions.Size() - 2); } diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index a38b802..3169011 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -148,6 +148,7 @@ public: ~IntegerValueRange(void); void Reset(void); + void Restart(void); int64 mMinValue, mMaxValue; int mMinExpanded, mMaxExpanded; @@ -163,8 +164,10 @@ public: bool Same(const IntegerValueRange& range) const; bool Merge(const IntegerValueRange& range, bool head, bool initial); void Expand(const IntegerValueRange& range); + void Union(const IntegerValueRange& range); void Limit(const IntegerValueRange& range); + void MergeUnknown(const IntegerValueRange& range); void SetLimit(int64 minValue, int64 maxValue); bool IsConstant(void) const; @@ -245,7 +248,7 @@ class InterVariable { public: bool mUsed, mAliased, mTemp; - int mIndex, mSize, mOffset, mTempIndex; + int mIndex, mSize, mOffset, mTempIndex, mByteIndex; int mNumReferences; const Ident * mIdent; LinkerObject * mLinkerObject; @@ -318,10 +321,12 @@ public: void FilterTempUsage(NumberSet& requiredTemps, NumberSet& providedTemps); void FilterVarsUsage(const GrowingVariableArray& localVars, NumberSet& requiredVars, NumberSet& providedVars, const GrowingVariableArray& params, NumberSet& requiredParams, NumberSet& providedParams, InterMemory paramMemory); void FilterStaticVarsUsage(const GrowingVariableArray& staticVars, NumberSet& requiredVars, NumberSet& providedVars); - + void FilterStaticVarsByteUsage(const GrowingVariableArray& staticVars, NumberSet& requiredVars, NumberSet& providedVars); + bool RemoveUnusedResultInstructions(InterInstruction* pre, NumberSet& requiredTemps); bool RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars, NumberSet& requiredVars, const GrowingVariableArray& params, NumberSet& requiredParams, InterMemory paramMemory); bool RemoveUnusedStaticStoreInstructions(InterCodeBasicBlock * block, const GrowingVariableArray& staticVars, NumberSet& requiredVars, GrowingInstructionPtrArray& storeIns); + bool RemoveUnusedStaticStoreByteInstructions(InterCodeBasicBlock* block, const GrowingVariableArray& staticVars, NumberSet& requiredVars); void PerformValueForwarding(GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid); void BuildCallerSaveTempSet(NumberSet& requiredTemps, NumberSet& callerSaveTemps); @@ -343,6 +348,8 @@ public: bool ConstantFolding(void); bool ConstantFoldingRelationRange(void); + void UnionRanges(InterInstruction* ins); + void Disassemble(FILE* file, InterCodeProcedure * proc); }; @@ -381,7 +388,7 @@ public: GrowingArray mMemoryValueSize, mEntryMemoryValueSize; - GrowingArray mEntryBlocks, mLoopPathBlocks; + ExpandingArray mEntryBlocks, mLoopPathBlocks; GrowingInstructionPtrArray mMergeTValues, mMergeAValues; ValueSet mMergeValues; @@ -435,6 +442,9 @@ public: bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars); bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars); + void BuildStaticVariableByteSet(const GrowingVariableArray& staticVars, int bsize); + bool RemoveUnusedStaticStoreByteInstructions(const GrowingVariableArray& staticVars, int bsize); + bool CheckSingleBlockLimitedLoop(InterCodeBasicBlock*& pblock, int64 & nloop); void RestartLocalIntegerRangeSets(int num, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars); @@ -443,6 +453,7 @@ public: bool BuildGlobalIntegerRangeSets(bool initial, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars); void SimplifyIntegerRangeRelops(void); void MarkIntegerRangeBoundUp(int temp, int64 value, GrowingIntegerValueRangeArray& range); + void UnionIntegerRanges(const InterCodeBasicBlock* block); bool CombineIndirectAddressing(void); @@ -551,9 +562,9 @@ public: void SingleBlockLoopUnrolling(void); bool SingleBlockLoopPointerSplit(int& spareTemps); bool SingleBlockLoopPointerToByte(int& spareTemps); - bool CollectLoopBody(InterCodeBasicBlock* head, GrowingArray & body); - bool CollectLoopBodyRecursive(InterCodeBasicBlock* head, GrowingArray& body); - void CollectLoopPath(const GrowingArray& body, GrowingArray& path); + bool CollectLoopBody(InterCodeBasicBlock* head, ExpandingArray & body); + bool CollectLoopBodyRecursive(InterCodeBasicBlock* head, ExpandingArray& body); + void CollectLoopPath(const ExpandingArray& body, ExpandingArray& path); void InnerLoopOptimization(const NumberSet& aliasedParams); void PushMoveOutOfLoop(void); @@ -670,6 +681,7 @@ protected: void BuildLoopPrefix(void); void SingleAssignmentForwarding(void); void RemoveUnusedStoreInstructions(InterMemory paramMemory); + void RemoveUnusedPartialStoreInstructions(void); void RemoveUnusedLocalStoreInstructions(void); void MergeCommonPathInstructions(void); void PushSinglePathResultInstructions(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 8797913..bfdd59e 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -17948,6 +17948,183 @@ bool NativeCodeBasicBlock::RemoveDoubleZPStore(void) return changed; } +struct ValueNumbers +{ + int zvalues[256], avalue, xvalue, yvalue; + int ivalue = 0; + + void Reset(void) + { + for (int i = 0; i < 256; i++) + zvalues[i] = ivalue++; + avalue = ivalue++; + xvalue = ivalue++; + yvalue = ivalue++; + } + +}; + +bool NativeCodeBasicBlock::LocalZeroPageValueNumbering(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + ValueNumbers vn; + vn.Reset(); + + for (int i = 0; i < mIns.Size(); i++) + { + NativeCodeInstruction& ins = mIns[i]; + + if (ins.mType == ASMIT_LDA && ins.mMode == ASMIM_ZERO_PAGE) + { + if (vn.avalue == vn.zvalues[ins.mAddress]) + { + if (ins.mLive & LIVE_CPU_REG_Z) + { + ins.mType = ASMIT_ORA; + ins.mMode = ASMIM_IMMEDIATE; + ins.mAddress = 0; + changed = true; + } + else + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + changed = true; + } + } + else + vn.avalue = vn.zvalues[ins.mAddress]; + } + else if (ins.mType == ASMIT_LDX && ins.mMode == ASMIM_ZERO_PAGE) + { + if (vn.xvalue == vn.zvalues[ins.mAddress] && !(ins.mLive & LIVE_CPU_REG_Z)) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + changed = true; + } + else + vn.xvalue = vn.zvalues[ins.mAddress]; + } + else if (ins.mType == ASMIT_LDY && ins.mMode == ASMIM_ZERO_PAGE) + { + if (vn.yvalue == vn.zvalues[ins.mAddress] && !(ins.mLive & LIVE_CPU_REG_Z)) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + changed = true; + } + else + vn.yvalue = vn.zvalues[ins.mAddress]; + } + else if (ins.mType == ASMIT_STA && ins.mMode == ASMIM_ZERO_PAGE) + { + if (vn.avalue == vn.zvalues[ins.mAddress]) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + changed = true; + } + else + vn.zvalues[ins.mAddress] = vn.avalue; + } + else if (ins.mType == ASMIT_STX && ins.mMode == ASMIM_ZERO_PAGE) + { + if (vn.xvalue == vn.zvalues[ins.mAddress]) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + changed = true; + } + else + vn.zvalues[ins.mAddress] = vn.xvalue; + } + else if (ins.mType == ASMIT_STY && ins.mMode == ASMIM_ZERO_PAGE) + { + if (vn.yvalue == vn.zvalues[ins.mAddress]) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + changed = true; + } + else + vn.zvalues[ins.mAddress] = vn.yvalue; + } + else if (ins.mType == ASMIT_TAX) + { + if (vn.avalue == vn.xvalue && !(ins.mLive & LIVE_CPU_REG_Z)) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + changed = true; + } + else + vn.xvalue = vn.avalue; + } + else if (ins.mType == ASMIT_TAY) + { + if (vn.avalue == vn.yvalue && !(ins.mLive & LIVE_CPU_REG_Z)) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + changed = true; + } + else + vn.yvalue = vn.avalue; + } + else if (ins.mType == ASMIT_TXA) + { + if (vn.xvalue == vn.avalue && !(ins.mLive & LIVE_CPU_REG_Z)) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + changed = true; + } + else + vn.avalue = vn.xvalue; + } + else if (ins.mType == ASMIT_TYA) + { + if (vn.yvalue == vn.avalue && !(ins.mLive & LIVE_CPU_REG_Z)) + { + ins.mType = ASMIT_NOP; + ins.mMode = ASMIM_IMPLIED; + changed = true; + } + else + vn.avalue = vn.yvalue; + } + else if (ins.mType == ASMIT_JSR) + vn.Reset(); + else + { + if (ins.ChangesAccu()) + vn.avalue = vn.ivalue++; + if (ins.ChangesXReg()) + vn.xvalue = vn.ivalue++; + if (ins.ChangesYReg()) + vn.yvalue = vn.ivalue++; + if (ins.mMode == ASMIM_ZERO_PAGE && ins.ChangesAddress()) + vn.zvalues[ins.mAddress] = vn.ivalue++; + } + } + + + if (mTrueJump && mTrueJump->LocalZeroPageValueNumbering()) + changed = true; + + if (mFalseJump && mFalseJump->LocalZeroPageValueNumbering()) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::LocalRegisterXYMap(void) { bool changed = false; @@ -27176,6 +27353,50 @@ bool NativeCodeBasicBlock::FoldShiftORAIntoLoadImmUp(int at) return false; } +// TAX +// CLC +// ADC #1, 2, 3 +// STA +// +// convert to INX/DEX/STX when X not needed anymore + +bool NativeCodeBasicBlock::MoveTAXADCSTADown(int at) +{ + int n = mIns[at + 2].mAddress; + int addr = mIns[at + 3].mAddress; + + int si = at + 4; + while (si < mIns.Size()) + { + if (!(mIns[si].mLive & LIVE_CPU_REG_X)) + { + if (mIns[si].mLive & LIVE_CPU_REG_Z) + return false; + + mIns[si].mLive |= LIVE_CPU_REG_X; + si++; + + for (int i = 0; i < n; i++) + { + mIns.Insert(si, NativeCodeInstruction(mIns[at].mIns, ASMIT_INX)); + si++; + } + mIns.Insert(si, NativeCodeInstruction(mIns[at].mIns, ASMIT_STX, ASMIM_ZERO_PAGE, addr)); + return true; + } + + if (mIns[si].ChangesXReg()) + return false; + if (mIns[si].ReferencesZeroPage(addr)) + return false; + + si++; + } + + return false; +} + + // CLC // LDA zp0 // ADC #1, 2, 3 @@ -31487,7 +31708,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc, bool f { // check for usage of Y register - bool yother = false, yindex = false; + bool yother = false, yindex = false, xother = false, xindex = false; int zreg = mIns[sz - 1].mAddress; int yinc = 0, xinc = 0; @@ -31495,6 +31716,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc, bool f if (mIns[sz - 1].mLive & LIVE_CPU_REG_Y) yother = true; + if (mIns[sz - 1].mLive & LIVE_CPU_REG_X) + xother = true; for (int i = 0; i < sz - 1; i++) { @@ -31518,6 +31741,27 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc, bool f yother = true; else if (mIns[i].mType != ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg) yother = true; + + if (mIns[i].mType == ASMIT_TAX) + xother = true; + else if (mIns[i].mType == ASMIT_INX) + xinc++; + else if (mIns[i].mType == ASMIT_DEX) + xinc--; + else if (mIns[i].mType == ASMIT_LDX) + { + if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg && xinc >= -1 && xinc <= 1) + { + xinc = 0; + xindex = true; + } + else + xother = true; + } + else if (!xindex && (mIns[i].mType == ASMIT_STX || mIns[i].mType == ASMIT_TXA || mIns[i].mMode == ASMIM_ABSOLUTE_X)) + xother = true; + else if (mIns[i].mType != ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg) + xother = true; } if (!yother) @@ -31601,6 +31845,89 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc, bool f changed = true; + assert(mIns.Size() == 0 || mIns[0].mType != ASMIT_INV); + } + else if (!xother) + { + int linc = xinc + 1; + + NativeCodeBasicBlock* lblock = proc->AllocateBlock(); + NativeCodeBasicBlock* eblock = proc->AllocateBlock(); + + yinc = 0; + for (int i = 0; i + 1 < sz; i++) + { + mIns[i].mLive |= LIVE_CPU_REG_X; + + if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg) + lblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_TXA, ASMIM_IMPLIED)); + else if (mIns[i].mType == ASMIT_LDX) + { + if (yinc > 0) + lblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_DEX)); + else if (yinc < 0) + lblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_INX)); + yinc = 0; + } + else + { + lblock->mIns.Push(mIns[i]); + if (mIns[i].mType == ASMIT_INX) + yinc++; + else if (mIns[i].mType == ASMIT_DEX) + yinc--; + } + } + + if (linc == 0) + { + lblock->mIns.Push(NativeCodeInstruction(iins, ASMIT_CPX, ASMIM_IMMEDIATE, 0)); + } + else + { + while (linc < 0) + { + lblock->mIns.Push(NativeCodeInstruction(iins, ASMIT_INX, ASMIM_IMPLIED)); + linc++; + } + while (linc > 0) + { + lblock->mIns.Push(NativeCodeInstruction(iins, ASMIT_DEX, ASMIM_IMPLIED)); + linc--; + } + } + + lblock->mBranch = mBranch; + lblock->mTrueJump = lblock; + lblock->mFalseJump = eblock; + + eblock->mIns.Push(NativeCodeInstruction(iins, ASMIT_STX, ASMIM_ZERO_PAGE, zreg)); + eblock->mBranch = ASMIT_JMP; + eblock->mTrueJump = mFalseJump; + eblock->mFalseJump = nullptr; + + lblock->mEntryRequiredRegs = mEntryRequiredRegs; + lblock->mExitRequiredRegs = mExitRequiredRegs; + eblock->mEntryRequiredRegs = mExitRequiredRegs; + eblock->mExitRequiredRegs = mExitRequiredRegs; + mExitRequiredRegs = mEntryRequiredRegs; + mExitRequiredRegs += CPU_REG_X; + lblock->mEntryRequiredRegs += CPU_REG_X; + lblock->mExitRequiredRegs += CPU_REG_X; + eblock->mEntryRequiredRegs += CPU_REG_X; + + mIns.SetSize(0); + mIns.Push(NativeCodeInstruction(iins, ASMIT_LDX, ASMIM_ZERO_PAGE, zreg)); + mBranch = ASMIT_JMP; + mTrueJump = lblock; + mFalseJump = nullptr; + + lblock->OptimizeSimpleLoopInvariant(proc, this, eblock, full); + + lblock->CheckLive(); + + changed = true; + assert(mIns.Size() == 0 || mIns[0].mType != ASMIT_INV); } } @@ -34543,6 +34870,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #endif +#if 1 + for (int i = 0; i + 3 < mIns.Size(); i++) + { + if (mIns[i + 0].mType == ASMIT_TAX && mIns[i + 1].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 2 && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) + + { + if (MoveTAXADCSTADown(i)) + changed = true; + } + } + + CheckLive(); +#endif + #if 1 for (int i = 0; i < mIns.Size(); i++) { @@ -42138,6 +42481,12 @@ void NativeCodeProcedure::Optimize(void) } #endif + if (step > 1) + { + ResetVisited(); + mEntryBlock->LocalZeroPageValueNumbering(); + } + int t = 0; #if 1 do diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 6ec4307..79d26c4 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -446,6 +446,8 @@ public: bool FoldShiftORAIntoLoadImmUp(int at); bool MoveSimpleADCToINCDECDown(int at); + bool MoveTAXADCSTADown(int at); + bool MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction & lins, const NativeCodeInstruction & sins); bool ShortcutCrossBlockMoves(NativeCodeProcedure* proc); @@ -570,6 +572,7 @@ public: bool LocalRegisterXYMap(void); bool ReduceLocalYPressure(void); bool ReduceLocalXPressure(void); + bool LocalZeroPageValueNumbering(void); bool CombineZPPair(int at, int r0, int r1, bool use0, bool use1, bool & swap); bool RemoveDoubleZPStore(void); diff --git a/oscar64/NumberSet.cpp b/oscar64/NumberSet.cpp index 9f269b0..74b2dd8 100644 --- a/oscar64/NumberSet.cpp +++ b/oscar64/NumberSet.cpp @@ -73,6 +73,34 @@ void NumberSet::Reset(int size, bool set) } } +void NumberSet::AddRange(int elem, int num) +{ + for (int i = 0; i < num; i++) + *this += elem + i; +} + +void NumberSet::SubRange(int elem, int num) +{ + for (int i = 0; i < num; i++) + *this -= elem + i; +} + +bool NumberSet::RangeClear(int elem, int num) const +{ + for (int i = 0; i < num; i++) + if ((*this)[elem + i]) + return false; + return true; +} + +bool NumberSet::RangeFilled(int elem, int num) const +{ + for (int i = 0; i < num; i++) + if (!(*this)[elem + i]) + return false; + return true; +} + void NumberSet::Fill(void) { int i; diff --git a/oscar64/NumberSet.h b/oscar64/NumberSet.h index 624e398..45cea76 100644 --- a/oscar64/NumberSet.h +++ b/oscar64/NumberSet.h @@ -34,6 +34,10 @@ public: void Clear(void); void Fill(void); + void AddRange(int elem, int num); + void SubRange(int elem, int num); + bool RangeClear(int elem, int num) const; + bool RangeFilled(int elem, int num) const; int Size(void) { return size; } }; From 4f76ffa3110d7926f19dc91a450c0721e4d72991 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 14 Oct 2023 15:19:24 +0200 Subject: [PATCH 148/169] Implement #line directive --- README.md | 11 +++++++++++ oscar64/Preprocessor.cpp | 5 +++-- oscar64/Preprocessor.h | 2 +- oscar64/Scanner.cpp | 15 +++++++++++++++ oscar64/Scanner.h | 1 + 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 35cf7cc..26b309f 100644 --- a/README.md +++ b/README.md @@ -569,6 +569,17 @@ This sample generates an array with pointers to screen rows: #for(i,SCREEN_HEIGHT) Screen + SCREEN_WIDTH * i, }; +The preprocessor keeps track of the source location while parsing a file to generate error messages and debug symbols. This is problematic for generated code, where the C source file position does not reflect the actual source position. + +The source position can be set with the #line directiv + + #line linenum + + sets the line number + + #line linenum "sourcefile" + + sets the line number and source file name ### Linker control diff --git a/oscar64/Preprocessor.cpp b/oscar64/Preprocessor.cpp index 75bfb0e..787a048 100644 --- a/oscar64/Preprocessor.cpp +++ b/oscar64/Preprocessor.cpp @@ -608,6 +608,7 @@ bool SourceFile::Open(const char* name, const char* path, SourceFileMode mode) *p = '/'; p++; } + strcpy_s(mLocationFileName, mFileName); mMode = mode; mLimit = 0x10000; mFill = 0; @@ -731,7 +732,7 @@ bool Preprocessor::EmbedData(const char* reason, const char* name, bool local, i source->mUp = mSource; mSource = source; - mLocation.mFileName = mSource->mFileName; + mLocation.mFileName = mSource->mLocationFileName; mLocation.mLine = 0; mLine[0] = 0; @@ -791,7 +792,7 @@ bool Preprocessor::OpenSource(const char * reason, const char* name, bool local) source->mUp = mSource; mSource = source; - mLocation.mFileName = mSource->mFileName; + mLocation.mFileName = mSource->mLocationFileName; mLocation.mLine = 0; mLine[0] = 0; diff --git a/oscar64/Preprocessor.h b/oscar64/Preprocessor.h index 19e1d54..a849ba6 100644 --- a/oscar64/Preprocessor.h +++ b/oscar64/Preprocessor.h @@ -39,7 +39,7 @@ enum SourceFileDecoder class SourceFile { public: - char mFileName[MAXPATHLEN]; + char mFileName[MAXPATHLEN], mLocationFileName[MAXPATHLEN]; SourceFile * mUp, * mNext; Location mLocation; diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 2a48e37..b761cd9 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -143,6 +143,7 @@ const char* TokenNames[] = "'#ifdef'", "'#ifndef'", "'#pragma'", + "'#line'", "'#assign'", "'#repeat'", @@ -597,6 +598,18 @@ void Scanner::NextPreToken(void) mPreprocessor->CloseSource(); } } + else if (mToken == TK_PREP_LINE) + { + NextPreToken(); + int l = mLocation.mLine; + int64 v = PrepParseConditional(); + if (mLocation.mLine == l && mToken == TK_STRING) + { + strcpy_s(mPreprocessor->mSource->mLocationFileName, mTokenString); + NextRawToken(); + } + mPreprocessor->mLocation.mLine = v - 1; + } else if (mToken == TK_PREP_FOR) { NextRawToken(); @@ -1384,6 +1397,8 @@ void Scanner::NextRawToken(void) mToken = TK_PREP_ENDIF; else if (!strcmp(tkprep, "pragma")) mToken = TK_PREP_PRAGMA; + else if (!strcmp(tkprep, "line")) + mToken = TK_PREP_LINE; else if (!strcmp(tkprep, "assign")) mToken = TK_PREP_ASSIGN; else if (!strcmp(tkprep, "repeat")) diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 8db05ac..1f41adc 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -141,6 +141,7 @@ enum Token TK_PREP_IFDEF, TK_PREP_IFNDEF, TK_PREP_PRAGMA, + TK_PREP_LINE, TK_PREP_ASSIGN, TK_PREP_REPEAT, From d160b2ae65ebfb762e26ee59b631c4be0d937130 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 14 Oct 2023 16:51:33 +0200 Subject: [PATCH 149/169] Optimize bitfields --- autotest/bitfields.cpp | 107 +++++++++++++++++++++++++++++++++++++++ oscar64/InterCode.cpp | 111 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 209 insertions(+), 9 deletions(-) diff --git a/autotest/bitfields.cpp b/autotest/bitfields.cpp index 3e7cd44..9a4d4e9 100644 --- a/autotest/bitfields.cpp +++ b/autotest/bitfields.cpp @@ -232,9 +232,109 @@ void test_word_signed(void) } } +void test_inc_char_fit(void) +{ + A ai; + ai.x = 7; + ai.y = 1; + ai.z = 2; + for(int i=0; i<16; i++) + { + assert(ai.x == ((7 + i) & 15)); + assert(ai.y == ((1 + i) & 1)); + assert(ai.z == ((2 + i) & 7)); + ai.x++; + ai.y++; + ai.z++; + } +} + +void test_inc_char_cross(void) +{ + B bi; + bi.x = 11; + bi.y = 22; + bi.z = 33; + bi.w = 44; + + for(int i=0; i<64; i++) + { + assert(bi.x == ((11 + i) & 0x3f)); + assert(bi.y == ((22 + i) & 0x3f)); + assert(bi.z == ((33 + i) & 0x3f)); + assert(bi.w == ((44 + i) & 0x3f)); + bi.x++; + bi.y++; + bi.z++; + bi.w++; + } +} + +void test_add_char_cross(void) +{ + B bi= {0}; + bi.x = 11; + bi.y = 22; + bi.z = 33; + bi.w = 44; + + for(int i=0; i<64; i++) + { + assert(bi.x == ((11 + 5 * i) & 0x3f)); + assert(bi.y == ((22 + 21 * i) & 0x3f)); + assert(bi.z == ((33 - 4 * i) & 0x3f)); + assert(bi.w == ((44 - 11 * i) & 0x3f)); + bi.x += 5; + bi.y += 21; + bi.z -= 4; + bi.w -= 11; + } +} + +void test_add_word_fit(void) +{ + C ci = {0}; + + ci.x = 7; + ci.y = 1; + ci.z = 2; + + for(int i=0; i<16; i++) + { + assert(ci.x == ((7 + 5 * i) & 15)); + assert(ci.y == ((1 + 21 * i) & 1)); + assert(ci.z == ((2 - 4 * i) & 7)); + ci.x += 5; + ci.y += 21; + ci.z -= 4; + } +} + +void test_add_word_cross(void) +{ + D di = {0}; + + di.x = 111; + di.y = 222; + di.z = 333; + di.w = 444; + + for(int i=0; i<1024; i++) + { + assert(di.x == ((111 + 5 * i) & 0x3ff)); + assert(di.y == ((222 + 21 * i) & 0x3ff)); + assert(di.z == ((333 - 4 * i) & 0x3ff)); + assert(di.w == ((444 - 11 * i) & 0x3ff)); + di.x += 5; + di.y += 21; + di.z -= 4; + di.w -= 11; + } +} int main(void) { +#if 0 test_char_fit(); test_char_cross(); test_word_fit(); @@ -244,5 +344,12 @@ int main(void) test_char_signed(); test_word_signed(); + test_inc_char_fit(); + test_inc_char_cross(); + test_add_char_cross(); +#endif + test_add_word_fit(); + test_add_word_cross(); + return 0; } diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 1b1b5f0..a5204d7 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -7150,16 +7150,21 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray else if (ins->mSrc[1].mTemp < 0) { vr = mLocalValueRange[ins->mSrc[0].mTemp]; + + IntegerValueRange::State s = vr.mMinState; + vr.mMinState = vr.mMaxState; + vr.mMaxState = s; + int64 maxv = vr.mMaxValue, minv = vr.mMinValue; - if (vr.mMaxState == IntegerValueRange::S_WEAK) - { - if (vr.mMinState == IntegerValueRange::S_WEAK) - vr.mMaxState = IntegerValueRange::S_UNBOUND; - vr.mMinState = IntegerValueRange::S_UNBOUND; - } if (vr.mMinState == IntegerValueRange::S_WEAK) + { + if (vr.mMaxState == IntegerValueRange::S_WEAK) + vr.mMinState = IntegerValueRange::S_UNBOUND; vr.mMaxState = IntegerValueRange::S_UNBOUND; + } + if (vr.mMaxState == IntegerValueRange::S_WEAK) + vr.mMinState = IntegerValueRange::S_UNBOUND; vr.mMaxValue = ins->mSrc[1].mIntConst - minv; vr.mMinValue = ins->mSrc[1].mIntConst - maxv; @@ -9381,7 +9386,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra { InterInstruction* ains = ltvalue[pins->mSrc[0].mTemp]; - if (ains->mCode == IC_BINARY_OPERATOR && ains->mOperator == IA_ADD && ains->mSrc[0].mTemp < 0) + if (ains->mCode == IC_BINARY_OPERATOR && (ains->mOperator == IA_ADD || ains->mOperator == IA_SUB) && ains->mSrc[0].mTemp < 0) { if (spareTemps + 2 >= ltvalue.Size()) return true; @@ -9404,7 +9409,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra nins->mDst.mRange = ins->mDst.mRange; mInstructions.Insert(i + 1, nins); - ins->mOperator = IA_ADD; + ins->mOperator = ains->mOperator; ins->mSrc[0] = ains->mSrc[0]; ins->mSrc[0].mIntConst <<= nins->mSrc[0].mIntConst; ins->mSrc[1] = nins->mDst; @@ -15892,7 +15897,94 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 2]->mSrc[0].mIntConst = 0; changed = true; } +#if 1 + if (i + 2 < mInstructions.Size() && + mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_AND && + mInstructions[i + 0]->mSrc[0].mTemp < 0 && + mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 1]->mOperator == IA_SHR && + mInstructions[i + 1]->mSrc[0].mTemp < 0 && + mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal && + mInstructions[i + 2]->mCode == IC_RELATIONAL_OPERATOR && + mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 1]->mDst.mTemp && mInstructions[i + 2]->mSrc[0].mFinal && + mInstructions[i + 2]->mSrc[0].mTemp < 0) + { + mInstructions[i + 0]->mSrc[0].mIntConst &= ~((1 << mInstructions[i + 1]->mSrc[0].mIntConst) - 1); + mInstructions[i + 2]->mSrc[0].mIntConst <<= mInstructions[i + 1]->mSrc[0].mIntConst; + mInstructions[i + 2]->mSrc[1] = mInstructions[i + 0]->mDst; + mInstructions[i + 1]->mCode = IC_NONE; + mInstructions[i + 1]->mNumOperands = 0; + changed = true; + } + if (i + 2 < mInstructions.Size() && + mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_SHR && + mInstructions[i + 0]->mSrc[0].mTemp < 0 && + mInstructions[i + 1]->mCode == IC_RELATIONAL_OPERATOR && + mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mFinal && + mInstructions[i + 1]->mSrc[0].mTemp < 0) + { + mInstructions[i + 1]->mSrc[0].mIntConst <<= mInstructions[i + 0]->mSrc[0].mIntConst; + + mInstructions[i + 0]->mOperator = IA_AND; + mInstructions[i + 0]->mSrc[0].mIntConst = ~((1 << mInstructions[i + 0]->mSrc[0].mIntConst) - 1); + mInstructions[i + 0]->mDst.mRange.Reset(); + mInstructions[i + 1]->mSrc[1].mRange.Reset(); + changed = true; + } + + if (i + 3 < mInstructions.Size() && + mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_SHR && + mInstructions[i + 0]->mSrc[0].mTemp < 0 && + + mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && (mInstructions[i + 1]->mOperator == IA_ADD || mInstructions[i + 1]->mOperator == IA_SUB) && + mInstructions[i + 1]->mSrc[0].mTemp < 0 && + mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal && + + mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 2]->mOperator == IA_SHL && + mInstructions[i + 2]->mSrc[0].mTemp < 0 && + mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 1]->mDst.mTemp && mInstructions[i + 2]->mSrc[1].mFinal && + + mInstructions[i + 3]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 3]->mOperator == IA_AND && + mInstructions[i + 3]->mSrc[0].mTemp < 0 && + mInstructions[i + 3]->mSrc[1].mTemp == mInstructions[i + 2]->mDst.mTemp && mInstructions[i + 3]->mSrc[1].mFinal && + + mInstructions[i + 0]->mSrc[0].mIntConst == mInstructions[i + 2]->mSrc[0].mIntConst) + { + mInstructions[i + 3]->mSrc[0].mIntConst &= ~((1 << mInstructions[i + 0]->mSrc[0].mIntConst) - 1); + mInstructions[i + 1]->mSrc[0].mIntConst <<= mInstructions[i + 0]->mSrc[0].mIntConst; + + mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1]; + mInstructions[i + 1]->mDst = mInstructions[i + 2]->mDst; + + mInstructions[i + 0]->mCode = IC_NONE; + mInstructions[i + 0]->mNumOperands = 0; + mInstructions[i + 2]->mCode = IC_NONE; + mInstructions[i + 2]->mNumOperands = 0; + changed = true; + } + if (i + 2 < mInstructions.Size() && + mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_AND && + mInstructions[i + 0]->mSrc[0].mTemp < 0 && + + mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && (mInstructions[i + 1]->mOperator == IA_ADD || mInstructions[i + 1]->mOperator == IA_SUB) && + mInstructions[i + 1]->mSrc[0].mTemp < 0 && + mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal && + + mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 2]->mOperator == IA_AND && + mInstructions[i + 2]->mSrc[0].mTemp < 0 && + mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 1]->mDst.mTemp && mInstructions[i + 2]->mSrc[1].mFinal && + + (mInstructions[i + 0]->mSrc[0].mIntConst & (mInstructions[i + 0]->mSrc[0].mIntConst + 1)) == 0 && // Is power of two - 1 + (~mInstructions[i + 0]->mSrc[0].mIntConst & mInstructions[i + 1]->mSrc[0].mIntConst) == 0 && // add is part of initial mask + (~mInstructions[i + 0]->mSrc[0].mIntConst & mInstructions[i + 2]->mSrc[0].mIntConst) == 0) // final mask is part of initial mask + { + mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1]; + + mInstructions[i + 0]->mCode = IC_NONE; + mInstructions[i + 0]->mNumOperands = 0; + changed = true; + } +#endif #if 1 if (i + 2 < mInstructions.Size() && mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && @@ -17925,7 +18017,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "ftoa"); + CheckFunc = !strcmp(mIdent->mString, "test_add_char_cross"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -18281,6 +18373,7 @@ void InterCodeProcedure::Close(void) BuildDataFlowSets(); DisassembleDebug("Followed Jumps 2"); + CheckCase = true; RebuildIntegerRangeSet(); From 4e76b34f5379ca9c07e56944f6fb8d8eeff1b077 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 14 Oct 2023 18:50:27 +0200 Subject: [PATCH 150/169] constexpr constructor --- oscar64/Constexpr.cpp | 125 ++++++++++++++++++++++++++-------------- oscar64/Constexpr.h | 6 +- oscar64/Declaration.cpp | 10 +++- oscar64/Parser.cpp | 1 + 4 files changed, 96 insertions(+), 46 deletions(-) diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index a0de135..a5692e6 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -621,6 +621,83 @@ Expression* ConstexprInterpreter::EvalConstructor(Expression* exp) return mResult.ToExpression(mDataSection); } +Expression* ConstexprInterpreter::EvalTempConstructor(Expression* exp) +{ + Expression* cexp = exp->mLeft->mLeft; + + mProcType = cexp->mLeft->mDecType; + + Expression* pex = cexp->mRight; + Declaration* dec = cexp->mLeft->mDecType->mParams; + + Value othis = Value(exp->mLocation, exp->mRight->mDecType); + + mParams[0] = Value(exp->mLocation, dec->mBase); + mParams[0].PutPtr(Value(&othis)); + + int pos = 2; + if (pex->mType == EX_LIST) + pex = pex->mRight; + else + pex = nullptr; + dec = dec->mNext; + + while (pex && pex->mType == EX_LIST) + { + if (!AddParam(pos, pex->mLeft, dec)) + return exp; + + pex = pex->mRight; + if (dec) + dec = dec->mNext; + } + + if (pex) + { + if (!AddParam(pos, pex, dec)) + return exp; + } + + mHeap = new ExpandingArray(); + + Execute(cexp->mLeft->mDecValue->mValue); + + if (mHeap->Size() > 0) + mErrors->Error(exp->mLocation, EERR_UNBALANCED_HEAP_USE, "Unbalanced heap use in constexpr"); + delete mHeap; + + return othis.ToExpression(mDataSection); +} + +bool ConstexprInterpreter::AddParam(int& pos, Expression* pex, Declaration* dec) +{ + if (dec) + pos = dec->mVarIndex; + + if (pex->mType == EX_CONSTANT) + { + 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)) + { + mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase); + if (pex->mDecValue->mSize > 0) + mParams[pos].PutConst(0, pex->mDecValue->mValue->mDecValue); + } + else + return false; + + return true; +} + Expression* ConstexprInterpreter::EvalCall(Expression* exp) { mProcType = exp->mLeft->mDecType; @@ -638,57 +715,17 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp) while (pex && pex->mType == EX_LIST) { - if (dec) - pos = dec->mVarIndex; - - if (pex->mLeft->mType == EX_CONSTANT) - { - 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)) - { - mParams[pos] = Value(pex->mLeft->mLocation, pex->mLeft->mDecValue->mBase); - mParams[pos].PutConst(0, pex->mLeft->mDecValue->mValue->mDecValue); - } - else + if (!AddParam(pos, pex->mLeft, dec)) return exp; pex = pex->mRight; if (dec) dec = dec->mNext; } - if (pex) - { - if (dec) - pos = dec->mVarIndex; - if (pex->mType == EX_CONSTANT) - { - 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)) - { - mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase); - if (pex->mDecValue->mSize > 0) - mParams[pos].PutConst(0, pex->mDecValue->mValue->mDecValue); - } - else + if (pex) + { + if (!AddParam(pos, pex, dec)) return exp; } diff --git a/oscar64/Constexpr.h b/oscar64/Constexpr.h index 7986427..7cfc825 100644 --- a/oscar64/Constexpr.h +++ b/oscar64/Constexpr.h @@ -8,9 +8,13 @@ public: ConstexprInterpreter(const Location & loc, Errors * err, LinkerSection * dataSection); ~ConstexprInterpreter(void); - Expression* EvalCall(Expression* exp); Expression* EvalConstructor(Expression* exp); + Expression* EvalCall(Expression* exp); + Expression* EvalTempConstructor(Expression* exp); protected: + + bool AddParam(int& pos, Expression* pex, Declaration* dec); + struct Value; struct ValueItem diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 24a399a..424e2ba 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -899,7 +899,15 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio { ConstexprInterpreter cinter(mLocation, errors, dataSection); return cinter.EvalCall(this); - } + } + else if (mType == EX_CONSTRUCT && mLeft->mType == EX_LIST && !mLeft->mRight && mLeft->mLeft->mType == EX_CALL && + mLeft->mLeft->mLeft->mType == EX_CONSTANT && (mLeft->mLeft->mLeft->mDecValue->mFlags & DTF_CONSTEXPR) && + (mRight->mDecValue->mFlags & DTF_TEMPORARY) && + dataSection) + { + ConstexprInterpreter cinter(mLocation, errors, dataSection); + return cinter.EvalTempConstructor(this); + } return this; } diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 84e7f75..7b7e2d8 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1552,6 +1552,7 @@ Expression* Parser::ParseInitExpression(Declaration* dtype) } Expression* texp = ParseInitExpression(dtype->mBase); + texp = texp->ConstantFold(mErrors, mDataSection); for (int i = 0; i < nrep; i++) { Declaration* cdec = CopyConstantInitializer(index, dtype->mBase, texp); From 3da58bf1ca7a887e22abb4032f4b06f13be66968 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 15 Oct 2023 12:01:24 +0200 Subject: [PATCH 151/169] Fix line directive off by one error --- autotest/autotest.bat | 3 +++ autotest/bitfields.cpp | 4 +-- autotest/mmultest.c | 43 +++++++++++++++++++++++++++++++++ oscar64/InterCode.cpp | 36 ++++++++++++++++++++++----- oscar64/InterCode.h | 1 + oscar64/NativeCodeGenerator.cpp | 12 ++++----- oscar64/Scanner.cpp | 2 +- 7 files changed, 86 insertions(+), 15 deletions(-) create mode 100644 autotest/mmultest.c diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 567bea6..37f4864 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -216,6 +216,9 @@ rem @echo off @call :testn stripedarraytest.c @if %errorlevel% neq 0 goto :error +@call :testn mmultest.c +@if %errorlevel% neq 0 goto :error + @exit /b 0 :error diff --git a/autotest/bitfields.cpp b/autotest/bitfields.cpp index 9a4d4e9..02031e7 100644 --- a/autotest/bitfields.cpp +++ b/autotest/bitfields.cpp @@ -334,7 +334,7 @@ void test_add_word_cross(void) } int main(void) { -#if 0 + test_char_fit(); test_char_cross(); test_word_fit(); @@ -347,7 +347,7 @@ int main(void) test_inc_char_fit(); test_inc_char_cross(); test_add_char_cross(); -#endif + test_add_word_fit(); test_add_word_cross(); diff --git a/autotest/mmultest.c b/autotest/mmultest.c new file mode 100644 index 0000000..edcb10c --- /dev/null +++ b/autotest/mmultest.c @@ -0,0 +1,43 @@ +#include +#include +#include + +Matrix4 ml, mr; + +int main(void) +{ + for(char i=0; i<16; i++) + { + for(char j=0; j<16; j++) + { + for(char k=0; k<16; k++) + { + ml.m[k] = (i == k) ? 1.0 : 0.0; + mr.m[k] = (j == k) ? 1.0 : 0.0; + } + + mat4_mmul(&ml, &mr); + +#if 0 + printf("%d, %d\n", i, j); + for(char k=0; k<16; k++) + printf("%f ", ml.m[k]); + printf("\n"); +#endif + + for(char k=0; k<16; k++) + { + char ix = i & 3, iy = i >> 2; + char jx = j & 3, jy = j >> 2; + char kx = k & 3, ky = k >> 2; + + if (ky == jy && kx == ix && jx == iy) + assert(ml.m[k] == 1.0); + else + assert(ml.m[k] == 0.0); + } + } + } + + return 0; +} diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index a5204d7..6c5ac7a 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -8007,6 +8007,26 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray +void InterCodeBasicBlock::PruneUnusedIntegerRangeSets(void) +{ + if (!mVisited) + { + mVisited = true; + + if (mEntryValueRange.Size() > 0 && mEntryRequiredTemps.Size()) + { + for (int i = 0; i < mEntryValueRange.Size(); i++) + { + if (!mEntryRequiredTemps[i]) + mEntryValueRange[i].Reset(); + } + } + + if (mTrueJump) mTrueJump->PruneUnusedIntegerRangeSets(); + if (mFalseJump) mFalseJump->PruneUnusedIntegerRangeSets(); + } +} + void InterCodeBasicBlock::RestartLocalIntegerRangeSets(int num, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars) { if (!mVisited) @@ -10731,6 +10751,9 @@ void InterCodeBasicBlock::RenameValueRanges(const GrowingIntArray& renameTable, { if (renameTable[i] >= 0) { + assert(mLocalValueRange[i].mMinState == IntegerValueRange::S_UNKNOWN || mEntryValueRange[renameTable[i]].mMinState == IntegerValueRange::S_UNKNOWN); + assert(mLocalValueRange[i].mMaxState == IntegerValueRange::S_UNKNOWN || mEntryValueRange[renameTable[i]].mMaxState == IntegerValueRange::S_UNKNOWN); + mEntryValueRange[renameTable[i]].Limit(mLocalValueRange[i]); } } @@ -18017,7 +18040,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "test_add_char_cross"); + CheckFunc = !strcmp(mIdent->mString, "qsort"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -18373,7 +18396,6 @@ void InterCodeProcedure::Close(void) BuildDataFlowSets(); DisassembleDebug("Followed Jumps 2"); - CheckCase = true; RebuildIntegerRangeSet(); @@ -18502,8 +18524,6 @@ void InterCodeProcedure::Close(void) Disassemble("gcp-"); #endif - CheckCase = true; - #if 1 RebuildIntegerRangeSet(); #endif @@ -18565,8 +18585,6 @@ void InterCodeProcedure::Close(void) LoadStoreForwarding(paramMemory); - CheckCase = true; - RebuildIntegerRangeSet(); #if 1 @@ -18777,6 +18795,9 @@ void InterCodeProcedure::Close(void) PeepholeOptimization(); DisassembleDebug("Peephole Temp Check"); + + if (i == 1) + CheckCase = true; RemoveUnusedInstructions(); @@ -19458,6 +19479,9 @@ void InterCodeProcedure::ReduceTemporaries(void) ResetVisited(); } while (mEntryBlock->BuildGlobalRequiredTempSet(totalRequired2)); + ResetVisited(); + mEntryBlock->PruneUnusedIntegerRangeSets(); + collisionSet = new NumberSet[numTemps]; for (i = 0; i < numTemps; i++) diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 3169011..737417f 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -454,6 +454,7 @@ public: void SimplifyIntegerRangeRelops(void); void MarkIntegerRangeBoundUp(int temp, int64 value, GrowingIntegerValueRangeArray& range); void UnionIntegerRanges(const InterCodeBasicBlock* block); + void PruneUnusedIntegerRangeSets(void); bool CombineIndirectAddressing(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index bfdd59e..bebe30f 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -26593,7 +26593,7 @@ bool NativeCodeBasicBlock::ForwardReplaceZeroPage(int at, int from, int to) if (mFalseJump && mFalseJump->ForwardReplaceZeroPage(0, from, to)) changed = true; - if (changed) + if (mEntryRequiredRegs[from]) mEntryRequiredRegs += to; } @@ -29635,7 +29635,8 @@ bool NativeCodeBasicBlock::OptimizeLoopCarryOver(void) mExitRequiredRegs += CPU_REG_Y; changed = true; } - else if (sz > 1 && hblock->mIns[0].mType == ASMIT_LDA && mIns[sz - 1].mType == ASMIT_CMP && mIns[sz - 2].mType == ASMIT_LDA && hblock->mIns[0].SameEffectiveAddress(mIns[sz - 2]) && !(hblock->mIns[0].mLive & LIVE_CPU_REG_Z)) + else if (sz > 1 && hblock->mIns[0].mType == ASMIT_LDA && mIns[sz - 1].mType == ASMIT_CMP && mIns[sz - 2].mType == ASMIT_LDA + && hblock->mIns[0].SameEffectiveAddress(mIns[sz - 2]) && !(hblock->mIns[0].mLive & LIVE_CPU_REG_Z) && !(hblock->mIns[0].mFlags & NCIF_VOLATILE)) { pblock->mIns.Push(hblock->mIns[0]); hblock->mIns.Remove(0); @@ -41791,7 +41792,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "atoi"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "mat4_mmul"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -43090,7 +43091,7 @@ void NativeCodeProcedure::Optimize(void) #endif #if 1 - if (step == 10) + if (step == 10 && (mInterProc->mCompilerOptions & COPT_OPTIMIZE_BASIC)) { ResetVisited(); mEntryBlock->MarkLocalUsedLinkerObjects(); @@ -43126,7 +43127,6 @@ void NativeCodeProcedure::Optimize(void) } } #endif - #if _DEBUG ResetVisited(); mEntryBlock->CheckAsmCode(); @@ -43157,7 +43157,6 @@ void NativeCodeProcedure::Optimize(void) else cnt++; - } while (changed); #if 1 @@ -43226,6 +43225,7 @@ void NativeCodeProcedure::Optimize(void) changed = mEntryBlock->JoinTailCodeSequences(this, true); } + } while (changed); #endif diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index b761cd9..967d160 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -608,7 +608,7 @@ void Scanner::NextPreToken(void) strcpy_s(mPreprocessor->mSource->mLocationFileName, mTokenString); NextRawToken(); } - mPreprocessor->mLocation.mLine = v - 1; + mPreprocessor->mLocation.mLine = v + mLocation.mLine - l - 1; } else if (mToken == TK_PREP_FOR) { From 6e6e3b2adb0a4946a5a9f5f1111289166ccec08e Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 15 Oct 2023 12:26:32 +0200 Subject: [PATCH 152/169] Fix line directive over consumption --- oscar64/Scanner.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 967d160..ca60f20 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -600,6 +600,7 @@ void Scanner::NextPreToken(void) } else if (mToken == TK_PREP_LINE) { + mPreprocessorMode = true; NextPreToken(); int l = mLocation.mLine; int64 v = PrepParseConditional(); @@ -608,7 +609,8 @@ void Scanner::NextPreToken(void) strcpy_s(mPreprocessor->mSource->mLocationFileName, mTokenString); NextRawToken(); } - mPreprocessor->mLocation.mLine = v + mLocation.mLine - l - 1; + mPreprocessor->mLocation.mLine = int(v) + mLocation.mLine - l; + mPreprocessorMode = false; } else if (mToken == TK_PREP_FOR) { From eb16767bdb27a9a84c445d5b2d679acb7ae9e88b Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 15 Oct 2023 13:59:30 +0200 Subject: [PATCH 153/169] Optimize wide right shift --- oscar64/InterCode.cpp | 12 +++++++++++- oscar64/NativeCodeGenerator.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 6c5ac7a..ef3c474 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -18040,7 +18040,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "qsort"); + CheckFunc = !strcmp(mIdent->mString, "setspr"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -19350,6 +19350,16 @@ void InterCodeProcedure::MergeBasicBlocks(void) mblocks[j]->mInstructions.Remove(mblocks[j]->mInstructions.Size() - 2); } + + if (nblock->mEntryValueRange.Size()) + { + for (int j = 0; j < ins->mNumOperands; j++) + { + if (ins->mSrc[j].mTemp >= 0) + nblock->mEntryValueRange[ins->mSrc[j].mTemp] = ins->mSrc[j].mRange; + } + } + changed = true; } } diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index bebe30f..d1daa23 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -36116,6 +36116,16 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_ROR && mIns[i + 0].mMode == ASMIM_IMPLIED && + mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_IMPLIED) + { + mIns[i + 0].mType = ASMIT_AND; + mIns[i + 0].mMode = ASMIM_IMMEDIATE; + mIns[i + 0].mAddress = 0xfe; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + progress = true; + } else if ( (mIns[i + 0].mType == ASMIT_INX || mIns[i + 0].mType == ASMIT_DEX) && @@ -40451,6 +40461,23 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #endif } + if (i + 5 < mIns.Size() && + mIns[i + 0].mType == ASMIT_LSR && mIns[i + 0].mMode == ASMIM_IMPLIED && + mIns[i + 1].mType == ASMIT_LSR && mIns[i + 1].mMode == ASMIM_IMPLIED && + mIns[i + 2].mType == ASMIT_LSR && mIns[i + 2].mMode == ASMIM_IMPLIED && + mIns[i + 3].mType == ASMIT_LSR && mIns[i + 3].mMode == ASMIM_IMPLIED && + mIns[i + 4].mType == ASMIT_LSR && mIns[i + 4].mMode == ASMIM_IMPLIED && + mIns[i + 5].mType == ASMIT_LSR && mIns[i + 5].mMode == ASMIM_IMPLIED && !(mIns[i + 5].mLive & LIVE_CPU_REG_C)) + { + mIns[i + 0].mType = ASMIT_ASL; mIns[i + 0].mLive |= LIVE_CPU_REG_C; + mIns[i + 1].mType = ASMIT_ROL; mIns[i + 1].mLive |= LIVE_CPU_REG_C; + mIns[i + 2].mType = ASMIT_ROL; + mIns[i + 3].mType = ASMIT_NOP; + mIns[i + 4].mType = ASMIT_NOP; + mIns[i + 5].mType = ASMIT_AND; mIns[i + 5].mMode = ASMIM_IMMEDIATE; mIns[i + 5].mAddress = 3; + progress = true; + } + #if 1 if (i + 1 < mIns.Size() && mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mMode == ASMIM_INDIRECT_Y) { From 454c4f5dbe88fb87703d9c07625c34f3b27d57c7 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 15 Oct 2023 14:22:59 +0200 Subject: [PATCH 154/169] Bump version number --- oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++++---- oscar64setup/oscar64setup.vdproj | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 351368c..7c48217 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.26.223"); + strcpy(strProductVersion, "1.26.224"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 32c8681..e52501f 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,26,223,0 - PRODUCTVERSION 1,26,223,0 + FILEVERSION 1,26,224,0 + PRODUCTVERSION 1,26,224,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.26.223.0" + VALUE "FileVersion", "1.26.224.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.26.223.0" + VALUE "ProductVersion", "1.26.224.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 0392c28..2791258 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5712,15 +5712,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{8947A625-BB69-4660-BD2A-A58BD90E541C}" - "PackageCode" = "8:{A4C4A88C-A11E-4AD7-8EE8-99887AD5731F}" + "ProductCode" = "8:{F884314C-DBC1-466B-9A34-1761B921E1BD}" + "PackageCode" = "8:{5563B34B-0822-45A3-85A4-8007E3D57051}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.26.223" + "ProductVersion" = "8:1.26.224" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 7858e32d126b986bdf46648f23e35d9e5efaf462 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 15 Oct 2023 20:17:04 +0200 Subject: [PATCH 155/169] Improve handling of single member structs --- include/opp/slab.h | 80 ++++++++++ include/opp/static_vector.h | 258 +++++++++++++++++++++++++++++++++ oscar64/InterCode.cpp | 29 ++++ oscar64/InterCodeGenerator.cpp | 124 +++++++++------- oscar64/InterCodeGenerator.h | 1 + oscar64/Parser.cpp | 2 +- 6 files changed, 439 insertions(+), 55 deletions(-) create mode 100644 include/opp/slab.h create mode 100644 include/opp/static_vector.h diff --git a/include/opp/slab.h b/include/opp/slab.h new file mode 100644 index 0000000..1a61d4d --- /dev/null +++ b/include/opp/slab.h @@ -0,0 +1,80 @@ +#ifndef OPP_SLAB_H +#define OPP_SLAB_H + +template +class slabptr +{ +public: + char index; + + slabptr(void) + : index(N) + {} + + slabptr(char i) + : index(i) + {} + + slabptr(const slabptr & i) + : index(i.index) + {} + + auto operator-> (); + auto & operator* (); +}; + +template +class slab +{ +protected: + static __striped T buffer[N]; + static char head; + static char next[N]; + +public: + typedef slabptr ptr; + + static void init(void); + static auto alloc(void); + static void free(ptr p); +}; + + +template +inline auto slabptr::operator-> () +{ + return slab::buffer + index; +} + +template +inline auto & slabptr::operator* () +{ + return slab::buffer[index]; +} + + +template +void slab::init(void) +{ + head = 0; + for(char i=0; i +auto slab::alloc(void) +{ + char i = head; + head = next[head]; + return slabptr(i); +} + +template +void slab::free(slabptr p) +{ + next[p.index] = head; + head = p.index; +} + +#endif + diff --git a/include/opp/static_vector.h b/include/opp/static_vector.h new file mode 100644 index 0000000..c5358c6 --- /dev/null +++ b/include/opp/static_vector.h @@ -0,0 +1,258 @@ +#ifndef OPP_STATIC_VECTOR_H +#define OPP_STATIC_VECTOR_H + +#include +#include +#include + +namespace opp { + +template +class static_vector +{ +protected: + char _space[N * sizeof(T)]; + enum { m = N } _size; +public: + typedef T element_type; + + static_vector(void) : _size(0) {} + + static_vector(size_t n) : _size(n) + { + T * data = (T*)_space; + for(size_t i=0; i + void emplace_back(const P&... p); +}; + + + +template +void static_vector::resize(size_t n) +{ + T * data = (T*)_space; + if (n < _size) + { + for(size_t i=n; i<_size; i++) + data[i].~T(); + _size = n; + } + else + { + for(size_t i=_size; i +void static_vector::push_back(const T & t) +{ + new ((T*)_space + _size++)T(t); +} + +template +void static_vector::push_back(T && t) +{ + new ((T*)_space + _size++)T(t); +} + +template +template +void static_vector::emplace_back(const P&... p) +{ + new ((T*)_space + _size++)T(p...); +} + +template +void static_vector::insert(size_t at, const T & t) +{ + T * data = (T*)_space; + new (data + _size)T; + for(size_t i=_size; i>at; i--) + data[i] = move(data[i - 1]); + data[at] = t; + _size++; +} + +template +void static_vector::erase(size_t at, size_t n) +{ + T * data = (T*)_space; + _size -= n; + for(size_t i=at; i<_size; i++) + data[i] = move(data[i + n]); + for(size_t i=0; i +T * static_vector::insert(T * at, const T & t) +{ + T * data = (T*)_space; + T * dp = data + _size; + new (dp)T; + while (dp != at) + { + dp--; + dp[1] = move(dp[0]); + } + dp[0] = t; + _size++; + return dp + 1; +} + +} +#endif + diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index ef3c474..086b690 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16173,6 +16173,35 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray changed = true; } } +#endif +#if 1 + if (i + 1 < mInstructions.Size()) + { + if (mInstructions[i + 0]->mCode == IC_LEA && mInstructions[i + 0]->mSrc[1].mTemp < 0 && + mInstructions[i + 1]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mTemp < 0 && + mInstructions[i + 1]->mSrc[0].mMemory == IM_ABSOLUTE && mInstructions[i + 1]->mSrc[0].mIntConst == 0) + { + if (mInstructions[i + 0]->mSrc[1].mMemory != IM_ABSOLUTE) + { + if (mInstructions[i + 1]->mOperator == IA_CMPEQ) + { + mInstructions[i + 1]->mNumOperands = 0; + mInstructions[i + 1]->mCode = IC_CONSTANT; + mInstructions[i + 1]->mConst.mType = IT_BOOL; + mInstructions[i + 1]->mConst.mIntConst = 0; + changed = true; + } + else if (mInstructions[i + 1]->mOperator == IA_CMPNE) + { + mInstructions[i + 1]->mNumOperands = 0; + mInstructions[i + 1]->mCode = IC_CONSTANT; + mInstructions[i + 1]->mConst.mType = IT_BOOL; + mInstructions[i + 1]->mConst.mIntConst = 1; + changed = true; + } + } + } + } #endif } diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 28cd27c..e520776 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1252,24 +1252,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); if (vp.mTemp != vr.mTemp) - { - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); - cins->mNumOperands = 2; - - cins->mSrc[0].mType = IT_POINTER; - cins->mSrc[0].mTemp = vr.mTemp; - cins->mSrc[0].mMemory = IM_INDIRECT; - cins->mSrc[0].mOperandSize = vp.mType->mSize; - cins->mSrc[0].mStride = vr.mType->mStripe; - - cins->mSrc[1].mType = IT_POINTER; - cins->mSrc[1].mTemp = ains->mDst.mTemp; - cins->mSrc[1].mMemory = IM_INDIRECT; - cins->mSrc[1].mOperandSize = vp.mType->mSize; - - cins->mConst.mOperandSize = vp.mType->mSize; - block->Append(cins); - } + CopyStructSimple(proc, exp, block, vp, vr); } else { @@ -1390,6 +1373,73 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro return ExValue(TheVoidTypeDeclaration); } +void InterCodeGenerator::CopyStructSimple(InterCodeProcedure* proc, Expression * exp, InterCodeBasicBlock* block, ExValue vl, ExValue vr) +{ + int ne = 0; + Declaration* mdec = nullptr; + if (vl.mType->mType == DT_TYPE_STRUCT) + { + Declaration* dec = vl.mType->mParams; + while (dec) + { + if (dec->mType == DT_ELEMENT && !(dec->mFlags & DTF_STATIC)) + { + mdec = dec->mBase; + ne++; + } + dec = dec->mNext; + } + } + + // Single element structs are copied as individual value + if (ne == 1 && mdec->mSize == vl.mType->mSize) + { + InterInstruction* lins = new InterInstruction(exp->mLocation, IC_LOAD); + lins->mNumOperands = 1; + + lins->mSrc[0].mType = IT_POINTER; + lins->mSrc[0].mTemp = vr.mTemp; + lins->mSrc[0].mMemory = IM_INDIRECT; + lins->mSrc[0].mOperandSize = mdec->mSize; + lins->mSrc[0].mStride = mdec->mStripe; + + lins->mDst.mType = InterTypeOf(mdec); + lins->mDst.mTemp = proc->AddTemporary(lins->mDst.mType); + block->Append(lins); + + InterInstruction* sins = new InterInstruction(exp->mLocation, IC_STORE); + sins->mNumOperands = 2; + + sins->mSrc[1].mType = IT_POINTER; + sins->mSrc[1].mTemp = vl.mTemp; + sins->mSrc[1].mMemory = IM_INDIRECT; + sins->mSrc[1].mOperandSize = mdec->mSize; + sins->mSrc[1].mStride = mdec->mStripe; + + sins->mSrc[0] = lins->mDst; + block->Append(sins); + } + else + { + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + cins->mNumOperands = 2; + + cins->mSrc[0].mType = IT_POINTER; + cins->mSrc[0].mTemp = vr.mTemp; + cins->mSrc[0].mMemory = IM_INDIRECT; + cins->mSrc[0].mOperandSize = vr.mType->mSize; + cins->mSrc[0].mStride = vr.mType->mStripe; + + cins->mSrc[1].mOperandSize = vl.mType->mSize; + cins->mSrc[1].mType = IT_POINTER; + cins->mSrc[1].mTemp = vl.mTemp; + cins->mSrc[1].mMemory = IM_INDIRECT; + + cins->mConst.mOperandSize = vl.mType->mSize; + block->Append(cins); + } +} + void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving) { if (vr.mTemp == vl.mTemp) @@ -1587,24 +1637,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I } } else - { - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); - cins->mNumOperands = 2; - - cins->mSrc[0].mType = IT_POINTER; - cins->mSrc[0].mTemp = vr.mTemp; - cins->mSrc[0].mMemory = IM_INDIRECT; - cins->mSrc[0].mOperandSize = vr.mType->mSize; - cins->mSrc[0].mStride = vr.mType->mStripe; - - cins->mSrc[1].mOperandSize = vl.mType->mSize; - cins->mSrc[1].mType = IT_POINTER; - cins->mSrc[1].mTemp = vl.mTemp; - cins->mSrc[1].mMemory = IM_INDIRECT; - - cins->mConst.mOperandSize = vl.mType->mSize; - block->Append(cins); - } + CopyStructSimple(proc, exp, block, vl, vr); } InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, ExValue* lrexp) @@ -2104,24 +2137,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); if (vr.mTemp != vl.mTemp) - { - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_COPY); - ins->mNumOperands = 2; - - ins->mSrc[0].mType = IT_POINTER; - ins->mSrc[0].mTemp = vr.mTemp; - ins->mSrc[0].mMemory = IM_INDIRECT; - ins->mSrc[0].mOperandSize = vl.mType->mSize; - ins->mSrc[0].mStride = vr.mType->mStripe; - - ins->mSrc[1].mType = IT_POINTER; - ins->mSrc[1].mTemp = vl.mTemp; - ins->mSrc[1].mMemory = IM_INDIRECT; - ins->mSrc[1].mOperandSize = vl.mType->mSize; - ins->mSrc[1].mStride = vl.mType->mStripe; - ins->mConst.mOperandSize = vl.mType->mSize; - block->Append(ins); - } + CopyStructSimple(proc, exp, block, vl, vr); } else { diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 79f9bb0..67d3e2a 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -87,6 +87,7 @@ protected: void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper); ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp); void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving); + void CopyStructSimple(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock * block, ExValue vl, ExValue vr); void StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr); void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom, InlineMapper* inlineMapper); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 7b7e2d8..b191c87 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -5334,7 +5334,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) if (dec) { - if (dec->mType == DT_ELEMENT || dec->mType == DT_CONST_FUNCTION) + if ((dec->mType == DT_ELEMENT || dec->mType == DT_CONST_FUNCTION) && !(dec->mFlags & DTF_STATIC)) { Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE); texp->mDecType = mThisPointer->mBase; From 19e2498cc8d18a3db8aa5890901e37690c0cee8a Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 16 Oct 2023 14:13:20 +0200 Subject: [PATCH 156/169] Fix member constructor for multi dim array members --- oscar64/Parser.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index b191c87..0653df8 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -1974,6 +1974,17 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc) } else { + qexp->mDecType = dec->mBase->mBase; + + while (qexp->mDecType->mType == DT_TYPE_ARRAY) + { + Expression* iexp = new Expression(pthis->mLocation, EX_PREFIX); + iexp->mToken = TK_MUL; + iexp->mLeft = qexp; + iexp->mDecType = qexp->mDecType->mBase; + qexp = iexp; + } + qexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); qexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; qexp->mDecType->mBase = bdec; From da5326cc5f23e551afabdecc9b2d91fa2500181c Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 16 Oct 2023 15:01:30 +0200 Subject: [PATCH 157/169] Fix local multi dim array init --- oscar64/InterCodeGenerator.cpp | 2 +- oscar64/Parser.cpp | 30 +++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index e520776..2dd0e6d 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -2890,7 +2890,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a pointer type"); else if (vl.mType->mStride != 1) vl = Dereference(proc, exp, block, vl, 0); - return ExValue(vl.mType->mBase, vl.mTemp, vl.mReference + 1); + return ExValue(vl.mType->mBase, vl.mTemp, 1); case TK_BINARY_AND: { if (vl.mReference < 1 || vl.mBits) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 0653df8..64fc32e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3092,6 +3092,17 @@ void Parser::AppendMemberDestructor(Declaration* pthis) } else { + qexp->mDecType = dec->mBase->mBase; + + while (qexp->mDecType->mType == DT_TYPE_ARRAY) + { + Expression* iexp = new Expression(pthis->mLocation, EX_PREFIX); + iexp->mToken = TK_MUL; + iexp->mLeft = qexp; + iexp->mDecType = qexp->mDecType->mBase; + qexp = iexp; + } + qexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); qexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; qexp->mDecType->mBase = bdec; @@ -4504,6 +4515,19 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else { + Expression* texp = vexp; + + while (texp->mDecType->mBase->mType == DT_TYPE_ARRAY) + { + Expression* iexp = new Expression(vexp->mLocation, EX_PREFIX); + iexp->mToken = TK_MUL; + iexp->mLeft = texp; + iexp->mDecType = texp->mDecType->mBase; + texp = iexp; + } + + //texp->mDecType = bdec->BuildPointer(vexp->mLocation); + Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER); ncdec->mBase = TheUnsignedIntTypeDeclaration; ncdec->mInteger = ndec->mSize / bdec->mSize; @@ -4520,11 +4544,11 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex fexp->mLeft = cexp; fexp->mRight = new Expression(mScanner->mLocation, EX_LIST); - fexp->mRight->mLeft = vexp; + fexp->mRight->mLeft = texp; fexp->mRight->mRight = new Expression(mScanner->mLocation, EX_BINARY); fexp->mRight->mRight->mToken = TK_ADD; - fexp->mRight->mRight->mLeft = vexp; - fexp->mRight->mRight->mDecType = vexp->mDecType; + fexp->mRight->mRight->mLeft = texp; + fexp->mRight->mRight->mDecType = texp->mDecType; fexp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT); fexp->mRight->mRight->mRight->mDecType = ncdec->mBase; fexp->mRight->mRight->mRight->mDecValue = ncdec; From 63725f35117fc23986b8292931896193062050dd Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:24:35 +0200 Subject: [PATCH 158/169] Fix const eval of sin/cos --- oscar64/Declaration.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 424e2ba..1e19268 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -867,9 +867,9 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio Declaration* decf = mLeft->mDecValue, * decp = mRight->mDecValue; const Ident* iname = decf->mQualIdent; - if (decp->mType == DT_TYPE_FLOAT || decp->mType == DT_TYPE_INTEGER) + if (decp->mType == DT_CONST_FLOAT || decp->mType == DT_CONST_INTEGER) { - double d = decp->mType == DT_TYPE_FLOAT ? decp->mNumber : decp->mInteger; + double d = decp->mType == DT_CONST_FLOAT ? decp->mNumber : decp->mInteger; bool check = false; From f5c13c02af86fb510d80e11868fec6860e6e2ffb Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 16 Oct 2023 21:29:42 +0200 Subject: [PATCH 159/169] Some native code opts --- oscar64/NativeCodeGenerator.cpp | 92 +++++++++++++++++++++++++++++++++ oscar64/NativeCodeGenerator.h | 2 + 2 files changed, 94 insertions(+) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index d1daa23..5577756 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -17481,6 +17481,36 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) } } + if (mIns.Size() >= 2 && !mFalseJump && mTrueJump && mTrueJump->mIns.Size() > 0) + { + int sz = mIns.Size(); + if (mIns[sz - 2].mType == ASMIT_LDA && mIns[sz - 2].mMode == ASMIM_ZERO_PAGE && + mIns[sz - 1].mType == ASMIT_ADC && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && mIns[sz - 1].mAddress == 0 && + mTrueJump->mIns[0].mType == ASMIT_STA && mTrueJump->mIns[0].SameEffectiveAddress(mIns[sz - 2]) && !(mTrueJump->mIns[0].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) + { + NativeCodeBasicBlock * tblock = mTrueJump->SplitAt(1); + mTrueJump->mNumEntries--; + mTrueJump->mEntryBlocks.RemoveAll(this); + + NativeCodeBasicBlock* iblock = proc->AllocateBlock(); + iblock->Close(mBranchIns, tblock, nullptr, ASMIT_JMP); + iblock->mIns.Push(NativeCodeInstruction(mIns[sz - 2].mIns, ASMIT_INC, mIns[sz - 2])); + mIns.SetSize(sz - 2); + mBranch = ASMIT_BCC; + mTrueJump = tblock; + mFalseJump = iblock; + + tblock->mNumEntries += 2; + tblock->mEntryBlocks.Push(this); + tblock->mEntryBlocks.Push(iblock); + iblock->mNumEntries = 1; + iblock->mEntryBlocks.Push(this); + + changed = true; + } + + } + if (mIns.Size() >= 8 && mFalseJump && (mBranch == ASMIT_BNE || mBranch == ASMIT_BEQ)) { int sz = mIns.Size(); @@ -35268,6 +35298,46 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass CheckLive(); #endif +#if 1 + // Move TAX and TAY down + + for (int i = 0; i + 1 < mIns.Size(); i++) + { + if (mIns[i].mType == ASMIT_TAX) + { + int j = i + 1; + while (j < mIns.Size() && !mIns[j].ReferencesXReg() && !mIns[j].ChangesAccu()) + j++; + if (j < mIns.Size() && mIns[j].mType == ASMIT_CPX && !(mIns[j].mLive & LIVE_CPU_REG_X)) + { + mIns[j].mType = ASMIT_CMP; + while (j > i) + { + j--; + mIns[j].mLive |= LIVE_CPU_REG_A; + } + changed = true; + } + } + else if (mIns[i].mType == ASMIT_TAY) + { + int j = i + 1; + while (j < mIns.Size() && !mIns[j].ReferencesYReg() && !mIns[j].ChangesAccu()) + j++; + if (j < mIns.Size() && mIns[j].mType == ASMIT_CPY && !(mIns[j].mLive & LIVE_CPU_REG_Y)) + { + mIns[j].mType = ASMIT_CMP; + while (j > i) + { + j--; + mIns[j].mLive |= LIVE_CPU_REG_A; + } + changed = true; + } + } + } + CheckLive(); +#endif #if 1 int taxPos = -1, tayPos = -1; for (int i = 0; i < mIns.Size(); i++) @@ -41230,6 +41300,28 @@ void NativeCodeBasicBlock::Close(const InterInstruction* ins, NativeCodeBasicBlo this->mBranchIns = ins; } +NativeCodeBasicBlock* NativeCodeBasicBlock::SplitAt(int at) +{ + NativeCodeBasicBlock* eblock = mProc->AllocateBlock(); + eblock->Close(mBranchIns, mTrueJump, mFalseJump, mBranch); + this->mBranch = ASMIT_JMP; + this->mFalseJump = nullptr; + this->mTrueJump = eblock; + for (int i = at; i < mIns.Size(); i++) + eblock->mIns.Push(mIns[i]); + mIns.SetSize(at); + eblock->mNumEntries = 1; + eblock->mEntryBlocks.Push(this); + eblock->mTrueJump->mEntryBlocks.RemoveAll(this); + eblock->mTrueJump->mEntryBlocks.Push(eblock); + if (eblock->mFalseJump) + { + eblock->mFalseJump->mEntryBlocks.RemoveAll(this); + eblock->mFalseJump->mEntryBlocks.Push(eblock); + } + return eblock; +} + NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void) { if (mBypassed) diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 79d26c4..fa69c8b 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -255,6 +255,8 @@ public: int JumpByteSize(NativeCodeBasicBlock * target, int offset); int BranchByteSize(NativeCodeBasicBlock* target, int from, int to); + NativeCodeBasicBlock* SplitAt(int at); + NativeCodeBasicBlock* BypassEmptyBlocks(void); int LeadsInto(NativeCodeBasicBlock* block, int dist); From 9e3b014927ea254741b24ede3161f05335a880b5 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 16 Oct 2023 21:51:20 +0200 Subject: [PATCH 160/169] Eliminate some simple dead X/Y loops --- oscar64/NativeCodeGenerator.cpp | 61 +++++++++++++++++++++++++++++++++ oscar64/NativeCodeGenerator.h | 1 + 2 files changed, 62 insertions(+) diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 5577756..37f60cc 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -16088,6 +16088,60 @@ bool NativeCodeBasicBlock::Split16BitLoopCount(NativeCodeProcedure* proc) return changed; } +bool NativeCodeBasicBlock::EliminateDeadLoops(void) +{ + bool changed = false; + if (!mVisited) + { + mVisited = true; + + if (mLoopHead && mNumEntries == 2 && mFalseJump) + { + NativeCodeBasicBlock* eblock = nullptr; + if (mTrueJump == this) + eblock = mFalseJump; + else if (mFalseJump == this) + eblock = mTrueJump; + + if (eblock) + { + if (mIns.Size() == 2 && (mIns[0].mType == ASMIT_INX || mIns[0].mType == ASMIT_DEX) && mIns[1].mType == ASMIT_CPX) + { + if (!(eblock->mEntryRequiredRegs[CPU_REG_X])) + { + mLoopHead = false; + mTrueJump = eblock; + mBranch = ASMIT_JMP; + mEntryBlocks.RemoveAll(this); + mNumEntries--; + changed = true; + } + } + else if (mIns.Size() == 2 && (mIns[0].mType == ASMIT_INY || mIns[0].mType == ASMIT_DEY) && mIns[1].mType == ASMIT_CPY) + { + if (!(eblock->mEntryRequiredRegs[CPU_REG_Y])) + { + mLoopHead = false; + mTrueJump = eblock; + mBranch = ASMIT_JMP; + mEntryBlocks.RemoveAll(this); + mNumEntries--; + changed = true; + } + } + } + } + + if (mTrueJump && mTrueJump->EliminateDeadLoops()) + changed = true; + if (mFalseJump && mFalseJump->EliminateDeadLoops()) + changed = true; + } + + return changed; +} + + bool NativeCodeBasicBlock::CrossBlockStoreLoadBypass(NativeCodeProcedure* proc) { bool changed = false; @@ -43115,6 +43169,13 @@ void NativeCodeProcedure::Optimize(void) changed = true; } + if (step >= 9) + { + ResetVisited(); + if (mEntryBlock->EliminateDeadLoops()) + changed = true; + } + #if _DEBUG ResetVisited(); mEntryBlock->CheckBlocks(); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index fa69c8b..2319579 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -584,6 +584,7 @@ public: bool SimplifyDiamond(NativeCodeProcedure* proc); bool SimplifyLoopEnd(NativeCodeProcedure* proc); bool CrossBlockStoreLoadBypass(NativeCodeProcedure* proc); + bool EliminateDeadLoops(void); bool CanBytepassLoad(const NativeCodeInstruction& ains, int from = 0) const; bool CanHoistStore(const NativeCodeInstruction& ains) const; From 0f5e9330021070a865b7f1ed4ec97a590cc5e9b7 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 18 Oct 2023 15:57:59 +0200 Subject: [PATCH 161/169] Optimize cross block constant propagation --- oscar64/InterCode.cpp | 164 +++++++++++++++++++++++++++++++- oscar64/InterCode.h | 4 + oscar64/Linker.cpp | 25 +++++ oscar64/NativeCodeGenerator.cpp | 69 +++++++++++++- oscar64/NativeCodeGenerator.h | 1 + 5 files changed, 256 insertions(+), 7 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 086b690..97caaf6 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16219,6 +16219,153 @@ static int TempUseDelta(const InterInstruction* ins) return d; } +bool InterCodeBasicBlock::IsConstExitTemp(int temp) const +{ + int n = mInstructions.Size() - 1; + while (n >= 0 && mInstructions[n]->mDst.mTemp != temp) + n--; + return n >= 0 && mInstructions[n]->mCode == IC_CONSTANT; +} + +bool InterCodeBasicBlock::SplitSingleBranchUseConst(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + if (!mLoopHead && mFalseJump) + { + for (int i = 0; i + 1 < mInstructions.Size(); i++) + { + InterInstruction* ins = mInstructions[i]; + + if (ins->mCode == IC_CONSTANT) + { + if (CanMoveInstructionBehindBlock(i)) + { + InterCodeBasicBlock* tblock = nullptr; + + if (mTrueJump->mEntryRequiredTemps[ins->mDst.mTemp] && !mFalseJump->mEntryRequiredTemps[ins->mDst.mTemp]) + tblock = mTrueJump; + else if (!mTrueJump->mEntryRequiredTemps[ins->mDst.mTemp] && mFalseJump->mEntryRequiredTemps[ins->mDst.mTemp]) + tblock = mFalseJump; + + if (tblock) + { + if (tblock->mNumEntries > 1) + { + InterCodeBasicBlock* nblock = new InterCodeBasicBlock(mProc); + + nblock->mEntryRequiredTemps = tblock->mEntryRequiredTemps; + nblock->mExitRequiredTemps = tblock->mEntryRequiredTemps; + + mExitRequiredTemps -= ins->mDst.mTemp; + nblock->mEntryRequiredTemps -= ins->mDst.mTemp; + + tblock->mEntryBlocks.RemoveAll(this); + tblock->mEntryBlocks.Push(nblock); + + if (tblock == mTrueJump) + mTrueJump = nblock; + else + mFalseJump = nblock; + + InterInstruction* jins = new InterInstruction(mInstructions.Last()->mLocation, IC_JUMP); + nblock->mInstructions.Push(jins); + nblock->Close(tblock, nullptr); + + nblock->mEntryBlocks.Push(this); + nblock->mNumEntries = 1; + + tblock = nblock; + } + + tblock->mInstructions.Insert(0, ins); + mInstructions.Remove(i); + i--; + changed = true; + } + } + } + } + } + + + if (mTrueJump && mTrueJump->SplitSingleBranchUseConst()) + changed = true; + if (mFalseJump && mFalseJump->SplitSingleBranchUseConst()) + changed = true; + } + + return changed; +} + + +bool InterCodeBasicBlock::CommonTailCodeMerge(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + if (!mLoopHead) + { + for (int i = 0; i + 1 < mInstructions.Size(); i++) + { + InterInstruction* ins = mInstructions[i]; + + if (CanMoveInstructionBeforeBlock(i)) + { + bool aconst = true, aany = false; + for (int j = 0; j < ins->mNumOperands; j++) + { + if (ins->mSrc[j].mTemp >= 0) + { + aany = true; + int k = 0; + while (k < mEntryBlocks.Size() && mEntryBlocks[k]->IsConstExitTemp(ins->mSrc[j].mTemp) && !mEntryBlocks[k]->mFalseJump) + k++; + if (k < mEntryBlocks.Size()) + { + aconst = false; + break; + } + } + } + + if (aconst && aany) + { + for (int j = 0; j < mEntryBlocks.Size(); j++) + { + InterCodeBasicBlock* eblock = mEntryBlocks[j]; + eblock->mInstructions.Insert(eblock->mInstructions.Size() - 1, ins->Clone()); + if (ins->mDst.mTemp >= 0) + eblock->mExitRequiredTemps += ins->mDst.mTemp; + } + if (ins->mDst.mTemp >= 0) + mEntryRequiredTemps += ins->mDst.mTemp; + ins->mCode = IC_NONE; + ins->mNumOperands = 0; + ins->mDst.mTemp = -1; + changed = true; + } + + } + } + } + + if (mTrueJump && mTrueJump->CommonTailCodeMerge()) + changed = true; + if (mFalseJump && mFalseJump->CommonTailCodeMerge()) + changed = true; + } + + return changed; +} + void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& staticVars) { int i; @@ -18021,6 +18168,17 @@ void InterCodeProcedure::PropagateConstOperationsUp(void) do { changed = false; + ResetVisited(); + if (mEntryBlock->SplitSingleBranchUseConst()) + changed = true; + + ResetVisited(); + if (mEntryBlock->CommonTailCodeMerge()) + { + changed = true; + BuildDataFlowSets(); + } + ResetVisited(); mEntryBlock->BuildConstTempSets(); @@ -18069,7 +18227,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "setspr"); + CheckFunc = !strcmp(mIdent->mString, "dungeon_rand_path"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -18775,15 +18933,11 @@ void InterCodeProcedure::Close(void) #if 1 do { DisassembleDebug("InConstP"); - CheckFinal(); TempForwarding(); - CheckFinal(); } while (GlobalConstantPropagation()); - CheckFinal(); BuildTraces(false); DisassembleDebug("Rebuilt traces"); - CheckFinal(); PeepholeOptimization(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 737417f..7835b2e 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -555,6 +555,10 @@ public: void CheckFinal(void); void CheckBlocks(void); + bool IsConstExitTemp(int temp) const; + bool CommonTailCodeMerge(void); + bool SplitSingleBranchUseConst(void); + void PeepholeOptimization(const GrowingVariableArray& staticVars); bool PeepholeReplaceOptimization(const GrowingVariableArray& staticVars); diff --git a/oscar64/Linker.cpp b/oscar64/Linker.cpp index 092dedf..030b9c1 100644 --- a/oscar64/Linker.cpp +++ b/oscar64/Linker.cpp @@ -1283,6 +1283,31 @@ bool Linker::WriteMapFile(const char* filename) } } + fprintf(file, "\nobjects by size\n"); + ExpandingArray so; + for (int i = 0; i < mObjects.Size(); i++) + { + LinkerObject* obj = mObjects[i]; + + if ((obj->mFlags & LOBJF_REFERENCED) && obj->mIdent) + { + int k = so.Size(); + so.Push(obj); + while (k > 0 && so[k - 1]->mSize < obj->mSize) + { + so[k] = so[k - 1]; + k--; + } + so[k] = obj; + } + } + + for (int i = 0; i < so.Size(); i++) + { + const LinkerObject* obj = so[i]; + fprintf(file, "%04x (%04x) : %s, %s:%s\n", obj->mAddress, obj->mSize, obj->mIdent->mString, LinkerObjectTypeNames[obj->mType], obj->mSection->mIdent->mString); + } + fclose(file); return true; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 37f60cc..7da5edd 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -18844,6 +18844,63 @@ void NativeCodeBasicBlock::PrependInstruction(const NativeCodeInstruction& ins) mIns[0].mLive |= LIVE_CPU_REG_C; } +bool NativeCodeBasicBlock::ShortcutBlockExit(void) +{ + bool changed = false; + if (!mVisited) + { + mVisited = true; + + if (!mLoopHead && mTrueJump && mFalseJump && !mTrueJump->mLoopHead && !mFalseJump->mLoopHead) + { + for (int i = 0; i < mTrueJump->mEntryBlocks.Size(); i++) + { + NativeCodeBasicBlock* eblock = mTrueJump->mEntryBlocks[i]; + if (eblock != this) + { + if (eblock->mTrueJump == mTrueJump && eblock->mFalseJump == mFalseJump && eblock->mBranch == mBranch) + { + int n = mIns.Size(), m = eblock->mIns.Size(); + if (m > 0 && n >= m) + { + while (m > 0 && mIns[n - 1].IsSame(eblock->mIns[m - 1])) + { + n--; + m--; + } + + if (m == 0) + { + mTrueJump->mNumEntries--; + mTrueJump->mEntryBlocks.RemoveAll(this); + mFalseJump->mNumEntries--; + mFalseJump->mEntryBlocks.RemoveAll(this); + mFalseJump = nullptr; + mTrueJump = eblock; + eblock->mNumEntries++; + eblock->mEntryBlocks.Push(this); + + mIns.SetSize(n); + mBranch = ASMIT_JMP; + changed = true; + break; + } + } + } + } + } + } + + if (mTrueJump && mTrueJump->ShortcutBlockExit()) + changed = true; + if (mFalseJump && mFalseJump->ShortcutBlockExit()) + changed = true; + + } + + return changed; +} + bool NativeCodeBasicBlock::PropagateSinglePath(void) { bool changed = false; @@ -41965,7 +42022,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "mat4_mmul"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "cursor_joy_exit"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -42634,7 +42691,7 @@ void NativeCodeProcedure::Optimize(void) ResetPatched(); mEntryBlock->CheckVisited(); } - + } while (bchanged); } @@ -42892,6 +42949,14 @@ void NativeCodeProcedure::Optimize(void) if (mEntryBlock->PropagateSinglePath()) changed = true; } + + if (step > 4) + { + ResetVisited(); + if (mEntryBlock->ShortcutBlockExit()) + changed = true; + } + #endif #if _DEBUG diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 2319579..e32638d 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -515,6 +515,7 @@ public: bool IsExitXRegZP(int addr, int& index) const; bool IsExitARegZP(int addr, int& index) const; + bool ShortcutBlockExit(void); bool PropagateSinglePath(void); bool CanChangeTailZPStoreToX(int addr, const NativeCodeBasicBlock * nblock, const NativeCodeBasicBlock* fblock = nullptr) const; From f7d6b520743484f20951d0bbac9addf391c91630 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 18 Oct 2023 20:26:11 +0200 Subject: [PATCH 162/169] Fixed striped auto pointer --- oscar64/InterCodeGenerator.cpp | 2 ++ oscar64/NativeCodeGenerator.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 2dd0e6d..79c9bdc 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -2890,6 +2890,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a pointer type"); else if (vl.mType->mStride != 1) vl = Dereference(proc, exp, block, vl, 0); + else + return ExValue(vl.mType->mBase, vl.mTemp, vl.mReference + 1); return ExValue(vl.mType->mBase, vl.mTemp, 1); case TK_BINARY_AND: { diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 7da5edd..511e02a 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -42022,7 +42022,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "cursor_joy_exit"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "enemies_move_show"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; From 6cb15fd7d9bfccaefde52dca55d35540f1974b86 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 19 Oct 2023 17:27:09 +0200 Subject: [PATCH 163/169] Improve incompatible type error message --- oscar64/Declaration.cpp | 3 +++ oscar64/Errors.cpp | 21 +++++++++++++-------- oscar64/Errors.h | 4 ++-- oscar64/InterCodeGenerator.cpp | 14 +++++++------- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 1e19268..19ab071 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1153,6 +1153,9 @@ Declaration* Declaration::Last(void) const Ident* Declaration::MangleIdent(void) { + if (!this) + return Ident::Unique("null"); + if (!mMangleIdent) { if (mType == DT_CONST_INTEGER) diff --git a/oscar64/Errors.cpp b/oscar64/Errors.cpp index 5522e47..dc8c13d 100644 --- a/oscar64/Errors.cpp +++ b/oscar64/Errors.cpp @@ -9,15 +9,18 @@ Errors::Errors(void) } -void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info) +void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info1, const Ident* info2) { - if (info) - this->Error(loc, eid, msg, info->mString); - else + if (!info1) this->Error(loc, eid, msg); + else if (!info2) + this->Error(loc, eid, msg, info1->mString); + else + this->Error(loc, eid, msg, info1->mString, info2->mString); } -void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char* info) + +void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char* info1, const char * info2) { const char* level = "info"; if (eid >= EERR_GENERIC) @@ -30,10 +33,12 @@ void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char level = "warning"; } - if (info) - fprintf(stderr, "%s(%d, %d) : %s %d: %s '%s'\n", loc.mFileName, loc.mLine, loc.mColumn, level ,eid, msg, info); - else + if (!info1) fprintf(stderr, "%s(%d, %d) : %s %d: %s\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg); + else if (!info2) + fprintf(stderr, "%s(%d, %d) : %s %d: %s '%s'\n", loc.mFileName, loc.mLine, loc.mColumn, level ,eid, msg, info1); + else + fprintf(stderr, "%s(%d, %d) : %s %d: %s '%s' != '%s'\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg, info1, info2); if (mErrorCount > 10 || eid >= EFATAL_GENERIC) exit(20); diff --git a/oscar64/Errors.h b/oscar64/Errors.h index f26cefd..e2b734f 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -110,6 +110,6 @@ public: int mErrorCount; - void Error(const Location& loc, ErrorID eid, const char* msg, const Ident * info); - void Error(const Location& loc, ErrorID eid, const char* msg, const char* info = nullptr); + void Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info1, const Ident* info2 = nullptr); + void Error(const Location& loc, ErrorID eid, const char* msg, const char* info1 = nullptr, const char* info2 = nullptr); }; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 79c9bdc..907fc73 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1244,7 +1244,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro if (!(pdec && pdec->mBase->IsReference()) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) { if (pdec && !pdec->mBase->CanAssign(vr.mType)) - mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types", pdec->mBase->MangleIdent(), vr.mType->MangleIdent()); vr = Dereference(proc, texp, block, vr, 1); @@ -1273,7 +1273,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro if (!pdec->mBase->CanAssign(vr.mType)) { pdec->mBase->CanAssign(vr.mType); - mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types", pdec->mBase->MangleIdent(), vr.mType->MangleIdent()); } vr = CoerceType(proc, texp, block, vr, pdec->mBase); } @@ -2076,7 +2076,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* 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", vl.mType->MangleIdent(), vr.mType->MangleIdent()); } } @@ -2178,7 +2178,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Invalid pointer assignment"); if (!vr.mType->IsIntegerType()) - mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Invalid argument for pointer inc/dec"); + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Invalid argument for pointer inc/dec", vr.mType->MangleIdent()); cins->mDst.mType = IT_INT16; cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); @@ -2997,7 +2997,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if ((mCompilerOptions & COPT_CPLUSPLUS) && (vl.mType->mBase->IsSubType(vr.mType->mBase) || vr.mType->mBase->IsSubType(vl.mType->mBase))) ; else if (!vl.mType->mBase->IsConstSame(vr.mType->mBase)) - mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible pointer types"); + mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible pointer types", vl.mType->mBase->MangleIdent(), vr.mType->mBase->MangleIdent()); } else mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible pointer types"); @@ -3514,7 +3514,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!(pdec && pdec->mBase->IsReference()) && (vr.mType->mType == DT_TYPE_STRUCT || vr.mType->mType == DT_TYPE_UNION)) { if (pdec && !pdec->mBase->CanAssign(vr.mType)) - mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types", pdec->mBase->MangleIdent(), vr.mType->MangleIdent()); vr = Dereference(proc, texp, block, vr, 1); @@ -3569,7 +3569,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!(pdec->mFlags & DTF_FPARAM_UNUSED) && !pdec->mBase->CanAssign(vr.mType)) { pdec->mBase->CanAssign(vr.mType); - mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types", pdec->mBase->MangleIdent(), vr.mType->MangleIdent()); } vr = CoerceType(proc, texp, block, vr, pdec->mBase); } From 6e4bf52781e2aab7eebd3d3ef7097fcc53966b6d Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:15:01 +0200 Subject: [PATCH 164/169] Optimize switch case tree --- oscar64/InterCodeGenerator.cpp | 93 +++++++++++++++++++++++----------- oscar64/InterCodeGenerator.h | 2 +- 2 files changed, 65 insertions(+), 30 deletions(-) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 907fc73..efd1855 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1051,40 +1051,53 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex assert(offset == osize); } -void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, InterCodeBasicBlock* dblock) +void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock) { - if (right - left < 5) + if (right - left < 3) { for (int i = left; i < right; i++) { - InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc); + if (vleft == vright) + { + InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + block->Append(jins); + block->Close(nodes[i].mBlock, nullptr); + return; + } + else + { + InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc); - InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); - vins->mConst.mType = IT_INT16; - vins->mConst.mIntConst = nodes[i].mValue; - vins->mDst.mType = IT_INT16; - vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType); - block->Append(vins); + InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); + vins->mConst.mType = IT_INT16; + vins->mConst.mIntConst = nodes[i].mValue; + vins->mDst.mType = IT_INT16; + vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType); + block->Append(vins); - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); - cins->mOperator = IA_CMPEQ; - cins->mSrc[0].mType = vins->mDst.mType; - cins->mSrc[0].mTemp = vins->mDst.mTemp; - cins->mSrc[1].mType = vins->mDst.mType; - cins->mSrc[1].mTemp = v.mTemp; - cins->mDst.mType = IT_BOOL; - cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); + cins->mOperator = IA_CMPEQ; + cins->mSrc[0].mType = vins->mDst.mType; + cins->mSrc[0].mTemp = vins->mDst.mTemp; + cins->mSrc[1].mType = vins->mDst.mType; + cins->mSrc[1].mTemp = v.mTemp; + cins->mDst.mType = IT_BOOL; + cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); - block->Append(cins); + block->Append(cins); - InterInstruction* bins = new InterInstruction(exp->mLocation, IC_BRANCH); - bins->mSrc[0].mType = IT_BOOL; - bins->mSrc[0].mTemp = cins->mDst.mTemp; - block->Append(bins); + InterInstruction* bins = new InterInstruction(exp->mLocation, IC_BRANCH); + bins->mSrc[0].mType = IT_BOOL; + bins->mSrc[0].mTemp = cins->mDst.mTemp; + block->Append(bins); - block->Close(nodes[i].mBlock, cblock); + block->Close(nodes[i].mBlock, cblock); - block = cblock; + block = cblock; + + if (vleft == nodes[i].mValue) + vleft = nodes[i].mValue + 1; + } } InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); @@ -1094,7 +1107,8 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e } else { - int center = (left + right + 1) >> 1; + int center = (left + right) >> 1; + int vcenter = nodes[center].mValue; InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* rblock = new InterCodeBasicBlock(proc); @@ -1102,7 +1116,7 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); vins->mConst.mType = IT_INT16; - vins->mConst.mIntConst = nodes[center].mValue; + vins->mConst.mIntConst = vcenter; vins->mDst.mType = IT_INT16; vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType); block->Append(vins); @@ -1143,8 +1157,8 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e cblock->Close(lblock, rblock); - BuildSwitchTree(proc, exp, lblock, v, nodes, left, center, dblock); - BuildSwitchTree(proc, exp, rblock, v, nodes, center + 1, right, dblock); + BuildSwitchTree(proc, exp, lblock, v, nodes, left, center, vleft, vcenter -1, dblock); + BuildSwitchTree(proc, exp, rblock, v, nodes, center + 1, right, vcenter + 1, vright, dblock); } } @@ -1434,6 +1448,7 @@ void InterCodeGenerator::CopyStructSimple(InterCodeProcedure* proc, Expression * cins->mSrc[1].mType = IT_POINTER; cins->mSrc[1].mTemp = vl.mTemp; cins->mSrc[1].mMemory = IM_INDIRECT; + cins->mSrc[1].mStride = vl.mType->mStripe; cins->mConst.mOperandSize = vl.mType->mSize; block->Append(cins); @@ -4752,6 +4767,25 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = Dereference(proc, exp, block, vl); + + int vleft = 0, vright = 65535; + + if (vl.mType->mSize == 1) + { + if (vl.mType->mFlags & DTF_SIGNED) + { + vleft = -128; + vright = 127; + } + else + vright = 255; + } + else if (vl.mType->mFlags & DTF_SIGNED) + { + vleft = -32768; + vright = 32767; + } + vl = CoerceType(proc, exp, block, vl, TheSignedIntTypeDeclaration); InterCodeBasicBlock * dblock = nullptr; @@ -4824,7 +4858,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* sexp = sexp->mRight; } - BuildSwitchTree(proc, exp, sblock, vl, switchNodes, 0, switchNodes.Size(), dblock ? dblock : eblock); + + BuildSwitchTree(proc, exp, sblock, vl, switchNodes, 0, switchNodes.Size(), vleft, vright, dblock ? dblock : eblock); if (block) { diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 67d3e2a..544a8b4 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -78,7 +78,7 @@ protected: InterCodeProcedure* mMainInitProc; InterCodeBasicBlock* mMainInitBlock; - void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, InterCodeBasicBlock* dblock); + void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock); ExValue ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v); ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level = 0); From aad35e02430d65c64ec3d5cc71c295a4a8b6a192 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 22 Oct 2023 12:14:15 +0200 Subject: [PATCH 165/169] Fix IEC drive timing --- include/c64/iecbus.c | 50 +++++++++++++++++++------------------------- include/c64/iecbus.h | 3 ++- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/include/c64/iecbus.c b/include/c64/iecbus.c index aef034a..a9560ff 100644 --- a/include/c64/iecbus.c +++ b/include/c64/iecbus.c @@ -14,14 +14,14 @@ IEC_STATUS iec_status; #pragma optimize(push) #pragma optimize(1) +// multiples of 5us static void delay(char n) { - while (n) - { - __asm { - nop - } - n--; + __asm { + ldx n + l1: + dex + bne l1 } } @@ -70,7 +70,7 @@ static bool data_check(void) return true; else { - iec_status = IEC_TIMEOUT; + iec_status = IEC_DATA_CHECK; return false; } } @@ -81,7 +81,7 @@ bool iec_eoi(void) while (!(cia2.pra & CIA2B_DATAIN)) ; - delay(50); + delay(40); return data_check(); } @@ -93,25 +93,21 @@ bool iec_write(char b) while (!(cia2.pra & CIA2B_DATAIN)) ; + clock_high(); + for(char i=0; i<8; i++) { - clock_high(); if (b & 1) data_low(); else data_high(); + delay(5); clock_low(); b >>= 1; - __asm - { - nop - nop - nop - nop - } + delay(5); + clock_high(); + data_low(); } - data_low(); - clock_high(); return data_check(); } @@ -131,13 +127,7 @@ char iec_read(void) { iec_status = IEC_EOF; data_high(); - __asm - { - nop - nop - nop - nop - } + delay(4); data_low(); cnt = 200; @@ -172,10 +162,11 @@ char iec_read(void) void iec_atn(char dev, char sec) { + cdata_low(); atn_high(); clock_high(); - delay(100); + delay(200); iec_write(dev); if (sec != 0xff) @@ -190,8 +181,10 @@ void iec_talk(char dev, char sec) { iec_status = IEC_OK; - iec_atn(dev | 0x40, sec); + iec_atn(dev | 0x40, sec | 0x60); clock_low(); + + delay(10); } void iec_untalk(void) @@ -203,7 +196,7 @@ void iec_listen(char dev, char sec) { iec_status = IEC_OK; - iec_atn(dev | 0x20, sec); + iec_atn(dev | 0x20, sec | 0x60); } void iec_unlisten(void) @@ -216,6 +209,7 @@ void iec_open(char dev, char sec, const char * fname) iec_status = IEC_OK; iec_atn(dev | 0x20, sec | 0xf0); + char i = 0; while (fname[i]) { diff --git a/include/c64/iecbus.h b/include/c64/iecbus.h index 1ffdbee..cd4d4f5 100644 --- a/include/c64/iecbus.h +++ b/include/c64/iecbus.h @@ -7,7 +7,8 @@ enum IEC_STATUS IEC_EOF = 0x01, IEC_ERROR = 0x80, - IEC_TIMEOUT + IEC_TIMEOUT, + IEC_DATA_CHECK }; extern IEC_STATUS iec_status; From 3377ac04fcc9ad021c90f58d890d7e6fb8444b26 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 22 Oct 2023 12:34:26 +0200 Subject: [PATCH 166/169] Fix const use and vtable incompatibility --- oscar64/Parser.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 64fc32e..4c5fd7f 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -486,6 +486,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio } dec->SetDefined(); + if (dec->mConst) + dec->mConst->mSize = dec->mSize; if ((mCompilerOptions & COPT_CPLUSPLUS) && dec->mType == DT_TYPE_STRUCT && dec->mIdent) { @@ -530,6 +532,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio mdec = mdec->mNext; } dec->mSize++; + if (dec->mConst) + dec->mConst->mSize = dec->mSize; } dec->mScope->Iterate([=](const Ident* ident, Declaration* mdec) From f8f81f6d4c4f13e854628a4af5be505b6b3d8b26 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 22 Oct 2023 19:35:37 +0200 Subject: [PATCH 167/169] Optimize compile time --- oscar64/InterCode.cpp | 68 ++++++++++++++++---------------- oscar64/InterCode.h | 1 + oscar64/NativeCodeGenerator.cpp | 50 +++++++++++++---------- oscar64/NativeCodeGenerator.h | 2 + oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 ++-- oscar64setup/oscar64setup.vdproj | 58 +++++++++++++++++++++++++-- 7 files changed, 128 insertions(+), 61 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 97caaf6..09176ad 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -8100,8 +8100,8 @@ void InterCodeBasicBlock::BuildConstTempSets(void) { mVisited = true; - mEntryConstTemp = NumberSet(mEntryRequiredTemps.Size()); - mExitConstTemp = NumberSet(mEntryRequiredTemps.Size()); + mEntryConstTemp.Reset(mEntryRequiredTemps.Size()); + mExitConstTemp.Reset(mEntryRequiredTemps.Size()); for (i = 0; i < mInstructions.Size(); i++) { @@ -8594,18 +8594,20 @@ bool InterCodeBasicBlock::BuildGlobalRequiredTempSet(NumberSet& fromRequiredTemp { mVisited = true; - NumberSet newRequiredTemps(mExitRequiredTemps); + mNewRequiredTemps = mExitRequiredTemps; - if (mTrueJump && mTrueJump->BuildGlobalRequiredTempSet(newRequiredTemps)) revisit = true; - if (mFalseJump && mFalseJump->BuildGlobalRequiredTempSet(newRequiredTemps)) revisit = true; +// NumberSet newRequiredTemps(mExitRequiredTemps); - if (!(newRequiredTemps <= mExitRequiredTemps)) + if (mTrueJump && mTrueJump->BuildGlobalRequiredTempSet(mNewRequiredTemps)) revisit = true; + if (mFalseJump && mFalseJump->BuildGlobalRequiredTempSet(mNewRequiredTemps)) revisit = true; + + if (!(mNewRequiredTemps <= mExitRequiredTemps)) { revisit = true; - mExitRequiredTemps = newRequiredTemps; - newRequiredTemps -= mLocalProvidedTemps; - mEntryRequiredTemps |= newRequiredTemps; + mExitRequiredTemps = mNewRequiredTemps; + mNewRequiredTemps -= mLocalProvidedTemps; + mEntryRequiredTemps |= mNewRequiredTemps; } } @@ -8716,13 +8718,13 @@ void InterCodeBasicBlock::BuildStaticVariableSet(const GrowingVariableArray& sta { mVisited = true; - mLocalRequiredStatics = NumberSet(staticVars.Size()); - mLocalProvidedStatics = NumberSet(staticVars.Size()); + mLocalRequiredStatics.Reset(staticVars.Size()); + mLocalProvidedStatics.Reset(staticVars.Size()); - mEntryRequiredStatics = NumberSet(staticVars.Size()); - mEntryProvidedStatics = NumberSet(staticVars.Size()); - mExitRequiredStatics = NumberSet(staticVars.Size()); - mExitProvidedStatics = NumberSet(staticVars.Size()); + mEntryRequiredStatics.Reset(staticVars.Size()); + mEntryProvidedStatics.Reset(staticVars.Size()); + mExitRequiredStatics.Reset(staticVars.Size()); + mExitProvidedStatics.Reset(staticVars.Size()); for (int i = 0; i < mInstructions.Size(); i++) mInstructions[i]->FilterStaticVarsUsage(staticVars, mLocalRequiredStatics, mLocalProvidedStatics); @@ -8819,13 +8821,13 @@ void InterCodeBasicBlock::BuildStaticVariableByteSet(const GrowingVariableArray& { mVisited = true; - mLocalRequiredStatics = NumberSet(bsize); - mLocalProvidedStatics = NumberSet(bsize); + mLocalRequiredStatics.Reset(bsize); + mLocalProvidedStatics.Reset(bsize); - mEntryRequiredStatics = NumberSet(bsize); - mEntryProvidedStatics = NumberSet(bsize); - mExitRequiredStatics = NumberSet(bsize); - mExitProvidedStatics = NumberSet(bsize); + mEntryRequiredStatics.Reset(bsize); + mEntryProvidedStatics.Reset(bsize); + mExitRequiredStatics.Reset(bsize); + mExitProvidedStatics.Reset(bsize); for (int i = 0; i < mInstructions.Size(); i++) mInstructions[i]->FilterStaticVarsByteUsage(staticVars, mLocalRequiredStatics, mLocalProvidedStatics); @@ -8881,21 +8883,21 @@ void InterCodeBasicBlock::BuildLocalVariableSets(const GrowingVariableArray& loc { mVisited = true; - mLocalRequiredVars = NumberSet(localVars.Size()); - mLocalProvidedVars = NumberSet(localVars.Size()); + mLocalRequiredVars.Reset(localVars.Size()); + mLocalProvidedVars.Reset(localVars.Size()); - mEntryRequiredVars = NumberSet(localVars.Size()); - mEntryProvidedVars = NumberSet(localVars.Size()); - mExitRequiredVars = NumberSet(localVars.Size()); - mExitProvidedVars = NumberSet(localVars.Size()); + mEntryRequiredVars.Reset(localVars.Size()); + mEntryProvidedVars.Reset(localVars.Size()); + mExitRequiredVars.Reset(localVars.Size()); + mExitProvidedVars.Reset(localVars.Size()); - mLocalRequiredParams = NumberSet(params.Size()); - mLocalProvidedParams = NumberSet(params.Size()); + mLocalRequiredParams.Reset(params.Size()); + mLocalProvidedParams.Reset(params.Size()); - mEntryRequiredParams = NumberSet(params.Size()); - mEntryProvidedParams = NumberSet(params.Size()); - mExitRequiredParams = NumberSet(params.Size()); - mExitProvidedParams = NumberSet(params.Size()); + mEntryRequiredParams.Reset(params.Size()); + mEntryProvidedParams.Reset(params.Size()); + mExitRequiredParams.Reset(params.Size()); + mExitProvidedParams.Reset(params.Size()); for (i = 0; i < mInstructions.Size(); i++) { diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 7835b2e..f12f0e3 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -368,6 +368,7 @@ public: NumberSet mEntryRequiredTemps, mEntryProvidedTemps, mEntryPotentialTemps; NumberSet mExitRequiredTemps, mExitProvidedTemps, mExitPotentialTemps; NumberSet mEntryConstTemp, mExitConstTemp; + NumberSet mNewRequiredTemps; NumberSet mLocalRequiredVars, mLocalProvidedVars; NumberSet mEntryRequiredVars, mEntryProvidedVars; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 511e02a..73fa14c 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -95,13 +95,9 @@ void NativeRegisterDataSet::ResetMask(void) void NativeRegisterDataSet::ResetWorkRegs(void) { ResetZeroPage(BC_REG_WORK_Y); - ResetZeroPage(BC_REG_ADDR + 0); - ResetZeroPage(BC_REG_ADDR + 1); - - for (int i = 0; i < 4; i++) - ResetZeroPage(BC_REG_ACCU + i); - for (int i = 0; i < 8; i++) - ResetZeroPage(BC_REG_WORK + i); + ResetZeroPageRange(BC_REG_ADDR, 2); + ResetZeroPageRange(BC_REG_ACCU, 4); + ResetZeroPageRange(BC_REG_WORK, 8); } void NativeRegisterDataSet::ResetWorkMasks(void) @@ -129,6 +125,20 @@ void NativeRegisterDataSet::ResetZeroPage(int addr) } } +void NativeRegisterDataSet::ResetZeroPageRange(int addr, int num) +{ + for(int i=0; i= addr && mRegs[i].mValue < addr + num) + mRegs[i].Reset(); + else if (mRegs[i].mMode == NRDM_INDIRECT_Y && mRegs[i].mValue + 1 >= addr && mRegs[i].mValue < addr + num) + mRegs[i].Reset(); + } +} + + int NativeRegisterDataSet::FindAbsolute(LinkerObject* linkerObject, int addr) { for (int i = 0; i < 256; i++) @@ -12467,13 +12477,13 @@ void NativeCodeBasicBlock::BuildLocalRegSets(void) { mVisited = true; - mLocalRequiredRegs = NumberSet(NUM_REGS); - mLocalProvidedRegs = NumberSet(NUM_REGS); + mLocalRequiredRegs.Reset(NUM_REGS); + mLocalProvidedRegs.Reset(NUM_REGS); - mEntryRequiredRegs = NumberSet(NUM_REGS); - mEntryProvidedRegs = NumberSet(NUM_REGS); - mExitRequiredRegs = NumberSet(NUM_REGS); - mExitProvidedRegs = NumberSet(NUM_REGS); + mEntryRequiredRegs.Reset(NUM_REGS); + mEntryProvidedRegs.Reset(NUM_REGS); + mExitRequiredRegs.Reset(NUM_REGS); + mExitProvidedRegs.Reset(NUM_REGS); if (mEntryRegA) mLocalProvidedRegs += CPU_REG_A; @@ -12546,18 +12556,18 @@ bool NativeCodeBasicBlock::BuildGlobalRequiredRegSet(NumberSet& fromRequiredRegs { mVisited = true; - NumberSet newRequiredRegs(mExitRequiredRegs); + mNewRequiredRegs = mExitRequiredRegs; - if (mTrueJump && mTrueJump->BuildGlobalRequiredRegSet(newRequiredRegs)) revisit = true; - if (mFalseJump && mFalseJump->BuildGlobalRequiredRegSet(newRequiredRegs)) revisit = true; + if (mTrueJump && mTrueJump->BuildGlobalRequiredRegSet(mNewRequiredRegs)) revisit = true; + if (mFalseJump && mFalseJump->BuildGlobalRequiredRegSet(mNewRequiredRegs)) revisit = true; - if (!(newRequiredRegs <= mExitRequiredRegs)) + if (!(mNewRequiredRegs <= mExitRequiredRegs)) { revisit = true; - mExitRequiredRegs = newRequiredRegs; - newRequiredRegs -= mLocalProvidedRegs; - mEntryRequiredRegs |= newRequiredRegs; + mExitRequiredRegs = mNewRequiredRegs; + mNewRequiredRegs -= mLocalProvidedRegs; + mEntryRequiredRegs |= mNewRequiredRegs; } } diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index e32638d..07c27dd 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -45,6 +45,7 @@ struct NativeRegisterDataSet void ResetMask(void); void ResetZeroPage(int addr); + void ResetZeroPageRange(int addr, int num); void ResetAbsolute(LinkerObject * linkerObject, int addr); int FindAbsolute(LinkerObject* linkerObject, int addr); void ResetIndirect(int reg); @@ -369,6 +370,7 @@ public: NumberSet mLocalRequiredRegs, mLocalProvidedRegs; NumberSet mEntryRequiredRegs, mEntryProvidedRegs; NumberSet mExitRequiredRegs, mExitProvidedRegs; + NumberSet mNewRequiredRegs; NumberSet mTempRegs; void BuildLocalRegSets(void); diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 7c48217..b588cd6 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.26.224"); + strcpy(strProductVersion, "1.26.225"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index e52501f..60ea412 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,26,224,0 - PRODUCTVERSION 1,26,224,0 + FILEVERSION 1,26,225,0 + PRODUCTVERSION 1,26,225,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.26.224.0" + VALUE "FileVersion", "1.26.225.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.26.224.0" + VALUE "ProductVersion", "1.26.225.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 2791258..0eea676 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -52,6 +52,12 @@ } "Entry" { + "MsmKey" = "8:_071415C872DB4A94B28137BD7FE1F669" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_071CF34574024DBD95D2203D6E4279D0" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1150,6 +1156,12 @@ } "Entry" { + "MsmKey" = "8:_ED20DE3FDC8A400296E92AE0D37D8665" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_ED5FED616EA64689AB793E5D8BD3F13D" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1439,6 +1451,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_071415C872DB4A94B28137BD7FE1F669" + { + "SourcePath" = "8:..\\include\\opp\\slab.h" + "TargetName" = "8:slab.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_071CF34574024DBD95D2203D6E4279D0" { "SourcePath" = "8:..\\include\\opp\\iostream.h" @@ -5099,6 +5131,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ED20DE3FDC8A400296E92AE0D37D8665" + { + "SourcePath" = "8:..\\include\\opp\\static_vector.h" + "TargetName" = "8:static_vector.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ED5FED616EA64689AB793E5D8BD3F13D" { "SourcePath" = "8:..\\include\\nes\\mmc3.c" @@ -5712,15 +5764,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{F884314C-DBC1-466B-9A34-1761B921E1BD}" - "PackageCode" = "8:{5563B34B-0822-45A3-85A4-8007E3D57051}" + "ProductCode" = "8:{50B8F261-E014-4D97-807C-8B181651E0CF}" + "PackageCode" = "8:{73E601A2-834D-4280-AFAD-0E275AEDBF01}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.26.224" + "ProductVersion" = "8:1.26.225" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" From 0a3ad006b7b69cedacdf1c4995071159d1a83ee2 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 22 Oct 2023 19:50:26 +0200 Subject: [PATCH 168/169] Fix simple struct member optimization for array cases --- oscar64/InterCodeGenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index efd1855..9cbc742 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1396,7 +1396,7 @@ void InterCodeGenerator::CopyStructSimple(InterCodeProcedure* proc, Expression * Declaration* dec = vl.mType->mParams; while (dec) { - if (dec->mType == DT_ELEMENT && !(dec->mFlags & DTF_STATIC)) + if (dec->mType == DT_ELEMENT && !(dec->mFlags & DTF_STATIC) && dec->mBase->IsSimpleType()) { mdec = dec->mBase; ne++; From 982fe17aed810826a548ae808c2beaa4b501d4df Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:29:46 +0200 Subject: [PATCH 169/169] Fix compiler crash when using function result in if condition --- include/c64/vic.c | 9 + include/c64/vic.h | 3 + include/opp/string.cpp | 2 +- oscar64/Errors.cpp | 4 + oscar64/Errors.h | 11 +- oscar64/InterCode.cpp | 23 ++ oscar64/InterCode.h | 1 + oscar64/InterCodeGenerator.cpp | 611 ++++++++++++++++---------------- oscar64/InterCodeGenerator.h | 15 +- oscar64/NativeCodeGenerator.cpp | 9 + oscar64/Parser.cpp | 1 + 11 files changed, 378 insertions(+), 311 deletions(-) diff --git a/include/c64/vic.c b/include/c64/vic.c index 43894a1..ba602fa 100644 --- a/include/c64/vic.c +++ b/include/c64/vic.c @@ -73,6 +73,15 @@ void vic_waitFrame(void) ; } +void vic_waitFrames(char n) +{ + while (n > 0) + { + vic_waitFrame(); + n--; + } +} + void vic_waitLine(int line) { char upper = (char)(line >> 1) & VIC_CTRL1_RST8; diff --git a/include/c64/vic.h b/include/c64/vic.h index 430de53..d420778 100644 --- a/include/c64/vic.h +++ b/include/c64/vic.h @@ -109,6 +109,9 @@ inline void vic_waitTop(void); // wait for the top of the frame and then for the bottom of the visual area inline void vic_waitFrame(void); +// wait for n frames +void vic_waitFrames(char n); + // wait for a specific raster line void vic_waitLine(int line); diff --git a/include/opp/string.cpp b/include/opp/string.cpp index f72d1c4..0b4da19 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -516,7 +516,7 @@ const char * string::cend(void) const string string::substr(char pos, char len) const { if (!cstr || len == 0 || pos >= cstr[0]) - return string; + return string(); else { char l = cstr[0]; diff --git a/oscar64/Errors.cpp b/oscar64/Errors.cpp index dc8c13d..e77fbb0 100644 --- a/oscar64/Errors.cpp +++ b/oscar64/Errors.cpp @@ -40,6 +40,10 @@ void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char else fprintf(stderr, "%s(%d, %d) : %s %d: %s '%s' != '%s'\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg, info1, info2); + if (loc.mFrom) + + Error(*(loc.mFrom), EINFO_EXPANDED, "While expanding here"); + if (mErrorCount > 10 || eid >= EFATAL_GENERIC) exit(20); } diff --git a/oscar64/Errors.h b/oscar64/Errors.h index e2b734f..5a62749 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -3,10 +3,14 @@ class Location { public: - const char* mFileName; - int mLine, mColumn; + const char * mFileName; + int mLine, mColumn; + const Location * mFrom; - Location() : mFileName(nullptr), mLine(0), mColumn(0) {} + Location() : mFileName(nullptr), mLine(0), mColumn(0), mFrom(nullptr) {} + Location(const Location& loc, const Location* from) + : mFileName(loc.mFileName), mLine(loc.mLine), mColumn(loc.mColumn), mFrom(from) + {} }; class Ident; @@ -14,6 +18,7 @@ class Ident; enum ErrorID { EINFO_GENERIC = 1000, + EINFO_EXPANDED = 1001, EWARN_GENERIC = 2000, EWARN_CONSTANT_TRUNCATED, diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 09176ad..7b366d9 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16826,6 +16826,26 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati } } +void InterCodeBasicBlock::CheckNullptrDereference(void) +{ + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* ins = mInstructions[i]; + if (ins->mCode == IC_LOAD && ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_ABSOLUTE && ins->mSrc[0].mIntConst == 0 && !ins->mVolatile) + mProc->mModule->mErrors->Error(ins->mLocation, EWARN_NULL_POINTER_DEREFERENCED, "nullptr dereferenced"); + else if (ins->mCode == IC_STORE && ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_ABSOLUTE && ins->mSrc[1].mIntConst == 0 && !ins->mVolatile) + mProc->mModule->mErrors->Error(ins->mLocation, EWARN_NULL_POINTER_DEREFERENCED, "nullptr dereferenced"); + } + + if (mTrueJump) mTrueJump->CheckNullptrDereference(); + if (mFalseJump) mFalseJump->CheckNullptrDereference(); + } +} + void InterCodeBasicBlock::CheckValueReturn(void) { if (!mVisited) @@ -19088,6 +19108,9 @@ void InterCodeProcedure::Close(void) mEntryBlock->CheckValueReturn(); } + ResetVisited(); + mEntryBlock->CheckNullptrDereference(); + if (mSaveTempsLinkerObject && mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP) mSaveTempsLinkerObject->AddSpace(mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP)); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index f12f0e3..34ed462 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -605,6 +605,7 @@ public: void WarnUsedUndefinedVariables(void); void CheckValueReturn(void); + void CheckNullptrDereference(void); void CollectGlobalReferences(NumberSet& referencedGlobals, NumberSet& modifiedGlobals, bool & storesIndirect, bool & loadsIndirect, bool & globalsChecked); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 9cbc742..f0a1165 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -40,7 +40,7 @@ static inline InterType InterTypeOf(const Declaration* dec) } } -InterCodeGenerator::ExValue InterCodeGenerator::ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v) +InterCodeGenerator::ExValue InterCodeGenerator::ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v) { if (v.mType && v.mType->IsReference()) { @@ -51,11 +51,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::ToValue(InterCodeProcedure* proc return v; } -InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level) +InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v, int level) { while (v.mReference > level) { - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_LOAD); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_LOAD); ins->mSrc[0].mMemory = IM_INDIRECT; ins->mSrc[0].mType = IT_POINTER; ins->mSrc[0].mTemp = v.mTemp; @@ -92,7 +92,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* ins->mSrc[0].mOperandSize = InterTypeSize[ins->mDst.mType]; int nbits = ins->mSrc[0].mOperandSize * 8; - InterInstruction* clsins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* clsins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); clsins->mDst.mType = IT_INT8; clsins->mDst.mTemp = proc->AddTemporary(clsins->mDst.mType); clsins->mConst.mType = IT_INT8; @@ -100,7 +100,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* clsins->mNumOperands = 0; block->Append(clsins); - InterInstruction* crsins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* crsins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); crsins->mDst.mType = IT_INT8; crsins->mDst.mTemp = proc->AddTemporary(crsins->mDst.mType); crsins->mConst.mType = IT_INT8; @@ -108,7 +108,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* crsins->mNumOperands = 0; block->Append(crsins); - InterInstruction* slins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction* slins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); slins->mOperator = IA_SHL; slins->mDst.mType = ins->mDst.mType; slins->mDst.mTemp = proc->AddTemporary(slins->mDst.mType); @@ -117,7 +117,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* slins->mNumOperands = 2; block->Append(slins); - InterInstruction* srins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction* srins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); srins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_SAR : IA_SHR; srins->mDst.mType = ins->mDst.mType; srins->mDst.mTemp = proc->AddTemporary(slins->mDst.mType); @@ -128,7 +128,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* if (InterTypeSize[ins->mDst.mType] < v.mType->mSize) { - InterInstruction* crins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction* crins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); crins->mDst.mType = InterTypeOf(v.mType); crins->mDst.mTemp = proc->AddTemporary(crins->mDst.mType); crins->mSrc[0] = srins->mDst; @@ -152,7 +152,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* return v; } -void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr) +void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue vl, ExValue vr) { // Bitfield assignment if (vl.mBits) @@ -168,7 +168,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I int nbits = InterTypeSize[itype] * 8; - InterInstruction* lins = new InterInstruction(exp->mLocation, IC_LOAD); + InterInstruction* lins = new InterInstruction(MapLocation(exp, inlineMapper), IC_LOAD); lins->mDst.mType = itype; lins->mDst.mTemp = proc->AddTemporary(lins->mDst.mType); lins->mSrc[0].mMemory = IM_INDIRECT; @@ -179,7 +179,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I lins->mNumOperands = 1; block->Append(lins); - InterInstruction* csins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* csins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); csins->mDst.mType = IT_INT8; csins->mDst.mTemp = proc->AddTemporary(csins->mDst.mType); csins->mConst.mType = IT_INT8; @@ -187,7 +187,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I csins->mNumOperands = 0; block->Append(csins); - InterInstruction* cmsins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* cmsins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); cmsins->mDst.mType = itype; cmsins->mDst.mTemp = proc->AddTemporary(cmsins->mDst.mType); cmsins->mConst.mType = itype; @@ -195,7 +195,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I cmsins->mNumOperands = 0; block->Append(cmsins); - InterInstruction* cmlins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* cmlins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); cmlins->mDst.mType = itype; cmlins->mDst.mTemp = proc->AddTemporary(cmlins->mDst.mType); cmlins->mConst.mType = itype; @@ -207,7 +207,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I if (InterTypeSize[itype] > vr.mType->mSize) { - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); if (InterTypeSize[itype] == 2) cins->mOperator = IA_EXT8TO16U; @@ -225,7 +225,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I rtemp = cins->mDst.mTemp; } - InterInstruction* sins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction* sins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); sins->mOperator = IA_SHL; sins->mDst.mType = itype; sins->mDst.mTemp = proc->AddTemporary(sins->mDst.mType); @@ -235,7 +235,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I sins->mNumOperands = 2; block->Append(sins); - InterInstruction* msins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction* msins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); msins->mOperator = IA_AND; msins->mDst.mType = itype; msins->mDst.mTemp = proc->AddTemporary(msins->mDst.mType); @@ -244,7 +244,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I msins->mNumOperands = 2; block->Append(msins); - InterInstruction* mlins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction* mlins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); mlins->mOperator = IA_AND; mlins->mDst.mType = itype; mlins->mDst.mTemp = proc->AddTemporary(mlins->mDst.mType); @@ -253,7 +253,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I mlins->mNumOperands = 2; block->Append(mlins); - InterInstruction* oins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction* oins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); oins->mOperator = IA_OR; oins->mDst.mType = itype; oins->mDst.mTemp = proc->AddTemporary(oins->mDst.mType); @@ -262,7 +262,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I oins->mNumOperands = 2; block->Append(oins); - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); ins->mSrc[1].mMemory = IM_INDIRECT; ins->mSrc[0] = oins->mDst; ins->mSrc[1].mType = IT_POINTER; @@ -274,7 +274,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I } else { - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); ins->mSrc[1].mMemory = IM_INDIRECT; ins->mSrc[0].mType = InterTypeOf(vr.mType); @@ -289,7 +289,7 @@ void InterCodeGenerator::StoreValue(InterCodeProcedure* proc, Expression* exp, I } } -InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration* type, bool checkTrunc) +InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v, Declaration* type, bool checkTrunc) { int stemp = v.mTemp; @@ -315,7 +315,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p { v.mReference++; v.mType = v.mType->mBase; - v = Dereference(proc, exp, block, v); + v = Dereference(proc, exp, block, inlineMapper, v); } if (v.mType->IsIntegerType() && type->mType == DT_TYPE_FLOAT) @@ -324,7 +324,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p { if (v.mType->mFlags & DTF_SIGNED) { - InterInstruction * xins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction * xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); xins->mOperator = IA_EXT8TO16S; xins->mSrc[0].mType = IT_INT8; xins->mSrc[0].mTemp = stemp; @@ -335,7 +335,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p } else { - InterInstruction * xins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction * xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); xins->mOperator = IA_EXT8TO16U; xins->mSrc[0].mType = IT_INT8; xins->mSrc[0].mTemp = stemp; @@ -346,7 +346,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p } } - InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); cins->mOperator = (v.mType->mFlags & DTF_SIGNED) ? IA_INT2FLOAT : IA_UINT2FLOAT; cins->mSrc[0].mType = IT_INT16; cins->mSrc[0].mTemp = stemp; @@ -361,7 +361,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p { mErrors->Error(exp->mLocation, EWARN_FLOAT_TO_INT, "Float to int conversion, potential loss of precision"); - InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); cins->mOperator = IA_FLOAT2INT; cins->mSrc[0].mType = IT_FLOAT; cins->mSrc[0].mTemp = v.mTemp; @@ -382,7 +382,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p } else if( type->mType == DT_TYPE_BOOL && v.mType->mType == DT_TYPE_POINTER) { - InterInstruction* zins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* zins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); zins->mDst.mType = IT_POINTER; zins->mDst.mTemp = proc->AddTemporary(IT_POINTER); zins->mConst.mType = IT_POINTER; @@ -390,7 +390,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p zins->mConst.mIntConst = 0; block->Append(zins); - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR); cins->mOperator = IA_CMPNE; cins->mSrc[0].mType = IT_POINTER; cins->mSrc[0].mTemp = v.mTemp; @@ -408,7 +408,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p { if (v.mType->mFlags & DTF_SIGNED) { - InterInstruction * xins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction * xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); xins->mOperator = IA_EXT8TO16S; xins->mSrc[0].mType = IT_INT8; xins->mSrc[0].mTemp = stemp; @@ -419,7 +419,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p } else { - InterInstruction * xins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction * xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); xins->mOperator = IA_EXT8TO16U; xins->mSrc[0].mType = IT_INT8; xins->mSrc[0].mTemp = stemp; @@ -433,7 +433,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p { if (v.mType->mFlags & DTF_SIGNED) { - InterInstruction* xins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction* xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); xins->mOperator = IA_EXT16TO32S; xins->mSrc[0].mType = IT_INT16; xins->mSrc[0].mTemp = stemp; @@ -444,7 +444,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p } else { - InterInstruction* xins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction* xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); xins->mOperator = IA_EXT16TO32U; xins->mSrc[0].mType = IT_INT16; xins->mSrc[0].mTemp = stemp; @@ -458,7 +458,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p { if (v.mType->mFlags & DTF_SIGNED) { - InterInstruction* xins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction* xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); xins->mOperator = IA_EXT8TO32S; xins->mSrc[0].mType = IT_INT8; xins->mSrc[0].mTemp = stemp; @@ -469,7 +469,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p } else { - InterInstruction* xins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction* xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); xins->mOperator = IA_EXT8TO32U; xins->mSrc[0].mType = IT_INT8; xins->mSrc[0].mTemp = stemp; @@ -1051,7 +1051,7 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex assert(offset == osize); } -void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock) +void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, InlineMapper * inlineMapper, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock) { if (right - left < 3) { @@ -1059,7 +1059,7 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e { if (vleft == vright) { - InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); block->Append(jins); block->Close(nodes[i].mBlock, nullptr); return; @@ -1068,14 +1068,14 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e { InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc); - InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); vins->mConst.mType = IT_INT16; vins->mConst.mIntConst = nodes[i].mValue; vins->mDst.mType = IT_INT16; vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType); block->Append(vins); - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR); cins->mOperator = IA_CMPEQ; cins->mSrc[0].mType = vins->mDst.mType; cins->mSrc[0].mTemp = vins->mDst.mTemp; @@ -1086,7 +1086,7 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e block->Append(cins); - InterInstruction* bins = new InterInstruction(exp->mLocation, IC_BRANCH); + InterInstruction* bins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BRANCH); bins->mSrc[0].mType = IT_BOOL; bins->mSrc[0].mTemp = cins->mDst.mTemp; block->Append(bins); @@ -1100,7 +1100,7 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e } } - InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); block->Append(jins); block->Close(dblock, nullptr); @@ -1114,14 +1114,14 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e InterCodeBasicBlock* rblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* lblock = new InterCodeBasicBlock(proc); - InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); vins->mConst.mType = IT_INT16; vins->mConst.mIntConst = vcenter; vins->mDst.mType = IT_INT16; vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType); block->Append(vins); - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR); cins->mOperator = IA_CMPEQ; cins->mSrc[0].mType = vins->mDst.mType; cins->mSrc[0].mTemp = vins->mDst.mTemp; @@ -1132,14 +1132,14 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e block->Append(cins); - InterInstruction* bins = new InterInstruction(exp->mLocation, IC_BRANCH); + InterInstruction* bins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BRANCH); bins->mSrc[0].mType = IT_BOOL; bins->mSrc[0].mTemp = cins->mDst.mTemp; block->Append(bins); block->Close(nodes[center].mBlock, cblock); - InterInstruction* rins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); + InterInstruction* rins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR); rins->mOperator = IA_CMPLS; rins->mSrc[0].mType = vins->mDst.mType; rins->mSrc[0].mTemp = vins->mDst.mTemp; @@ -1150,15 +1150,15 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e cblock->Append(rins); - InterInstruction* rbins = new InterInstruction(exp->mLocation, IC_BRANCH); + InterInstruction* rbins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BRANCH); rbins->mSrc[0].mType = IT_BOOL; rbins->mSrc[0].mTemp = rins->mDst.mTemp; cblock->Append(rbins); cblock->Close(lblock, rblock); - BuildSwitchTree(proc, exp, lblock, v, nodes, left, center, vleft, vcenter -1, dblock); - BuildSwitchTree(proc, exp, rblock, v, nodes, center + 1, right, vcenter + 1, vright, dblock); + BuildSwitchTree(proc, exp, lblock, inlineMapper, v, nodes, left, center, vleft, vcenter -1, dblock); + BuildSwitchTree(proc, exp, rblock, inlineMapper, v, nodes, center + 1, right, vcenter + 1, vright, dblock); } } @@ -1179,6 +1179,14 @@ void InterCodeGenerator::UnwindDestructStack(Declaration* procType, InterCodePro mErrors->Error(proc->mLocation, EWARN_DESTRUCTOR_MISMATCH, "Destructor sequence mismatch"); } +Location InterCodeGenerator::MapLocation(Expression* exp, InlineMapper* inlineMapper) +{ + if (inlineMapper) + return Location(exp->mLocation, inlineMapper->mLocation); + else + return exp->mLocation; +} + InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp) { DestructStack* destack = nullptr; @@ -1195,6 +1203,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro nmapper.mReturn = new InterCodeBasicBlock(proc); nmapper.mVarIndex = proc->mNumLocals; nmapper.mConstExpr = inlineConstexpr; + nmapper.mLocation = new Location(MapLocation(exp, inlineMapper)); proc->mNumLocals += fdec->mNumVars; if (inlineMapper) nmapper.mDepth = inlineMapper->mDepth + 1; @@ -1206,7 +1215,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro int nindex = proc->mNumLocals++; Declaration* vdec = new Declaration(pex->mLocation, DT_VARIABLE); - InterInstruction* ains = new InterInstruction(pex->mLocation, IC_CONSTANT); + InterInstruction* ains = new InterInstruction(MapLocation(pex, inlineMapper), IC_CONSTANT); ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); ains->mConst.mType = IT_POINTER; @@ -1260,27 +1269,27 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro if (pdec && !pdec->mBase->CanAssign(vr.mType)) mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types", pdec->mBase->MangleIdent(), vr.mType->MangleIdent()); - vr = Dereference(proc, texp, block, vr, 1); + vr = Dereference(proc, texp, block, inlineMapper, vr, 1); if (vr.mReference != 1) mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); if (vp.mTemp != vr.mTemp) - CopyStructSimple(proc, exp, block, vp, vr); + CopyStructSimple(proc, exp, block, inlineMapper, vp, vr); } else { if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION) - vr = Dereference(proc, texp, block, vr, 1); + vr = Dereference(proc, texp, block, inlineMapper, vr, 1); else if (pdec && (pdec->mBase->IsReference() && !vr.mType->IsReference())) - vr = Dereference(proc, texp, block, vr, 1); + vr = Dereference(proc, texp, block, inlineMapper, vr, 1); else if (vr.mType->IsReference() && !(pdec && pdec->mBase->IsReference())) { vr.mReference++; - vr = Dereference(proc, texp, block, vr); + vr = Dereference(proc, texp, block, inlineMapper, vr); } else - vr = Dereference(proc, texp, block, vr); + vr = Dereference(proc, texp, block, inlineMapper, vr); if (pdec) { @@ -1289,14 +1298,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro pdec->mBase->CanAssign(vr.mType); mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types", pdec->mBase->MangleIdent(), vr.mType->MangleIdent()); } - vr = CoerceType(proc, texp, block, vr, pdec->mBase); + vr = CoerceType(proc, texp, block, inlineMapper, vr, pdec->mBase); } else if (vr.mType->IsIntegerType() && vr.mType->mSize < 2) { - vr = CoerceType(proc, texp, block, vr, TheSignedIntTypeDeclaration); + vr = CoerceType(proc, texp, block, inlineMapper, vr, TheSignedIntTypeDeclaration); } - InterInstruction* wins = new InterInstruction(texp->mLocation, IC_STORE); + InterInstruction* wins = new InterInstruction(MapLocation(texp, inlineMapper), IC_STORE); wins->mSrc[1].mMemory = IM_INDIRECT; wins->mSrc[0].mType = vr.mReference > 0 ? IT_POINTER : InterTypeOf(vr.mType); wins->mSrc[0].mTemp = vr.mTemp; @@ -1349,7 +1358,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro vl = TranslateExpression(ftype, proc, block, fexp, idestack, BranchTarget(), BranchTarget(), &nmapper); - InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); block->Append(jins); block->Close(nmapper.mReturn, nullptr); @@ -1363,7 +1372,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro if (rdec) { - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ins->mConst.mType = IT_POINTER; @@ -1376,7 +1385,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro ExValue rv(rdec->mBase, ins->mDst.mTemp, 1); if (!rdec->mBase->IsReference() && rdec->mBase->mType != DT_TYPE_STRUCT) - rv = Dereference(proc, exp, block, rv); + rv = Dereference(proc, exp, block, inlineMapper, rv); return rv; } else if (lrexp) @@ -1387,7 +1396,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro return ExValue(TheVoidTypeDeclaration); } -void InterCodeGenerator::CopyStructSimple(InterCodeProcedure* proc, Expression * exp, InterCodeBasicBlock* block, ExValue vl, ExValue vr) +void InterCodeGenerator::CopyStructSimple(InterCodeProcedure* proc, Expression * exp, InterCodeBasicBlock* block, InlineMapper * inlineMapper, ExValue vl, ExValue vr) { int ne = 0; Declaration* mdec = nullptr; @@ -1408,7 +1417,7 @@ void InterCodeGenerator::CopyStructSimple(InterCodeProcedure* proc, Expression * // Single element structs are copied as individual value if (ne == 1 && mdec->mSize == vl.mType->mSize) { - InterInstruction* lins = new InterInstruction(exp->mLocation, IC_LOAD); + InterInstruction* lins = new InterInstruction(MapLocation(exp, inlineMapper), IC_LOAD); lins->mNumOperands = 1; lins->mSrc[0].mType = IT_POINTER; @@ -1421,7 +1430,7 @@ void InterCodeGenerator::CopyStructSimple(InterCodeProcedure* proc, Expression * lins->mDst.mTemp = proc->AddTemporary(lins->mDst.mType); block->Append(lins); - InterInstruction* sins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* sins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); sins->mNumOperands = 2; sins->mSrc[1].mType = IT_POINTER; @@ -1435,7 +1444,7 @@ void InterCodeGenerator::CopyStructSimple(InterCodeProcedure* proc, Expression * } else { - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_COPY); cins->mNumOperands = 2; cins->mSrc[0].mType = IT_POINTER; @@ -1503,7 +1512,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I int nindex = proc->mNumLocals++; Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); - InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); ains->mConst.mType = IT_POINTER; @@ -1521,7 +1530,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I vdec->mQualIdent = pdec->mQualIdent; block->Append(ains); - InterInstruction* wins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* wins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); wins->mNumOperands = 2; wins->mSrc[1].mMemory = IM_INDIRECT; wins->mSrc[0].mType = vl.mReference > 0 ? IT_POINTER : InterTypeOf(vl.mType); @@ -1537,7 +1546,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I nindex = proc->mNumLocals++; vdec = new Declaration(exp->mLocation, DT_VARIABLE); - ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ains->mNumOperands = 0; ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); @@ -1556,7 +1565,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I vdec->mQualIdent = pdec->mQualIdent; block->Append(ains); - wins = new InterInstruction(exp->mLocation, IC_STORE); + wins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); wins->mNumOperands = 2; wins->mSrc[1].mMemory = IM_INDIRECT; wins->mSrc[0].mType = vr.mReference > 0 ? IT_POINTER : InterTypeOf(vr.mType);; @@ -1569,7 +1578,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I TranslateExpression(ftype, proc, block, fexp, destack, BranchTarget(), BranchTarget(), &nmapper); - InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); block->Append(jins); block->Close(nmapper.mReturn, nullptr); @@ -1577,7 +1586,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I } else if (ccdec->mBase->mFlags & DTF_FASTCALL) { - InterInstruction* psins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* psins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); psins->mDst.mType = IT_POINTER; psins->mDst.mTemp = proc->AddTemporary(IT_POINTER); psins->mDst.mOperandSize = 2; @@ -1594,7 +1603,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I psins->mConst.mMemory = IM_FRAME; block->Append(psins); - InterInstruction* ssins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* ssins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); ssins->mSrc[0].mType = IT_POINTER; ssins->mSrc[0].mTemp = vl.mTemp; ssins->mSrc[0].mMemory = IM_INDIRECT; @@ -1602,7 +1611,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I ssins->mSrc[1] = psins->mDst; block->Append(ssins); - InterInstruction* plins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* plins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); plins->mDst.mType = IT_POINTER; plins->mDst.mTemp = proc->AddTemporary(IT_POINTER); plins->mDst.mOperandSize = 2; @@ -1619,7 +1628,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I plins->mConst.mMemory = IM_FRAME; block->Append(plins); - InterInstruction* slins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* slins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); slins->mSrc[0].mType = IT_POINTER; slins->mSrc[0].mTemp = vr.mTemp; slins->mSrc[0].mMemory = IM_INDIRECT; @@ -1629,7 +1638,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I proc->AddCalledFunction(proc->mModule->mProcedures[ccdec->mVarIndex]); - InterInstruction* pcins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* pcins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); pcins->mDst.mType = IT_POINTER; pcins->mDst.mTemp = proc->AddTemporary(IT_POINTER); pcins->mConst.mType = IT_POINTER; @@ -1640,7 +1649,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I pcins->mConst.mLinkerObject = ccdec->mLinkerObject; block->Append(pcins); - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CALL); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CALL); if (ccdec->mFlags & DTF_NATIVE) cins->mCode = IC_CALL_NATIVE; else @@ -1652,7 +1661,7 @@ void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, I } } else - CopyStructSimple(proc, exp, block, vl, vr); + CopyStructSimple(proc, exp, block, inlineMapper, vl, vr); } InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, ExValue* lrexp) @@ -1706,7 +1715,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (lrexp) return *lrexp; - InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); if (inlineMapper) { @@ -1729,7 +1738,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - InterInstruction* pins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* pins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); pins->mDst.mType = IT_POINTER; pins->mDst.mTemp = proc->AddTemporary(IT_POINTER); pins->mConst.mType = IT_POINTER; @@ -1770,7 +1779,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { case DT_CONST_INTEGER: { - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ins->mDst.mType = InterTypeOf(dec->mBase); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ins->mConst.mType = ins->mDst.mType; @@ -1831,7 +1840,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case DT_CONST_FLOAT: { - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ins->mDst.mType = InterTypeOf(dec->mBase); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ins->mConst.mType = ins->mDst.mType; @@ -1843,7 +1852,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case DT_CONST_ADDRESS: { - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(IT_POINTER); ins->mConst.mType = IT_POINTER; @@ -1861,7 +1870,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterCodeProcedure* cproc = this->TranslateProcedure(proc->mModule, dec->mValue, dec); } - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ins->mDst.mType = InterTypeOf(dec->mBase); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ins->mConst.mType = ins->mDst.mType; @@ -1879,7 +1888,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!dec->mLinkerObject) TranslateAssembler(proc->mModule, dec->mValue, nullptr); - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ins->mConst.mType = IT_POINTER; @@ -1924,7 +1933,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* proc->mModule->mGlobalVars.Push(var); } - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(IT_POINTER); ins->mConst.mType = IT_POINTER; @@ -1958,7 +1967,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* BuildInitializer(proc->mModule, d, 0, dec, var); } - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(IT_POINTER); ins->mConst.mType = IT_POINTER; @@ -1981,7 +1990,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { dec = exp->mDecValue; - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ins->mConst.mType = IT_POINTER; @@ -2082,8 +2091,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (exp->mType == EX_ASSIGNMENT) { - vl = ToValue(proc, exp, block, vl); - vr = ToValue(proc, exp, block, vr); + vl = ToValue(proc, exp, block, inlineMapper, vl); + vr = ToValue(proc, exp, block, inlineMapper, vr); } if (exp->mToken == TK_ASSIGN || !(vl.mType->mType == DT_TYPE_POINTER && vr.mType->IsIntegerType() && (exp->mToken == TK_ASSIGN_ADD || exp->mToken == TK_ASSIGN_SUB))) @@ -2107,22 +2116,22 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mType->IsReference()) { if (vr.mType->IsReference()) - vr = Dereference(proc, exp, block, vr, 0); + vr = Dereference(proc, exp, block, inlineMapper, vr, 0); else { - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); if (vr.mReference != 1) mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); } - vl = Dereference(proc, exp, block, vl, 2); + vl = Dereference(proc, exp, block, inlineMapper, vl, 2); if (vl.mReference != 2) mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not a left hand reference expression"); if (vr.mTemp != vl.mTemp) { - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); ins->mSrc[0].mType = IT_POINTER; ins->mSrc[0].mTemp = vr.mTemp; ins->mSrc[0].mMemory = IM_INDIRECT; @@ -2141,10 +2150,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else if (vl.mType->mType == DT_TYPE_STRUCT || vl.mType->mType == DT_TYPE_ARRAY || vl.mType->mType == DT_TYPE_UNION) { - vr = ToValue(proc, exp, block, vr); + vr = ToValue(proc, exp, block, inlineMapper, vr); - vr = Dereference(proc, exp, block, vr, 1); - vl = Dereference(proc, exp, block, vl, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); if (vl.mReference != 1) mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not a left hand expression"); @@ -2152,33 +2161,33 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); if (vr.mTemp != vl.mTemp) - CopyStructSimple(proc, exp, block, vl, vr); + CopyStructSimple(proc, exp, block, inlineMapper, vl, vr); } else { - vr = ToValue(proc, exp, block, vr); + vr = ToValue(proc, exp, block, inlineMapper, vr); if (vl.mType->mType == DT_TYPE_POINTER && (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION)) { - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); vr.mReference = 0; vr.mType = vl.mType; } else - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); - vl = Dereference(proc, exp, block, vl, 1); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); if (vl.mReference != 1) mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not a left hand expression"); if (exp->mToken != TK_ASSIGN) { - ExValue vll = Dereference(proc, exp, block, vl); + ExValue vll = Dereference(proc, exp, block, inlineMapper, vl); if (vl.mType->mType == DT_TYPE_POINTER) { - InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); cins->mConst.mType = IT_INT16; if (exp->mToken == TK_ASSIGN_ADD) @@ -2199,9 +2208,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); block->Append(cins); - vr = CoerceType(proc, exp, block, vr, TheSignedIntTypeDeclaration); + vr = CoerceType(proc, exp, block, inlineMapper, vr, TheSignedIntTypeDeclaration); - InterInstruction * mins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction * mins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); mins->mOperator = IA_MUL; mins->mSrc[0].mType = IT_INT16; mins->mSrc[0].mTemp = vr.mTemp; @@ -2211,7 +2220,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mins->mDst.mTemp = proc->AddTemporary(mins->mDst.mType); block->Append(mins); - InterInstruction * ains = new InterInstruction(exp->mLocation, IC_LEA); + InterInstruction * ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_LEA); ains->mSrc[1].mMemory = IM_INDIRECT; ains->mSrc[0].mType = IT_INT16; ains->mSrc[0].mTemp = mins->mDst.mTemp; @@ -2237,12 +2246,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* otype = TheSignedIntTypeDeclaration; else otype = TheUnsignedIntTypeDeclaration; - vll = CoerceType(proc, exp, block, vll, otype); + vll = CoerceType(proc, exp, block, inlineMapper, vll, otype); } - vr = CoerceType(proc, exp, block, vr, otype, exp->mToken != TK_ASSIGN_AND); + vr = CoerceType(proc, exp, block, inlineMapper, vr, otype, exp->mToken != TK_ASSIGN_AND); - InterInstruction * oins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction * oins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); oins->mSrc[0].mType = InterTypeOf(otype); oins->mSrc[0].mTemp = vr.mTemp; oins->mSrc[1].mType = InterTypeOf(otype); @@ -2303,15 +2312,15 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block->Append(oins); - vr = CoerceType(proc, exp, block, vr, vl.mType); + vr = CoerceType(proc, exp, block, inlineMapper, vr, vl.mType); } } else { - vr = CoerceType(proc, exp, block, vr, vl.mType); + vr = CoerceType(proc, exp, block, inlineMapper, vr, vl.mType); } - StoreValue(proc, exp, block, vl, vr); + StoreValue(proc, exp, block, inlineMapper, vl, vr); } } @@ -2322,8 +2331,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); - vl = ToValue(proc, exp, block, vl); - vr = ToValue(proc, exp, block, vr); + vl = ToValue(proc, exp, block, inlineMapper, vl); + vr = ToValue(proc, exp, block, inlineMapper, vr); int stride = vl.mType->Stride(); @@ -2337,8 +2346,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } } - vl = Dereference(proc, exp, block, vl, vl.mType->mType == DT_TYPE_POINTER ? 0 : 1); - vr = Dereference(proc, exp, block, vr); + vl = Dereference(proc, exp, block, inlineMapper, vl, vl.mType->mType == DT_TYPE_POINTER ? 0 : 1); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (vl.mType->mType != DT_TYPE_ARRAY && vl.mType->mType != DT_TYPE_POINTER) { @@ -2349,16 +2358,16 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!vr.mType->IsIntegerType()) mErrors->Error(exp->mLocation, EERR_INVALID_INDEX, "Index operand is not integral number"); - vr = CoerceType(proc, exp, block, vr, TheSignedIntTypeDeclaration); + vr = CoerceType(proc, exp, block, inlineMapper, vr, TheSignedIntTypeDeclaration); - InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); cins->mConst.mType = IT_INT16; cins->mConst.mIntConst = stride; cins->mDst.mType = IT_INT16; cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); block->Append(cins); - InterInstruction * mins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction * mins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); mins->mOperator = IA_MUL; mins->mSrc[0].mType = IT_INT16; mins->mSrc[0].mTemp = vr.mTemp; @@ -2368,7 +2377,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mins->mDst.mTemp = proc->AddTemporary(mins->mDst.mType); block->Append(mins); - InterInstruction * ains = new InterInstruction(exp->mLocation, IC_LEA); + InterInstruction * ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_LEA); ains->mSrc[1].mMemory = IM_INDIRECT; ains->mSrc[0].mType = IT_INT16; ains->mSrc[0].mTemp = mins->mDst.mTemp; @@ -2385,21 +2394,21 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - vl = ToValue(proc, exp, block, vl); + vl = ToValue(proc, exp, block, inlineMapper, vl); - vl = Dereference(proc, exp, block, vl, 1); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); if (vl.mReference != 1) mErrors->Error(exp->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); - InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); cins->mConst.mType = IT_INT16; cins->mConst.mIntConst = exp->mDecValue->mOffset; cins->mDst.mType = IT_INT16; cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); block->Append(cins); - InterInstruction * ains = new InterInstruction(exp->mLocation, IC_LEA); + InterInstruction * ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_LEA); ains->mSrc[1].mMemory = IM_INDIRECT; ains->mSrc[0].mType = IT_INT16; ains->mSrc[0].mTemp = cins->mDst.mTemp; @@ -2420,20 +2429,20 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); - vl = ToValue(proc, exp, block, vl); - vr = ToValue(proc, exp, block, vr); + vl = ToValue(proc, exp, block, inlineMapper, vl); + vr = ToValue(proc, exp, block, inlineMapper, vr); - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); if (vl.mType->mType == DT_TYPE_POINTER || vl.mType->mType == DT_TYPE_ARRAY) { if (vl.mType->mType == DT_TYPE_POINTER) - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); else { - vl = Dereference(proc, exp, block, vl, 1); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); Declaration* ptype = new Declaration(exp->mLocation, DT_TYPE_POINTER); ptype->mBase = vl.mType->mBase; @@ -2444,7 +2453,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vr.mType->IsIntegerType()) { - InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); cins->mConst.mType = IT_INT16; if (exp->mToken == TK_ADD) @@ -2462,9 +2471,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); block->Append(cins); - vr = CoerceType(proc, exp, block, vr, TheSignedIntTypeDeclaration); + vr = CoerceType(proc, exp, block, inlineMapper, vr, TheSignedIntTypeDeclaration); - InterInstruction * mins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction * mins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); mins->mCode = IC_BINARY_OPERATOR; mins->mOperator = IA_MUL; mins->mSrc[0].mType = IT_INT16; @@ -2489,7 +2498,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { if (exp->mToken == TK_SUB) { - InterInstruction * clins = new InterInstruction(exp->mLocation, IC_TYPECAST), * crins = new InterInstruction(exp->mLocation, IC_TYPECAST); + InterInstruction * clins = new InterInstruction(MapLocation(exp, inlineMapper), IC_TYPECAST), * crins = new InterInstruction(MapLocation(exp, inlineMapper), IC_TYPECAST); clins->mSrc[0].mTemp = vl.mTemp; clins->mSrc[0].mType = IT_POINTER; clins->mDst.mType = IT_INT16; @@ -2515,14 +2524,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* s = n; } - InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); cins->mConst.mType = IT_INT16; cins->mConst.mIntConst = s; cins->mDst.mType = IT_INT16; cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); block->Append(cins); - InterInstruction * sins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR), * dins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction * sins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR), * dins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); sins->mOperator = IA_SUB; sins->mSrc[0].mType = IT_INT16; sins->mSrc[0].mTemp = crins->mDst.mTemp; @@ -2552,10 +2561,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (vr.mType->mType == DT_TYPE_POINTER || vr.mType->mType == DT_TYPE_ARRAY) { if (vr.mType->mType == DT_TYPE_POINTER) - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); else { - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); Declaration* ptype = new Declaration(exp->mLocation, DT_TYPE_POINTER); ptype->mBase = vr.mType->mBase; @@ -2565,7 +2574,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mType->IsIntegerType()) { - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); cins->mConst.mType = IT_INT16; if (exp->mToken == TK_ADD) @@ -2579,9 +2588,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); block->Append(cins); - vl = CoerceType(proc, exp, block, vl, TheSignedIntTypeDeclaration); + vl = CoerceType(proc, exp, block, inlineMapper, vl, TheSignedIntTypeDeclaration); - InterInstruction* mins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); + InterInstruction* mins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR); mins->mOperator = IA_MUL; mins->mSrc[0].mType = IT_INT16; mins->mSrc[0].mTemp = vl.mTemp; @@ -2608,7 +2617,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); if (!vl.mType->IsNumericType()) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Left hand operand type is not numeric"); @@ -2679,8 +2688,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* dtype = TheUnsignedCharTypeDeclaration; } - vl = CoerceType(proc, exp, block, vl, dtype); - vr = CoerceType(proc, exp, block, vr, dtype); + vl = CoerceType(proc, exp, block, inlineMapper, vl, dtype); + vr = CoerceType(proc, exp, block, inlineMapper, vr, dtype); bool signedOP = dtype->mFlags & DTF_SIGNED; @@ -2735,8 +2744,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_PREINCDEC: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - vl = ToValue(proc, exp, block, vl); - vl = Dereference(proc, exp, block, vl, 1); + vl = ToValue(proc, exp, block, inlineMapper, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); if (vl.mReference != 1) mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not a left hand expression"); @@ -2744,9 +2753,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mType->mFlags & DTF_CONST) mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot change const value"); - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONSTANT), * ains = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);// , * sins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT), * ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR);// , * sins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); - ExValue vdl = Dereference(proc, exp, block, vl); + ExValue vdl = Dereference(proc, exp, block, inlineMapper, vl); bool ftype = vl.mType->mType == DT_TYPE_FLOAT; @@ -2785,7 +2794,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); block->Append(ains); - StoreValue(proc, exp, block, vl, ExValue(vl.mType, ains->mDst.mTemp)); + StoreValue(proc, exp, block, inlineMapper, vl, ExValue(vl.mType, ains->mDst.mTemp)); #if 0 sins->mSrc[1].mMemory = IM_INDIRECT; sins->mSrc[0].mType = ains->mDst.mType; @@ -2805,8 +2814,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_POSTINCDEC: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - vl = ToValue(proc, exp, block, vl); - vl = Dereference(proc, exp, block, vl, 1); + vl = ToValue(proc, exp, block, inlineMapper, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); if (vl.mReference != 1) mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not a left hand expression"); @@ -2814,9 +2823,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vl.mType->mFlags & DTF_CONST) mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot change const value"); - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CONSTANT), * ains = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);// , * sins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT), * ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_BINARY_OPERATOR);// , * sins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); - ExValue vdl = Dereference(proc, exp, block, vl); + ExValue vdl = Dereference(proc, exp, block, inlineMapper, vl); bool ftype = vl.mType->mType == DT_TYPE_FLOAT; @@ -2854,7 +2863,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ains->mDst.mTemp = proc->AddTemporary(ttype); block->Append(ains); - StoreValue(proc, exp, block, vl, ExValue(vl.mType, ains->mDst.mTemp)); + StoreValue(proc, exp, block, inlineMapper, vl, ExValue(vl.mType, ains->mDst.mTemp)); #if 0 sins->mSrc[1].mMemory = IM_INDIRECT; sins->mSrc[0].mType = ains->mDst.mType; @@ -2872,39 +2881,39 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_PREFIX: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - vl = ToValue(proc, exp, block, vl); + vl = ToValue(proc, exp, block, inlineMapper, vl); - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_UNARY_OPERATOR); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_UNARY_OPERATOR); switch (exp->mToken) { case TK_ADD: - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); ins->mOperator = IA_NONE; break; case TK_SUB: - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); if (!vl.mType->IsNumericType()) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a numeric type"); else if (vl.mType->mType == DT_TYPE_INTEGER && vl.mType->mSize < 2) - vl = CoerceType(proc, exp, block, vl, TheSignedIntTypeDeclaration); + vl = CoerceType(proc, exp, block, inlineMapper, vl, TheSignedIntTypeDeclaration); ins->mOperator = IA_NEG; break; case TK_BINARY_NOT: - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); if (!(vl.mType->mType == DT_TYPE_POINTER || vl.mType->IsNumericType())) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a numeric or pointer type"); else if (vl.mType->mType == DT_TYPE_INTEGER && vl.mType->mSize < 2) - vl = CoerceType(proc, exp, block, vl, TheUnsignedIntTypeDeclaration); + vl = CoerceType(proc, exp, block, inlineMapper, vl, TheUnsignedIntTypeDeclaration); ins->mOperator = IA_NOT; break; case TK_MUL: if (vl.mType->mType == DT_TYPE_ARRAY) - vl = Dereference(proc, exp, block, vl, 1); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); else if (vl.mType->mType != DT_TYPE_POINTER) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a pointer type"); else if (vl.mType->mStride != 1) - vl = Dereference(proc, exp, block, vl, 0); + vl = Dereference(proc, exp, block, inlineMapper, vl, 0); else return ExValue(vl.mType->mBase, vl.mTemp, vl.mReference + 1); return ExValue(vl.mType->mBase, vl.mTemp, 1); @@ -2957,7 +2966,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case TK_DELETE: { - vl = Dereference(proc, exp, block, vl, 0); + vl = Dereference(proc, exp, block, inlineMapper, vl, 0); ins->mCode = IC_FREE; ins->mSrc[0].mType = IT_POINTER; @@ -2981,14 +2990,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_RELATIONAL: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - vl = ToValue(proc, exp, block, vl); - vl = Dereference(proc, exp, block, vl, vl.mType->mType == DT_TYPE_ARRAY ? 1 : 0); + vl = ToValue(proc, exp, block, inlineMapper, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl, vl.mType->mType == DT_TYPE_ARRAY ? 1 : 0); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); - vr = ToValue(proc, exp, block, vr); - vr = Dereference(proc, exp, block, vr, vr.mType->mType == DT_TYPE_ARRAY ? 1 : 0); + vr = ToValue(proc, exp, block, inlineMapper, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr, vr.mType->mType == DT_TYPE_ARRAY ? 1 : 0); - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR); Declaration* dtype = TheSignedIntTypeDeclaration; @@ -3050,8 +3059,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* dtype = TheUnsignedIntTypeDeclaration; } - vl = CoerceType(proc, exp, block, vl, dtype); - vr = CoerceType(proc, exp, block, vr, dtype); + vl = CoerceType(proc, exp, block, inlineMapper, vl, dtype); + vr = CoerceType(proc, exp, block, inlineMapper, vr, dtype); bool signedCompare = dtype->mFlags & DTF_SIGNED; @@ -3100,13 +3109,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!strcmp(iname->mString, "fabs")) { vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (decf->mBase->mParams->CanAssign(vr.mType)) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); - vr = CoerceType(proc, exp, block, vr, decf->mBase->mParams); + vr = CoerceType(proc, exp, block, inlineMapper, vr, decf->mBase->mParams); - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_UNARY_OPERATOR); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_UNARY_OPERATOR); ins->mOperator = IA_ABS; ins->mSrc[0].mType = IT_FLOAT; ins->mSrc[0].mTemp = vr.mTemp; @@ -3119,13 +3128,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (!strcmp(iname->mString, "floor")) { vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (decf->mBase->mParams->CanAssign(vr.mType)) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); - vr = CoerceType(proc, exp, block, vr, decf->mBase->mParams); + vr = CoerceType(proc, exp, block, inlineMapper, vr, decf->mBase->mParams); - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_UNARY_OPERATOR); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_UNARY_OPERATOR); ins->mOperator = IA_FLOOR; ins->mSrc[0].mType = IT_FLOAT; ins->mSrc[0].mTemp = vr.mTemp; @@ -3138,13 +3147,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (!strcmp(iname->mString, "ceil")) { vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (decf->mBase->mParams->CanAssign(vr.mType)) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); - vr = CoerceType(proc, exp, block, vr, decf->mBase->mParams); + vr = CoerceType(proc, exp, block, inlineMapper, vr, decf->mBase->mParams); - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_UNARY_OPERATOR); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_UNARY_OPERATOR); ins->mOperator = IA_CEIL; ins->mSrc[0].mType = IT_FLOAT; ins->mSrc[0].mTemp = vr.mTemp; @@ -3163,13 +3172,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (!strcmp(iname->mString, "malloc")) { vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (decf->mBase->mParams->CanAssign(vr.mType)) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); - vr = CoerceType(proc, exp, block, vr, decf->mBase->mParams); + vr = CoerceType(proc, exp, block, inlineMapper, vr, decf->mBase->mParams); - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_MALLOC); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_MALLOC); ins->mSrc[0].mType = IT_INT16; ins->mSrc[0].mTemp = vr.mTemp; ins->mNumOperands = 1; @@ -3183,13 +3192,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (!strcmp(iname->mString, "free")) { vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (decf->mBase->mParams->CanAssign(vr.mType)) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); - vr = CoerceType(proc, exp, block, vr, decf->mBase->mParams); + vr = CoerceType(proc, exp, block, inlineMapper, vr, decf->mBase->mParams); - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_FREE); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_FREE); ins->mSrc[0].mType = IT_POINTER; ins->mSrc[0].mTemp = vr.mTemp; ins->mNumOperands = 1; @@ -3207,22 +3216,22 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { vl = TranslateExpression(procType, proc, block, tex, destack, breakBlock, continueBlock, inlineMapper); if (vl.mType->mType == DT_TYPE_ARRAY) - vl = Dereference(proc, exp, block, vl, 1); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); else - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); vr = TranslateExpression(procType, proc, block, sex, destack, breakBlock, continueBlock, inlineMapper); if (vr.mType->mType == DT_TYPE_ARRAY) - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); else - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (!TheCharPointerTypeDeclaration->CanAssign(vl.mType)) mErrors->Error(tex->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); if (!TheConstCharPointerTypeDeclaration->CanAssign(vr.mType)) mErrors->Error(sex->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_STRCPY); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STRCPY); ins->mNumOperands = 2; ins->mSrc[0].mType = IT_POINTER; @@ -3246,22 +3255,22 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { vl = TranslateExpression(procType, proc, block, tex, destack, breakBlock, continueBlock, inlineMapper); if (vl.mType->mType == DT_TYPE_ARRAY) - vl = Dereference(proc, exp, block, vl, 1); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); else - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); vr = TranslateExpression(procType, proc, block, sex, destack, breakBlock, continueBlock, inlineMapper); if (vr.mType->mType == DT_TYPE_ARRAY) - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); else - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (!TheVoidPointerTypeDeclaration->CanAssign(vl.mType)) mErrors->Error(tex->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); if (!TheConstVoidPointerTypeDeclaration->CanAssign(vr.mType)) mErrors->Error(sex->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_COPY); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_COPY); ins->mNumOperands = 2; ins->mSrc[0].mType = IT_POINTER; @@ -3342,7 +3351,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vl = TranslateExpression(procType, proc, block, funcexp, destack, breakBlock, continueBlock, inlineMapper); - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); int atotal = 0; @@ -3360,7 +3369,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - fins = new InterInstruction(exp->mLocation, IC_PUSH_FRAME); + fins = new InterInstruction(MapLocation(exp, inlineMapper), IC_PUSH_FRAME); fins->mNumOperands = 0; fins->mConst.mIntConst = atotal; block->Append(fins); @@ -3390,7 +3399,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* decResult = vdec; - InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); vins->mDst.mType = IT_POINTER; vins->mDst.mTemp = proc->AddTemporary(IT_POINTER); vins->mConst.mType = IT_POINTER; @@ -3402,7 +3411,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ttemp = vins->mDst.mTemp; } - InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(IT_POINTER); ains->mConst.mType = IT_POINTER; @@ -3418,7 +3427,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ains->mConst.mMemory = IM_FRAME; block->Append(ains); - InterInstruction* wins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* wins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); wins->mSrc[1].mMemory = IM_INDIRECT; wins->mSrc[0].mType = IT_POINTER; wins->mSrc[0].mTemp = ttemp; @@ -3443,7 +3452,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* Expression* pex = exp->mRight; while (pex) { - InterInstruction * ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ains->mConst.mType = IT_POINTER; ains->mDst.mType = IT_POINTER; @@ -3508,7 +3517,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vdec->mBase = pdec->mBase->mBase; vdec->mSize = pdec->mBase->mBase->mSize; - InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); vins->mDst.mType = IT_POINTER; vins->mDst.mTemp = proc->AddTemporary(IT_POINTER); vins->mConst.mMemory = IM_LOCAL; @@ -3531,7 +3540,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (pdec && !pdec->mBase->CanAssign(vr.mType)) mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types", pdec->mBase->MangleIdent(), vr.mType->MangleIdent()); - vr = Dereference(proc, texp, block, vr, 1); + vr = Dereference(proc, texp, block, inlineMapper, vr, 1); if (vr.mReference != 1) mErrors->Error(exp->mLeft->mLocation, EERR_NOT_AN_LVALUE, "Not an addressable expression"); @@ -3562,22 +3571,22 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else { if (vr.mType->mType == DT_TYPE_ARRAY)// || vr.mType->mType == DT_TYPE_FUNCTION) - vr = Dereference(proc, texp, block, vr, 1); + vr = Dereference(proc, texp, block, inlineMapper, vr, 1); else if (pdec && pdec->mBase->mType == DT_TYPE_POINTER && vr.mType->mType == DT_TYPE_INTEGER && texp->mType == EX_CONSTANT && texp->mDecValue->mType == DT_CONST_INTEGER && texp->mDecValue->mInteger == 0) { mErrors->Error(texp->mLocation, EWARN_NUMERIC_0_USED_AS_NULLPTR, "Numeric 0 used for nullptr"); - vr = CoerceType(proc, texp, block, vr, pdec->mBase); + vr = CoerceType(proc, texp, block, inlineMapper, vr, pdec->mBase); } else if (pdec && (pdec->mBase->IsReference() && !vr.mType->IsReference())) - vr = Dereference(proc, texp, block, vr, 1); + vr = Dereference(proc, texp, block, inlineMapper, vr, 1); else if (vr.mType->IsReference() && !(pdec && pdec->mBase->IsReference())) { vr.mReference++; - vr = Dereference(proc, texp, block, vr); + vr = Dereference(proc, texp, block, inlineMapper, vr); vr.mType = vr.mType->mBase; } else - vr = Dereference(proc, texp, block, vr); + vr = Dereference(proc, texp, block, inlineMapper, vr); if (pdec) { @@ -3586,11 +3595,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* pdec->mBase->CanAssign(vr.mType); mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types", pdec->mBase->MangleIdent(), vr.mType->MangleIdent()); } - vr = CoerceType(proc, texp, block, vr, pdec->mBase); + vr = CoerceType(proc, texp, block, inlineMapper, vr, pdec->mBase); } else if (vr.mType->IsIntegerType() && vr.mType->mSize < 2) { - vr = CoerceType(proc, texp, block, vr, TheSignedIntTypeDeclaration); + vr = CoerceType(proc, texp, block, inlineMapper, vr, TheSignedIntTypeDeclaration); } @@ -3636,7 +3645,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* for (int i = 0; i < defins.Size(); i++) block->Append(defins[i]); - InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CALL); + InterInstruction * cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CALL); cins->mNumOperands = 1; if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_NATIVE) || (mCompilerOptions & COPT_NATIVE)) cins->mCode = IC_CALL_NATIVE; @@ -3668,7 +3677,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { fins->mConst.mIntConst = atotal; - InterInstruction* xins = new InterInstruction(exp->mLocation, IC_POP_FRAME); + InterInstruction* xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_POP_FRAME); xins->mNumOperands = 0; xins->mConst.mIntConst = atotal; block->Append(xins); @@ -3679,7 +3688,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (lrexp) return *lrexp; - InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); vins->mDst.mType = IT_POINTER; vins->mDst.mTemp = proc->AddTemporary(IT_POINTER); vins->mConst.mType = IT_POINTER; @@ -3709,7 +3718,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { dec->mLinkerObject->mFlags |= LOBJF_INLINE; - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ins->mConst.mType = IT_POINTER; @@ -3720,7 +3729,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ins->mConst.mVarIndex = dec->mVarIndex; block->Append(ins); - InterInstruction * jins = new InterInstruction(exp->mLocation, IC_ASSEMBLER); + InterInstruction * jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_ASSEMBLER); jins->mDst.mTemp = proc->AddTemporary(IT_INT32); jins->mDst.mType = IT_INT32; @@ -3730,7 +3739,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* for (int i = 0; i < refvars.Size(); i++) { - InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* vins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); vins->mConst.mType = IT_POINTER; vins->mDst.mType = IT_POINTER; @@ -3771,7 +3780,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block->Append(vins); - InterInstruction* lins = new InterInstruction(exp->mLocation, IC_LOAD); + InterInstruction* lins = new InterInstruction(MapLocation(exp, inlineMapper), IC_LOAD); lins->mSrc[0].mMemory = IM_INDIRECT; lins->mSrc[0].mType = IT_POINTER; lins->mSrc[0].mTemp = vins->mDst.mTemp; @@ -3795,7 +3804,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_RETURN: { - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RETURN); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RETURN); if (exp->mLeft) { if (procType->mBase->IsReference()) @@ -3808,9 +3817,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr.mType = vr.mType->mBase; } - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); - vr = CoerceType(proc, exp, block, vr, procType->mBase); + vr = CoerceType(proc, exp, block, inlineMapper, vr, procType->mBase); if (vr.mReference == 0) mErrors->Error(exp->mLocation, EERR_INVALID_VALUE, "Returning value as reference"); @@ -3842,7 +3851,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); ains->mConst.mType = IT_POINTER; @@ -3869,7 +3878,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (procType->mBase->mType == DT_TYPE_STRUCT) { - InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); if (inlineMapper) { @@ -3894,7 +3903,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - InterInstruction* pins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* pins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); pins->mDst.mType = IT_POINTER; pins->mDst.mTemp = proc->AddTemporary(IT_POINTER); pins->mConst.mType = IT_POINTER; @@ -3926,7 +3935,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper, &rvr); - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID) mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Function has void return type"); @@ -3947,7 +3956,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!ccdec->mLinkerObject) this->TranslateProcedure(proc->mModule, ccdec->mValue, ccdec); - InterInstruction* psins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* psins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); psins->mDst.mType = IT_POINTER; psins->mDst.mTemp = proc->AddTemporary(IT_POINTER); psins->mConst.mVarIndex = 0; @@ -3962,12 +3971,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* psins->mConst.mMemory = IM_PARAM; block->Append(psins); - InterInstruction* ssins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* ssins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); ssins->mSrc[0] = ains->mDst; ssins->mSrc[1] = psins->mDst; block->Append(ssins); - InterInstruction* plins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* plins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); plins->mDst.mType = IT_POINTER; plins->mDst.mTemp = proc->AddTemporary(IT_POINTER); plins->mConst.mVarIndex = 2; @@ -3982,7 +3991,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* plins->mConst.mMemory = IM_PARAM; block->Append(plins); - InterInstruction* slins = new InterInstruction(exp->mLocation, IC_STORE); + InterInstruction* slins = new InterInstruction(MapLocation(exp, inlineMapper), IC_STORE); slins->mSrc[0].mType = IT_POINTER; slins->mSrc[0].mTemp = vr.mTemp; slins->mSrc[0].mMemory = IM_INDIRECT; @@ -3993,7 +4002,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* proc->AddCalledFunction(proc->mModule->mProcedures[ccdec->mVarIndex]); - InterInstruction* pcins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* pcins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); pcins->mDst.mType = IT_POINTER; pcins->mDst.mTemp = proc->AddTemporary(IT_POINTER); pcins->mConst.mType = IT_POINTER; @@ -4004,7 +4013,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* pcins->mConst.mLinkerObject = ccdec->mLinkerObject; block->Append(pcins); - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_CALL); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CALL); if (ccdec->mFlags & DTF_NATIVE) cins->mCode = IC_CALL_NATIVE; else @@ -4017,7 +4026,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - InterInstruction* cins = new InterInstruction(exp->mLocation, IC_COPY); + InterInstruction* cins = new InterInstruction(MapLocation(exp, inlineMapper), IC_COPY); cins->mSrc[0].mType = IT_POINTER; cins->mSrc[0].mTemp = vr.mTemp; cins->mSrc[0].mMemory = IM_INDIRECT; @@ -4040,12 +4049,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (procType->mBase->mType == DT_TYPE_POINTER && (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION)) { - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); vr.mReference = 0; vr.mType = procType->mBase; } else - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID) mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Function has void return type"); @@ -4054,7 +4063,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (!procType->mBase->CanAssign(vr.mType)) mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type"); - vr = CoerceType(proc, exp, block, vr, procType->mBase); + vr = CoerceType(proc, exp, block, inlineMapper, vr, procType->mBase); ins->mSrc[0].mType = InterTypeOf(vr.mType); ins->mSrc[0].mTemp = vr.mTemp; @@ -4072,7 +4081,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* ains = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); ains->mDst.mType = IT_POINTER; ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); ains->mConst.mType = IT_POINTER; @@ -4116,7 +4125,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (inlineMapper) { - InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); block->Append(jins); block->Close(inlineMapper->mReturn, nullptr); } @@ -4132,7 +4141,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (breakBlock.mBlock) { UnwindDestructStack(procType, proc, block, destack, breakBlock.mStack, inlineMapper); - InterInstruction * jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction * jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); block->Append(jins); block->Close(breakBlock.mBlock, nullptr); @@ -4149,7 +4158,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (continueBlock.mBlock) { UnwindDestructStack(procType, proc, block, destack, continueBlock.mStack, inlineMapper); - InterInstruction * jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction * jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); block->Append(jins); block->Close(continueBlock.mBlock, nullptr); @@ -4169,7 +4178,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, destack, inlineMapper); - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_UNREACHABLE); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_UNREACHABLE); ins->mNumOperands = 0; fblock->Append(ins); fblock->Close(nullptr, nullptr); @@ -4181,16 +4190,16 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_LOGICAL_NOT: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); - InterInstruction * zins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction * zins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); zins->mDst.mType = InterTypeOf(vl.mType); zins->mDst.mTemp = proc->AddTemporary(zins->mDst.mType); zins->mConst.mType = zins->mDst.mType; zins->mConst.mIntConst = 0; block->Append(zins); - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_RELATIONAL_OPERATOR); ins->mOperator = IA_CMPEQ; ins->mSrc[0].mType = InterTypeOf(vl.mType); ins->mSrc[0].mTemp = zins->mDst.mTemp; @@ -4213,7 +4222,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vl = TranslateExpression(procType, proc, block, exp->mRight->mLeft, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight->mRight, destack, breakBlock, continueBlock, inlineMapper); - vc = Dereference(proc, exp, block, vc); + vc = Dereference(proc, exp, block, inlineMapper, vc); int ttemp, tref = 0; InterType ttype, stypel, styper; @@ -4225,8 +4234,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (dtype->IsReference()) { - vl = Dereference(proc, exp, block, vl, 1); - vr = Dereference(proc, exp, block, vr, 1); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); tref = 1; dtype = dtype->mBase; @@ -4235,14 +4244,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else if (stypel == IT_POINTER || styper == IT_POINTER) { if (vl.mType->mType == DT_TYPE_ARRAY) - vl = Dereference(proc, exp, block, vl, 1); + vl = Dereference(proc, exp, block, inlineMapper, vl, 1); else - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); if (vr.mType->mType == DT_TYPE_ARRAY) - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); else - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (vl.mType->mBase->IsSubType(vr.mType->mBase)) dtype = vr.mType; @@ -4262,8 +4271,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - vl = Dereference(proc, exp, block, vl); - vr = Dereference(proc, exp, block, vr); + vl = Dereference(proc, exp, block, inlineMapper, vl); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (stypel == styper) { @@ -4275,22 +4284,22 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ttype = stypel; dtype = vl.mType; - vr = CoerceType(proc, exp, block, vr, dtype); + vr = CoerceType(proc, exp, block, inlineMapper, vr, dtype); } else { ttype = styper; dtype = vr.mType; - vl = CoerceType(proc, exp, block, vl, dtype); + vl = CoerceType(proc, exp, block, inlineMapper, vl, dtype); } } - vc = CoerceType(proc, exp, block, vc, TheBoolTypeDeclaration); + vc = CoerceType(proc, exp, block, inlineMapper, vc, TheBoolTypeDeclaration); ttemp = proc->AddTemporary(ttype); - InterInstruction* sins = new InterInstruction(exp->mLocation, IC_SELECT); + InterInstruction* sins = new InterInstruction(MapLocation(exp, inlineMapper), IC_SELECT); sins->mSrc[2].mType = InterTypeOf(vc.mType); sins->mSrc[2].mTemp = vc.mTemp; sins->mSrc[1].mType = ttype; @@ -4306,8 +4315,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* else #endif { - InterInstruction* jins0 = new InterInstruction(exp->mLocation, IC_JUMP); - InterInstruction* jins1 = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins0 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); + InterInstruction* jins1 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); InterCodeBasicBlock* tblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* fblock = new InterCodeBasicBlock(proc); @@ -4328,14 +4337,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (stypel == IT_POINTER || styper == IT_POINTER) { if (vl.mType->mType == DT_TYPE_ARRAY) - vl = Dereference(proc, exp, tblock, vl, 1); + vl = Dereference(proc, exp, tblock, inlineMapper, vl, 1); else - vl = Dereference(proc, exp, tblock, vl); + vl = Dereference(proc, exp, tblock, inlineMapper, vl); if (vr.mType->mType == DT_TYPE_ARRAY) - vr = Dereference(proc, exp, fblock, vr, 1); + vr = Dereference(proc, exp, fblock, inlineMapper, vr, 1); else - vr = Dereference(proc, exp, fblock, vr); + vr = Dereference(proc, exp, fblock, inlineMapper, vr); if (vl.mType->mBase->IsSubType(vr.mType->mBase)) dtype = vr.mType; @@ -4355,8 +4364,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - vl = Dereference(proc, exp, tblock, vl); - vr = Dereference(proc, exp, fblock, vr); + vl = Dereference(proc, exp, tblock, inlineMapper, vl); + vr = Dereference(proc, exp, fblock, inlineMapper, vr); if (stypel == styper) { @@ -4368,27 +4377,27 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* ttype = stypel; dtype = vl.mType; - vr = CoerceType(proc, exp, fblock, vr, dtype); + vr = CoerceType(proc, exp, fblock, inlineMapper, vr, dtype); } else { ttype = styper; dtype = vr.mType; - vl = CoerceType(proc, exp, tblock, vl, dtype); + vl = CoerceType(proc, exp, tblock, inlineMapper, vl, dtype); } } ttemp = proc->AddTemporary(ttype); - InterInstruction* rins = new InterInstruction(exp->mLocation, IC_LOAD_TEMPORARY); + InterInstruction* rins = new InterInstruction(MapLocation(exp, inlineMapper), IC_LOAD_TEMPORARY); rins->mSrc[0].mType = ttype; rins->mSrc[0].mTemp = vr.mTemp; rins->mDst.mType = ttype; rins->mDst.mTemp = ttemp; fblock->Append(rins); - InterInstruction* lins = new InterInstruction(exp->mLocation, IC_LOAD_TEMPORARY); + InterInstruction* lins = new InterInstruction(MapLocation(exp, inlineMapper), IC_LOAD_TEMPORARY); lins->mSrc[0].mType = ttype; lins->mSrc[0].mTemp = vl.mTemp; lins->mDst.mType = ttype; @@ -4413,11 +4422,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction * ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); if (exp->mDecType->mType == DT_TYPE_FLOAT && vr.mType->IsIntegerType()) { - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); int stemp = vr.mTemp; @@ -4425,7 +4434,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { if (vr.mType->mFlags & DTF_SIGNED) { - InterInstruction* xins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction* xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); xins->mOperator = IA_EXT8TO16S; xins->mSrc[0].mType = IT_INT8; xins->mSrc[0].mTemp = stemp; @@ -4436,7 +4445,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - InterInstruction* xins = new InterInstruction(exp->mLocation, IC_CONVERSION_OPERATOR); + InterInstruction* xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONVERSION_OPERATOR); xins->mOperator = IA_EXT8TO16U; xins->mSrc[0].mType = IT_INT8; xins->mSrc[0].mTemp = stemp; @@ -4456,7 +4465,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else if (exp->mDecType->IsIntegerType() && vr.mType->mType == DT_TYPE_FLOAT) { - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); ins->mOperator = (exp->mDecType->mFlags & DTF_SIGNED) ? IA_FLOAT2INT : IA_FLOAT2UINT; ins->mSrc[0].mType = InterTypeOf(vr.mType); ins->mSrc[0].mTemp = vr.mTemp; @@ -4466,7 +4475,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (exp->mDecType->mSize == 1) { - InterInstruction* xins = new InterInstruction(exp->mLocation, IC_TYPECAST); + InterInstruction* xins = new InterInstruction(MapLocation(exp, inlineMapper), IC_TYPECAST); xins->mSrc[0].mType = IT_INT16; xins->mSrc[0].mTemp = ins->mDst.mTemp; xins->mDst.mType = InterTypeOf(exp->mDecType); @@ -4492,8 +4501,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else if (exp->mDecType->IsIntegerType() && vr.mType->IsIntegerType()) { - vr = Dereference(proc, exp, block, vr); - return CoerceType(proc, exp, block, vr, exp->mDecType); + vr = Dereference(proc, exp, block, inlineMapper, vr); + return CoerceType(proc, exp, block, inlineMapper, vr, exp->mDecType); } else if (exp->mDecType->mType == DT_TYPE_VOID) { @@ -4503,12 +4512,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (vr.mReference == 0) mErrors->Error(exp->mLocation, EERR_NOT_AN_LVALUE, "Not an L value"); - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); return ExValue(exp->mDecType, vr.mTemp); } else { - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); ins->mCode = IC_TYPECAST; ins->mSrc[0].mType = vr.mReference > 0 ? IT_POINTER : InterTypeOf(vr.mType); ins->mSrc[0].mTemp = vr.mTemp; @@ -4524,8 +4533,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_LOGICAL_AND: case EX_LOGICAL_OR: { - InterInstruction* jins0 = new InterInstruction(exp->mLocation, IC_JUMP); - InterInstruction* jins1 = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins0 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); + InterInstruction* jins1 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); InterCodeBasicBlock* tblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* fblock = new InterCodeBasicBlock(proc); @@ -4535,14 +4544,14 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* int ttemp = proc->AddTemporary(IT_BOOL); - InterInstruction* tins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* tins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); tins->mConst.mType = IT_BOOL; tins->mConst.mIntConst = 1; tins->mDst.mType = IT_BOOL; tins->mDst.mTemp = ttemp; tblock->Append(tins); - InterInstruction* fins = new InterInstruction(exp->mLocation, IC_CONSTANT); + InterInstruction* fins = new InterInstruction(MapLocation(exp, inlineMapper), IC_CONSTANT); fins->mConst.mType = IT_BOOL; fins->mConst.mIntConst = 0; fins->mDst.mType = IT_BOOL; @@ -4577,9 +4586,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_DISPATCH: { vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_DISPATCH); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_DISPATCH); ins->mSrc[0].mType = IT_POINTER; ins->mSrc[0].mTemp = vl.mTemp; @@ -4603,8 +4612,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { DestructStack* odestack = destack; - InterInstruction * jins0 = new InterInstruction(exp->mLocation, IC_JUMP); - InterInstruction* jins1 = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction * jins0 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); + InterInstruction* jins1 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* lblock = cblock; @@ -4638,8 +4647,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { DestructStack* odestack = destack; - InterInstruction * jins0 = new InterInstruction(exp->mLocation, IC_JUMP); - InterInstruction* jins1 = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction * jins0 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); + InterInstruction* jins1 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); InterCodeBasicBlock* tblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* fblock = new InterCodeBasicBlock(proc); @@ -4681,10 +4690,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (exp->mLeft->mRight) TranslateExpression(procType, proc, block, exp->mLeft->mRight, destack, breakBlock, continueBlock, inlineMapper); - InterInstruction* jins0 = new InterInstruction(exp->mLocation, IC_JUMP); - InterInstruction* jins1 = new InterInstruction(exp->mLocation, IC_JUMP); - InterInstruction* jins2 = new InterInstruction(exp->mLocation, IC_JUMP); - InterInstruction* jins3 = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins0 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); + InterInstruction* jins1 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); + InterInstruction* jins2 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); + InterInstruction* jins3 = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* lblock = cblock; @@ -4735,7 +4744,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { DestructStack* odestack = destack; - InterInstruction * jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction * jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* lblock = cblock; @@ -4766,7 +4775,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* DestructStack* odestack = destack; vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); - vl = Dereference(proc, exp, block, vl); + vl = Dereference(proc, exp, block, inlineMapper, vl); int vleft = 0, vright = 65535; @@ -4786,7 +4795,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vright = 32767; } - vl = CoerceType(proc, exp, block, vl, TheSignedIntTypeDeclaration); + vl = CoerceType(proc, exp, block, inlineMapper, vl, TheSignedIntTypeDeclaration); InterCodeBasicBlock * dblock = nullptr; InterCodeBasicBlock* sblock = block; @@ -4824,7 +4833,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (block) { - InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); block->Append(jins); block->Close(nblock, nullptr); @@ -4840,7 +4849,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (block) { - InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); block->Append(jins); block->Close(dblock, nullptr); @@ -4859,13 +4868,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } - BuildSwitchTree(proc, exp, sblock, vl, switchNodes, 0, switchNodes.Size(), vleft, vright, dblock ? dblock : eblock); + BuildSwitchTree(proc, exp, sblock, inlineMapper, vl, switchNodes, 0, switchNodes.Size(), vleft, vright, dblock ? dblock : eblock); if (block) { UnwindDestructStack(procType, proc, block, destack, odestack, inlineMapper); - InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP); + InterInstruction* jins = new InterInstruction(MapLocation(exp, inlineMapper), IC_JUMP); block->Append(jins); block->Close(eblock, nullptr); @@ -5076,15 +5085,15 @@ void InterCodeGenerator::TranslateLogic(Declaration* procType, InterCodeProcedur ExValue vr = TranslateExpression(procType, proc, block, exp, destack, BranchTarget(), BranchTarget(), inlineMapper); if (vr.mType->mType == DT_TYPE_ARRAY) - vr = Dereference(proc, exp, block, vr, 1); + vr = Dereference(proc, exp, block, inlineMapper, vr, 1); else { - vr = Dereference(proc, exp, block, vr); + vr = Dereference(proc, exp, block, inlineMapper, vr); if (!vr.mType->IsSimpleType()) mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Not a valid condition value"); } - InterInstruction* ins = new InterInstruction(exp->mLocation, IC_BRANCH); + InterInstruction* ins = new InterInstruction(MapLocation(exp, inlineMapper), IC_BRANCH); ins->mSrc[0].mType = InterTypeOf(vr.mType); ins->mSrc[0].mTemp = vr.mTemp; block->Append(ins); diff --git a/oscar64/InterCodeGenerator.h b/oscar64/InterCodeGenerator.h index 544a8b4..e261f33 100644 --- a/oscar64/InterCodeGenerator.h +++ b/oscar64/InterCodeGenerator.h @@ -61,6 +61,7 @@ protected: int mResult, mDepth, mVarIndex; bool mConstExpr; ExValue * mResultExp; + Location * mLocation; InlineMapper(void) : mParams(-1), mResult(-1), mDepth(0), mResultExp(nullptr) @@ -78,17 +79,19 @@ protected: InterCodeProcedure* mMainInitProc; InterCodeBasicBlock* mMainInitBlock; - void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock); + Location MapLocation(Expression * exp, InlineMapper* inlineMapper); - ExValue ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v); - ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level = 0); - ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type, bool checkTrunc = true); + void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, InlineMapper * inlineMapper, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock); + + ExValue ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v); + ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v, int level = 0); + ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue v, Declaration * type, bool checkTrunc = true); ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper); ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp); void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving); - void CopyStructSimple(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock * block, ExValue vl, ExValue vr); - void StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr); + void CopyStructSimple(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock * block, InlineMapper* inlineMapper, ExValue vl, ExValue vr); + void StoreValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, InlineMapper* inlineMapper, ExValue vl, ExValue vr); void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom, InlineMapper* inlineMapper); void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 73fa14c..4f11a58 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -14159,6 +14159,15 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full) yoffset = 0; ypred = i; } + else if (mIns[i].mType == ASMIT_INC && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == yreg && yoffset == 1 && !(mIns[i].mLive & LIVE_CPU_REG_Z)) + { + mIns[i].mType = ASMIT_STY; + for (int j = ypred; j < i; j++) + mIns[j].mLive |= LIVE_CPU_REG_Y; + yoffset = 0; + ypred = i; + changed = true; + } #if 1 else if (mIns[i].mType == ASMIT_INC && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == yreg && yoffset == 0 && mIns[ypred].mType == ASMIT_STY && !(mIns[i].mLive & LIVE_CPU_REG_Y)) { diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 4c5fd7f..4bcae45 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -3279,6 +3279,7 @@ Expression* Parser::CleanupExpression(Expression* exp) Expression* cexp = new Expression(exp->mLocation, EX_CLEANUP); cexp->mLeft = exp; cexp->mRight = xexp; + cexp->mDecType = exp->mDecType; FreeTempVarExp(xexp); return cexp;