Add warning pragma, improved token concatenation in preprocessing

This commit is contained in:
drmortalwombat 2025-04-24 09:05:57 +02:00
parent 5ad94d01d4
commit 96a9109915
9 changed files with 127 additions and 41 deletions

View File

@ -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.

View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
class BitVector
{

View File

@ -4,7 +4,7 @@
#include <stdlib.h>
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)

View File

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

View File

@ -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)

View File

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

View File

@ -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];

View File

@ -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();

View File

@ -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