diff --git a/oscar64.md b/oscar64.md index 5bbee08..d3c69cf 100644 --- a/oscar64.md +++ b/oscar64.md @@ -334,6 +334,17 @@ The .asm file is a great resource when debugging from within e.g. the VICE monit The compiler has various extensions to simplify developing for the C64. +## Pragmas + +Warnings can be turned on or off using the warning pragma. The scope of the pragma is currently global in most cases, so if it is turned off at some place, it is off everywhere. + + #pragma warning(disable: 2000,2001) + +A message can be displayed during compilation with the message pragma + + #pragma message("Hello User") + + ## Embedding binary data The compiler supports the #embed preprocessor directive to import binary data. It converts a section of an external binary file into a sequence of numbers that can be placed into an initializer of an array. @@ -737,6 +748,11 @@ Regions can also be used to place assets such as character sets at fixed locatio The #pragma data(), #pragma code() and #pragma bss() control the placement of the generated objects into sections other than the default sections. +A global variable or function can be aligned on a given power of two start with the align pragma. This is most usefull if a page crossing is problematic. The compiler may also be able to generate more efficient code, if a larger variable is page aligned. + + #pragma align(myvar, 8) + #pragma align(myfunc, 256) + ### Additional BSS sections Additional bss sections can be defined on request. diff --git a/oscar64/BitVector.h b/oscar64/BitVector.h index e3c1fcf..f09eb45 100644 --- a/oscar64/BitVector.h +++ b/oscar64/BitVector.h @@ -3,6 +3,7 @@ #include #include #include +#include class BitVector { diff --git a/oscar64/Errors.cpp b/oscar64/Errors.cpp index fcfd0b7..56d2267 100644 --- a/oscar64/Errors.cpp +++ b/oscar64/Errors.cpp @@ -4,7 +4,7 @@ #include Errors::Errors(void) - : mErrorCount(0), mMinLevel(EINFO_GENERIC) + : mErrorCount(0), mMinLevel(EINFO_GENERIC), mDisabled(2000) { } @@ -29,7 +29,7 @@ void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const Iden void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char* info1, const char * info2) { - if (eid >= mMinLevel) + if (eid >= mMinLevel && !(eid < EERR_GENERIC && mDisabled[eid])) { const char* level = "info"; if (eid >= EERR_GENERIC) diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 4707f87..88a3e15 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -1,5 +1,7 @@ #pragma once +#include "NumberSet.h" + class Location { public: @@ -123,6 +125,8 @@ enum ErrorID EFATAL_GENERIC = 4000, EFATAL_OUT_OF_MEMORY, EFATAL_MACRO_EXPANSION_DEPTH, + + ERROR_MAX = 5000 }; class Errors @@ -135,6 +139,7 @@ public: int mErrorCount; ErrorID mMinLevel; + NumberSet mDisabled; 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/GlobalOptimizer.cpp b/oscar64/GlobalOptimizer.cpp index 360aca4..c01b2cd 100644 --- a/oscar64/GlobalOptimizer.cpp +++ b/oscar64/GlobalOptimizer.cpp @@ -60,7 +60,7 @@ void GlobalOptimizer::Reset(void) mFunctions.SetSize(0); mGlobalVariables.SetSize(0); mCalledFunctions.SetSize(0); - mCalledFunctions.SetSize(0); + mCallingFunctions.SetSize(0); } void GlobalOptimizer::PropagateParamCommas(Expression*& fexp, Expression*& exp) diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 43c3e3e..76eaccf 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -4357,6 +4357,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vins->mDst.mType = IT_POINTER; vins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + bool reference = false; + Declaration* vdec = refvars[i]; if (vdec->mType == DT_ARGUMENT) { @@ -4390,18 +4392,28 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vins->mConst.mIntConst = vdec->mOffset; if (inlineMapper) vins->mConst.mVarIndex += inlineMapper->mVarIndex; + + if (vdec->mBase->mType == DT_TYPE_ARRAY || vdec->mBase->mType == DT_TYPE_STRUCT) + reference = true; } block->Append(vins); - 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; - lins->mDst.mType = InterTypeOf(vdec->mBase); - lins->mDst.mTemp = proc->AddTemporary(lins->mDst.mType); - lins->mSrc[0].mOperandSize = vdec->mSize; - block->Append(lins); + InterInstruction* lins; + if (reference) + lins = vins; + else + { + lins = new InterInstruction(MapLocation(exp, inlineMapper), IC_LOAD); + lins->mDst.mType = InterTypeOf(vdec->mBase); + lins->mNumOperands = 1; + lins->mSrc[0].mMemory = IM_INDIRECT; + lins->mSrc[0].mType = IT_POINTER; + lins->mSrc[0].mTemp = vins->mDst.mTemp; + lins->mDst.mTemp = proc->AddTemporary(lins->mDst.mType); + lins->mSrc[0].mOperandSize = vdec->mSize; + block->Append(lins); + } if (jins->mNumOperands >= 32) mErrors->Error(exp->mLocation, EERR_ASSEMBLER_LIMIT, "Maximum number of variables in assembler block exceeded", vdec->mIdent); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 0fe67fa..762ff9d 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -54118,7 +54118,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mInterProc->mLinkerObject->mNativeProc = this; - CheckFunc = !strcmp(mIdent->mString, "dynamic"); + CheckFunc = !strcmp(mIdent->mString, "testf"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 6bcd3c5..04e9f5f 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -12799,6 +12799,34 @@ void Parser::ParsePragma(void) } ConsumeToken(TK_CLOSE_PARENTHESIS); } + else if (!strcmp(mScanner->mTokenIdent->mString, "warning")) + { + mScanner->NextToken(); + ConsumeToken(TK_OPEN_PARENTHESIS); + if (ConsumeIdentIf("disable")) + { + ConsumeToken(TK_COLON); + do { + if (ExpectToken(TK_INTEGER) && mScanner->mTokenInteger < EERR_GENERIC) + { + mErrors->mDisabled += int(mScanner->mTokenInteger); + mScanner->NextToken(); + } + } while (ConsumeTokenIf(TK_COMMA)); + } + else if (ConsumeToken(TK_DEFAULT)) + { + ConsumeToken(TK_COLON); + do { + if (ExpectToken(TK_INTEGER) && mScanner->mTokenInteger < EERR_GENERIC) + { + mErrors->mDisabled -= int(mScanner->mTokenInteger); + mScanner->NextToken(); + } + } while (ConsumeTokenIf(TK_COMMA)); + } + ConsumeToken(TK_CLOSE_PARENTHESIS); + } else if (!strcmp(mScanner->mTokenIdent->mString, "once")) { mScanner->MarkSourceOnce(); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index e52a4b7..1391144 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1116,46 +1116,70 @@ void Scanner::NextPreToken(void) while (mTokenChar == ' ') NextChar(); - while (mTokenChar == '#' && mLine[mOffset] == '#') + if (mTokenChar == '#' && mLine[mOffset] == '#') { - mOffset++; - NextChar(); - char tkbase[256]; strcpy_s(tkbase, mTokenIdent->mString); - ptrdiff_t n = 0; - char tkident[256]; - while (IsIdentChar(mTokenChar)) - { - if (n < 255) - tkident[n++] = mTokenChar; + do { + mOffset++; NextChar(); - } - tkident[n] = 0; - const Ident* ntkident = Ident::Unique(tkident); + ptrdiff_t n = 0; + char tkident[256]; + while (IsIdentChar(mTokenChar)) + { + if (n < 255) + tkident[n++] = mTokenChar; + NextChar(); + } + tkident[n] = 0; - Macro* def = nullptr; - if (mDefineArguments) - def = mDefineArguments->Lookup(ntkident); - if (!def) - def = mDefines->Lookup(ntkident); + const Ident* ntkident = Ident::Unique(tkident); - if (def) - strcat_s(tkbase, def->mString); - else - strcat_s(tkbase, tkident); + Macro* def = nullptr; + if (mDefineArguments) + def = mDefineArguments->Lookup(ntkident); + if (!def) + def = mDefines->Lookup(ntkident); - n = strlen(tkbase); - while (n > 0 && tkbase[n - 1] == ' ') - n--; - tkbase[n] = 0; + if (def) + strcat_s(tkbase, def->mString); + else + strcat_s(tkbase, tkident); - mTokenIdent = Ident::Unique(tkbase); + n = strlen(tkbase); + while (n > 0 && tkbase[n - 1] == ' ') + n--; + tkbase[n] = 0; + + while (mTokenChar == ' ') + NextChar(); + + } while (mTokenChar == '#' && mLine[mOffset] == '#'); + + ptrdiff_t n = strlen(tkbase); + char* str = new char[n + 1]; + strcpy_s(str, n + 1, tkbase); + + MacroExpansion* ex = new MacroExpansion(); + ex->mDefinedArguments = mDefineArguments; + + ex->mLine = mLine; + ex->mOffset = mOffset; + ex->mLink = mMacroExpansion; + ex->mChar = mTokenChar; + + mMacroExpansion = ex; + mMacroExpansionDepth++; + if (mMacroExpansionDepth > 1024) + mErrors->Error(mLocation, EFATAL_MACRO_EXPANSION_DEPTH, "Maximum macro expansion depth exceeded", mTokenIdent); + mLine = str; + mOffset = 0; + NextChar(); } - - return; + else + return; } } else