Add warning pragma, improved token concatenation in preprocessing
This commit is contained in:
parent
5ad94d01d4
commit
96a9109915
16
oscar64.md
16
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.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
class BitVector
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue