diff --git a/autotest/autotest.bat b/autotest/autotest.bat index e0f05fd..0cf6149 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -129,6 +129,9 @@ rem @echo off @call :test ptrinittest.c @if %errorlevel% neq 0 goto :error +@call :test ptrarraycmptest.c +@if %errorlevel% neq 0 goto :error + @exit /b 0 :error diff --git a/autotest/ptrarraycmptest.c b/autotest/ptrarraycmptest.c new file mode 100644 index 0000000..ef0860a --- /dev/null +++ b/autotest/ptrarraycmptest.c @@ -0,0 +1,39 @@ +#include + +struct X +{ + int a; +}; + +X x[5] = { + {1}, {2}, {3}, {4}, {5} +}; + +X * y; + +int main(void) +{ + y = x; + assert(y == x); + y = x + 1; + assert(y == x + 1); + y = &(x[2]); + assert(y == x + 2); + y = x + 3; + assert(y == &(x[3])); + y = x ; + assert(y == (struct X*)x); + + y = x; + assert(x == y); + y = x + 1; + assert(x + 1 == y); + y = &(x[2]); + assert(x + 2 == y); + y = x + 3; + assert(&(x[3]) == y); + y = x ; + assert((struct X*)x == y); + + return 0; +} diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index ccd4bc0..3b0a8a7 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -273,7 +273,7 @@ bool Compiler::GenerateCode(void) } #endif - for (int i = 0; i < mInterCodeModule->mProcedures.Size(); i++) + for (int i = mInterCodeModule->mProcedures.Size() - 1; i >=0; i--) { InterCodeProcedure* proc = mInterCodeModule->mProcedures[i]; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 7a1bb43..8e992eb 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -557,6 +557,9 @@ bool Declaration::IsSubType(const Declaration* dec) const if (dl || dr) return false; + if ((mFlags & DTF_INTERRUPT) && !(dec->mFlags & DTF_INTERRUPT)) + return false; + if ((mFlags & DTF_VARIADIC) != (dec->mFlags & DTF_VARIADIC)) return false; @@ -682,7 +685,7 @@ bool Declaration::CanAssign(const Declaration* fromType) const } else if (mBase->mType == DT_TYPE_FUNCTION && fromType->mType == DT_TYPE_FUNCTION) { - return mBase->IsSame(fromType); + return mBase->IsSubType(fromType); } else if (mBase->mType == DT_TYPE_VOID && fromType->mType == DT_TYPE_ASSEMBLER) { diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 63c139f..2d4ebd0 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -76,6 +76,7 @@ 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_FUNC_CONSTEXPR = (1ULL << 36); +static const uint64 DTF_FUNC_INTRSAVE = (1ULL << 37); static const uint64 DTF_VAR_ALIASING = (1ULL << 37); diff --git a/oscar64/Errors.h b/oscar64/Errors.h index a0001ba..94c921d 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -18,6 +18,7 @@ enum ErrorID EWARN_UNKNOWN_PRAGMA, EWARN_INDEX_OUT_OF_BOUNDS, EWARN_SYNTAX, + EWARN_NOT_INTERRUPT_SAFE, EERR_GENERIC = 3000, EERR_FILE_NOT_FOUND, diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index de4e52a..ff1ea7a 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -159,6 +159,8 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) mFunctions.Push(dec); dec->mFlags |= DTF_ANALYZED; + dec->mFlags |= DTF_FUNC_INTRSAVE; + if ((dec->mFlags & DTF_INTRINSIC) && !dec->mValue) dec->mFlags |= DTF_FUNC_CONSTEXPR; else if (dec->mFlags & DTF_DEFINED) @@ -325,6 +327,13 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) case EX_CALL: ldec = Analyze(exp->mLeft, procDec); RegisterCall(procDec, ldec); + if (!(GetProcFlags(ldec) & (DTF_FUNC_INTRSAVE | DTF_INTERRUPT))) + { + procDec->mFlags &= ~DTF_FUNC_INTRSAVE; + if (procDec->mFlags & DTF_INTERRUPT) + mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent->mString); + } + if (exp->mRight) RegisterProc(Analyze(exp->mRight, procDec)); break; @@ -423,6 +432,20 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) return TheVoidTypeDeclaration; } +uint64 GlobalAnalyzer::GetProcFlags(Declaration* to) const +{ + if (to->mType == DT_CONST_FUNCTION) + return to->mFlags; + else if (to->mType == DT_TYPE_FUNCTION) + return to->mFlags; + else if (to->mType == DT_TYPE_POINTER && to->mBase->mType == DT_TYPE_FUNCTION) + return GetProcFlags(to->mBase); + else if (to->mType == DT_VARIABLE || to->mType == DT_ARGUMENT) + return GetProcFlags(to->mBase); + else + return 0; +} + void GlobalAnalyzer::RegisterCall(Declaration* from, Declaration* to) { if (from) diff --git a/oscar64/GlobalAnalyzer.h b/oscar64/GlobalAnalyzer.h index 2252b09..0e03b5a 100644 --- a/oscar64/GlobalAnalyzer.h +++ b/oscar64/GlobalAnalyzer.h @@ -27,6 +27,7 @@ protected: Declaration* Analyze(Expression* exp, Declaration* procDec); + uint64 GetProcFlags(Declaration* to) const; void RegisterCall(Declaration* from, Declaration* to); void RegisterProc(Declaration* to); }; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index b5aab9d..16e568e 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -2627,6 +2627,16 @@ bool InterInstruction::ConstantFolding(void) mNumOperands = 0; return true; } + else if (mSrc[0].mTemp == mSrc[1].mTemp) + { + mCode = IC_CONSTANT; + mConst.mIntConst = ::ConstantFolding(mOperator, mSrc[0].mType, 0, 0); + mConst.mType = IT_BOOL; + mSrc[0].mTemp == -1; + mSrc[1].mTemp == -1; + mNumOperands = 0; + return true; + } break; case IC_BINARY_OPERATOR: if (mSrc[0].mTemp < 0 && mSrc[1].mTemp < 0) @@ -8581,6 +8591,9 @@ void InterCodeProcedure::Close(void) ResetVisited(); mEntryBlock->CollectOuterFrame(0, size, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode); + + if (mModule->mCompilerOptions & COPT_NATIVE) + mCallsByteCode = false; mCommonFrameSize = size; } else @@ -9074,6 +9087,7 @@ void InterCodeProcedure::RemoveNonRelevantStatics(void) { ResetVisited(); mEntryBlock->RemoveNonRelevantStatics(); + RemoveUnusedInstructions(); } void InterCodeProcedure::MapVariables(void) @@ -9390,7 +9404,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/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 82d1ea4..491a04d 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1717,9 +1717,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* case EX_RELATIONAL: { vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); - vl = Dereference(proc, block, vl); + vl = Dereference(proc, block, vl, vl.mType->mType == DT_TYPE_ARRAY ? 1 : 0); vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); - vr = Dereference(proc, block, vr); + vr = Dereference(proc, block, vr, vr.mType->mType == DT_TYPE_ARRAY ? 1 : 0); InterInstruction * ins = new InterInstruction(); diff --git a/oscar64/Linker.h b/oscar64/Linker.h index efbf3f8..32d894b 100644 --- a/oscar64/Linker.h +++ b/oscar64/Linker.h @@ -48,6 +48,11 @@ struct ZeroPageSet mBits[n >> 5] |= 1 << (n & 31); } + void operator -= (int n) + { + mBits[n >> 5] &= ~(1 << (n & 31)); + } + bool operator[] (int n) const { return (mBits[n >> 5] & (1 << (n & 31))) != 0; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 2ce8a8a..b47a290 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -8214,7 +8214,7 @@ void NativeCodeBasicBlock::CallFunction(InterCodeProcedure* proc, NativeCodeProc } } -void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction* ins) +void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, NativeCodeProcedure * nproc, const InterInstruction* ins) { if (ins->mCode == IC_ASSEMBLER) { @@ -8232,10 +8232,22 @@ void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterIn ins->mSrc[0].mLinkerObject->mNumTemporaries = ins->mNumOperands - 1; } - assert(ins->mSrc[0].mLinkerObject); + if (ins->mSrc[0].mTemp < 0) + { + assert(ins->mSrc[0].mLinkerObject); + mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject)); + } + else + { + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU)); + mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + + NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bcexec"))); + mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_FEXEC)); + } - mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject)); - if (ins->mDst.mTemp >= 0) { if (ins->mDst.mType == IT_FLOAT) @@ -8658,7 +8670,7 @@ void NativeCodeBasicBlock::CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet& case ASMIM_ABSOLUTE: if (mIns[i].mType == ASMIT_JSR) { - if (mIns[i].mFlags & NCIF_RUNTIME) + if ((mIns[i].mFlags & NCIF_RUNTIME) && !(mIns[i].mFlags & NCIF_FEXEC)) { for (int j = 0; j < 4; j++) { @@ -16028,6 +16040,20 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_PHA)); } + bool usesStack = false; + + if (zpLocal[BC_REG_STACK]) + { + usesStack = true; + zpLocal -= BC_REG_STACK; + zpLocal -= BC_REG_STACK + 1; + } + + if (usesStack) + { + mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + } + for (int i = 2; i < 256; i++) { if (zpLocal[i]) @@ -16045,6 +16071,10 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, i)); } } + if (usesStack) + { + mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1)); + } if (proc->mHardwareInterrupt) { @@ -16803,7 +16833,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode break; case IC_CALL_NATIVE: case IC_ASSEMBLER: - block->CallAssembler(iproc, ins); + block->CallAssembler(iproc, this, ins); break; case IC_PUSH_FRAME: { diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 3f55293..5fb0655 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -181,7 +181,7 @@ public: NativeCodeBasicBlock * CopyValue(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc); NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc); - void CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins); + void CallAssembler(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); void ShiftRegisterLeft(InterCodeProcedure* proc, int reg, int shift); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 6c0f1e0..f250e9c 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -962,7 +962,7 @@ Declaration* Parser::ParseDeclaration(bool variable) } } - Declaration* bdec = ParseBaseTypeDeclaration(0); + Declaration* bdec = ParseBaseTypeDeclaration(typeFlags); Declaration* rdec = nullptr, * ldec = nullptr; @@ -988,6 +988,8 @@ Declaration* Parser::ParseDeclaration(bool variable) } } + if (npdec->mBase->mType == DT_TYPE_FUNCTION) + npdec->mBase->mFlags |= storageFlags & (DTF_INTERRUPT | DTF_NATIVE | TK_FASTCALL); if (definingType) { diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index 9bbd5e4..c6b6121 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -73,7 +73,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.4.89"); + strcpy(strProductVersion, "1.4.90"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 6f1069a..9e0d407 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,89,0 - PRODUCTVERSION 1,4,89,0 + FILEVERSION 1,4,90,0 + PRODUCTVERSION 1,4,90,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.4.89.0" + VALUE "FileVersion", "1.4.90.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.4.89.0" + VALUE "ProductVersion", "1.4.90.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 4684183..6e71ede 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -3752,15 +3752,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{96DACD5F-2EC0-4296-9AFE-FB3F0A377D2A}" - "PackageCode" = "8:{49C9E61D-9B14-437A-A945-39BFE6ED8516}" + "ProductCode" = "8:{713950ED-E82C-46AE-AEE1-B7696F19319F}" + "PackageCode" = "8:{9CE6068F-14BD-457A-B770-D8A1BA054207}" "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.4.89" + "ProductVersion" = "8:1.4.90" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:"