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");