Improve C const declaration compatibility

This commit is contained in:
drmortalwombat 2022-01-21 14:42:49 +01:00
parent 8b4eff3ee1
commit cc927d778f
9 changed files with 145 additions and 15 deletions

View File

@ -776,7 +776,7 @@ void mat4_mmul(Matrix4 * md, const Matrix4 * ms)
for(char j=0; j<4; j++) for(char j=0; j<4; j++)
ma[j] = md->m[i + 0] * ms->m[4 * j] + md->m[i + 4] * ms->m[4 * j + 1] + md->m[i + 8] * ms->m[4 * j + 2] + md->m[i + 12] * ms->m[4 * j + 3]; ma[j] = md->m[i + 0] * ms->m[4 * j] + md->m[i + 4] * ms->m[4 * j + 1] + md->m[i + 8] * ms->m[4 * j + 2] + md->m[i + 12] * ms->m[4 * j + 3];
for(char j=0; j<4; j++) for(char j=0; j<4; j++)
md->m[(char)(i + 4 * j)] = ma[j]; md->m[i + 4 * j] = ma[j];
} }
} }

View File

@ -377,6 +377,21 @@ Declaration::~Declaration(void)
delete[] mData; delete[] mData;
} }
Declaration* Declaration::ToConstType(void)
{
if (mFlags & DTF_CONST)
return this;
Declaration* ndec = new Declaration(mLocation, mType);
ndec->mSize = mSize;
ndec->mBase = mBase;
ndec->mFlags = mFlags | DTF_CONST;
ndec->mScope = mScope;
ndec->mParams = mParams;
return ndec;
}
bool Declaration::IsSubType(const Declaration* dec) const bool Declaration::IsSubType(const Declaration* dec) const
{ {
if (this == dec) if (this == dec)
@ -403,6 +418,8 @@ bool Declaration::IsSubType(const Declaration* dec) const
return true; return true;
else if (mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_VOID) else if (mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_VOID)
return true; return true;
else if (mType == DT_TYPE_STRUCT && dec->mType == DT_TYPE_STRUCT)
return mScope == dec->mScope;
else if (mType == DT_TYPE_STRUCT || mType == DT_TYPE_ENUM || mType == DT_TYPE_UNION) else if (mType == DT_TYPE_STRUCT || mType == DT_TYPE_ENUM || mType == DT_TYPE_UNION)
return false; return false;
else if (mType == DT_TYPE_ARRAY) else if (mType == DT_TYPE_ARRAY)
@ -457,6 +474,8 @@ bool Declaration::IsSame(const Declaration* dec) const
} }
else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY)
return mBase->IsSame(dec->mBase); return mBase->IsSame(dec->mBase);
else if (mType == DT_TYPE_STRUCT && dec->mType == DT_TYPE_STRUCT)
return mScope == dec->mScope;
else if (mType == DT_TYPE_FUNCTION) else if (mType == DT_TYPE_FUNCTION)
{ {
if (!mBase->IsSame(dec->mBase)) if (!mBase->IsSame(dec->mBase))
@ -491,6 +510,8 @@ bool Declaration::CanAssign(const Declaration* fromType) const
if (fromType->IsNumericType()) if (fromType->IsNumericType())
return true; return true;
} }
else if (mType == DT_TYPE_STRUCT && fromType->mType == DT_TYPE_STRUCT)
return mScope == fromType->mScope;
else if (mType == DT_TYPE_POINTER) else if (mType == DT_TYPE_POINTER)
{ {
if (fromType->mType == DT_TYPE_POINTER || fromType->mType == DT_TYPE_ARRAY) if (fromType->mType == DT_TYPE_POINTER || fromType->mType == DT_TYPE_ARRAY)

View File

@ -105,6 +105,7 @@ enum ExpressionType
EX_CONSTANT, EX_CONSTANT,
EX_VARIABLE, EX_VARIABLE,
EX_ASSIGNMENT, EX_ASSIGNMENT,
EX_INITIALIZATION,
EX_BINARY, EX_BINARY,
EX_RELATIONAL, EX_RELATIONAL,
EX_PREINCDEC, EX_PREINCDEC,
@ -187,6 +188,8 @@ public:
bool IsIntegerType(void) const; bool IsIntegerType(void) const;
bool IsNumericType(void) const; bool IsNumericType(void) const;
bool IsSimpleType(void) const; bool IsSimpleType(void) const;
Declaration* ToConstType(void);
}; };
void InitDeclarations(void); void InitDeclarations(void);

View File

@ -279,6 +279,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec)
} }
} }
return exp->mDecValue; return exp->mDecValue;
case EX_INITIALIZATION:
case EX_ASSIGNMENT: case EX_ASSIGNMENT:
ldec = Analyze(exp->mLeft, procDec); ldec = Analyze(exp->mLeft, procDec);
rdec = Analyze(exp->mRight, procDec); rdec = Analyze(exp->mRight, procDec);

View File

@ -940,6 +940,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case EX_ASSIGNMENT: case EX_ASSIGNMENT:
case EX_INITIALIZATION:
{ {
if (exp->mLeft->mDecType && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT) if (exp->mLeft->mDecType && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT)
{ {
@ -958,7 +959,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
} }
if (vl.mType->mFlags & DTF_CONST) if (exp->mType != EX_INITIALIZATION && (vl.mType->mFlags & DTF_CONST))
mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot assign to const type"); mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot assign to const type");
if (vl.mType->mType == DT_TYPE_STRUCT || vl.mType->mType == DT_TYPE_ARRAY || vl.mType->mType == DT_TYPE_UNION) if (vl.mType->mType == DT_TYPE_STRUCT || vl.mType->mType == DT_TYPE_ARRAY || vl.mType->mType == DT_TYPE_UNION)

View File

@ -2628,18 +2628,25 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
block->PutByte(mParam); block->PutByte(mParam);
} }
if (mMode == ASMIM_IMMEDIATE_ADDRESS) AsmInsMode mode = mMode;
if (mode == ASMIM_ABSOLUTE && !mLinkerObject && mAddress < 256 && HasAsmInstructionMode(mType, ASMIM_ZERO_PAGE))
mode = ASMIM_ZERO_PAGE;
else if (mode == ASMIM_ABSOLUTE_X && !mLinkerObject && mAddress < 256 && HasAsmInstructionMode(mType, ASMIM_ZERO_PAGE_X))
mode = ASMIM_ZERO_PAGE_X;
if (mode == ASMIM_IMMEDIATE_ADDRESS)
{ {
assert(HasAsmInstructionMode(mType, ASMIM_IMMEDIATE)); assert(HasAsmInstructionMode(mType, ASMIM_IMMEDIATE));
block->PutByte(AsmInsOpcodes[mType][ASMIM_IMMEDIATE]); block->PutByte(AsmInsOpcodes[mType][ASMIM_IMMEDIATE]);
} }
else else
{ {
assert(HasAsmInstructionMode(mType, mMode)); assert(HasAsmInstructionMode(mType, mode));
block->PutByte(AsmInsOpcodes[mType][mMode]); block->PutByte(AsmInsOpcodes[mType][mode]);
} }
switch (mMode) switch (mode)
{ {
case ASMIM_IMPLIED: case ASMIM_IMPLIED:
break; break;
@ -12802,20 +12809,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
progress = true; progress = true;
} }
#if 1
else if ( else if (
mIns[i + 0].mType == ASMIT_TXA && mIns[i + 0].mType == ASMIT_TXA &&
mIns[i + 1].mType == ASMIT_CMP && (mIns[i + 1].mMode == ASMIM_IMMEDIATE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE)) mIns[i + 1].mType == ASMIT_CMP && (mIns[i + 1].mMode == ASMIM_IMMEDIATE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
{ {
mIns[i + 1].mType = ASMIT_CPX; mIns[i + 1].mType = ASMIT_CPX;
mIns[i + 0].mLive |= CPU_REG_X; mIns[i + 0].mLive |= LIVE_CPU_REG_X;
progress = true; progress = true;
} }
#endif
else if ( else if (
mIns[i + 0].mType == ASMIT_TYA && mIns[i + 0].mType == ASMIT_TYA &&
mIns[i + 1].mType == ASMIT_CMP && (mIns[i + 1].mMode == ASMIM_IMMEDIATE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE)) mIns[i + 1].mType == ASMIT_CMP && (mIns[i + 1].mMode == ASMIM_IMMEDIATE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
{ {
mIns[i + 1].mType = ASMIT_CPY; mIns[i + 1].mType = ASMIT_CPY;
mIns[i + 0].mLive |= CPU_REG_Y; mIns[i + 0].mLive |= LIVE_CPU_REG_Y;
progress = true; progress = true;
} }
else if ( else if (

View File

@ -235,6 +235,16 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint32 flags)
ndec->mBase = dec->mBase; ndec->mBase = dec->mBase;
dec = ndec; dec = ndec;
} }
else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags))
{
Declaration* ndec = new Declaration(dec->mLocation, dec->mType);
ndec->mFlags = dec->mFlags | flags;
ndec->mSize = dec->mSize;
ndec->mBase = dec->mBase;
ndec->mScope = dec->mScope;
ndec->mParams = dec->mParams;
dec = ndec;
}
mScanner->NextToken(); mScanner->NextToken();
} }
else if (!dec) else if (!dec)
@ -345,6 +355,12 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint32 flags)
dec->mFlags |= DTF_DEFINED; dec->mFlags |= DTF_DEFINED;
} }
if (mScanner->mToken == TK_CONST)
{
dec = dec->ToConstType();
mScanner->NextToken();
}
return dec; return dec;
} }
@ -356,11 +372,18 @@ Declaration* Parser::ParsePostfixDeclaration(void)
if (mScanner->mToken == TK_MUL) if (mScanner->mToken == TK_MUL)
{ {
mScanner->NextToken(); mScanner->NextToken();
Declaration* dec = ParsePostfixDeclaration();
Declaration* ndec = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); Declaration* ndec = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
ndec->mBase = dec;
ndec->mSize = 2; ndec->mSize = 2;
ndec->mFlags |= DTF_DEFINED; ndec->mFlags |= DTF_DEFINED;
if (mScanner->mToken == TK_CONST)
{
ndec->mFlags |= DTF_CONST;
mScanner->NextToken();
}
Declaration* dec = ParsePostfixDeclaration();
ndec->mBase = dec;
return ndec; return ndec;
} }
else if (mScanner->mToken == TK_OPEN_PARENTHESIS) else if (mScanner->mToken == TK_OPEN_PARENTHESIS)
@ -648,6 +671,23 @@ Expression* Parser::ParseInitExpression(Declaration* dtype)
Declaration* mdec = dtype->mParams; Declaration* mdec = dtype->mParams;
while (mdec) while (mdec)
{ {
if (ConsumeTokenIf(TK_DOT))
{
if (mScanner->mToken == TK_IDENT)
{
Declaration* ndec = dtype->mScope->Lookup(mScanner->mTokenIdent);
if (ndec)
mdec = ndec;
else
mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "Struct member not found");
mScanner->NextToken();
ConsumeToken(TK_ASSIGN);
}
else
mErrors->Error(mScanner->mLocation, EERR_CONSTANT_INITIALIZER, "Identifier expected");
}
Expression* texp = ParseInitExpression(mdec->mBase); Expression* texp = ParseInitExpression(mdec->mBase);
Declaration* cdec = CopyConstantInitializer(mdec->mOffset, mdec->mBase, texp); Declaration* cdec = CopyConstantInitializer(mdec->mOffset, mdec->mBase, texp);
@ -907,11 +947,32 @@ Declaration* Parser::ParseDeclaration(bool variable)
ndec = pdec; ndec = pdec;
} }
else if ((ndec->mFlags & DTF_EXTERN) || (pdec->mFlags & DTF_EXTERN)) else if (ndec->mFlags & DTF_EXTERN)
{ {
if (!ndec->mBase->IsSame(pdec->mBase)) if (!ndec->mBase->IsSame(pdec->mBase))
{ {
mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Variable declaration differs"); if (ndec->mBase->mType == DT_TYPE_ARRAY && pdec->mBase->mType == DT_TYPE_ARRAY && ndec->mBase->mBase->IsSame(pdec->mBase->mBase) && ndec->mBase->mSize == 0)
;
else if (ndec->mBase->mType == DT_TYPE_POINTER && pdec->mBase->mType == DT_TYPE_ARRAY && ndec->mBase->mBase->IsSame(pdec->mBase->mBase))
;
else
mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Variable declaration differs");
}
ndec = pdec;
}
else if (pdec->mFlags & DTF_EXTERN)
{
if (!ndec->mBase->IsSame(pdec->mBase))
{
if (ndec->mBase->mType == DT_TYPE_ARRAY && pdec->mBase->mType == DT_TYPE_ARRAY && ndec->mBase->mBase->IsSame(pdec->mBase->mBase) && pdec->mBase->mSize == 0)
pdec->mBase->mSize = ndec->mBase->mSize;
else if (pdec->mBase->mType == DT_TYPE_POINTER && ndec->mBase->mType == DT_TYPE_ARRAY && ndec->mBase->mBase->IsSame(pdec->mBase->mBase))
{
pdec->mBase = ndec->mBase;
}
else
mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Variable declaration differs");
} }
if (!(ndec->mFlags & DTF_EXTERN)) if (!(ndec->mFlags & DTF_EXTERN))
@ -991,9 +1052,9 @@ Expression* Parser::ParseDeclarationExpression(void)
{ {
while (dec) while (dec)
{ {
if (dec->mValue) if (dec->mValue && !(dec->mFlags & DTF_GLOBAL))
{ {
Expression* nexp = new Expression(dec->mValue->mLocation, EX_ASSIGNMENT); Expression* nexp = new Expression(dec->mValue->mLocation, EX_INITIALIZATION);
nexp->mToken = TK_ASSIGN; nexp->mToken = TK_ASSIGN;
nexp->mLeft = new Expression(dec->mLocation, EX_VARIABLE); nexp->mLeft = new Expression(dec->mLocation, EX_VARIABLE);
nexp->mLeft->mDecValue = dec; nexp->mLeft->mDecValue = dec;
@ -1125,7 +1186,7 @@ Expression* Parser::ParseSimpleExpression(void)
dec->mBase->mSize = dec->mSize; dec->mBase->mSize = dec->mSize;
dec->mBase->mBase = TheConstCharTypeDeclaration; dec->mBase->mBase = TheConstCharTypeDeclaration;
dec->mBase->mFlags |= DTF_DEFINED; dec->mBase->mFlags |= DTF_DEFINED;
uint8* d = new uint8[dec->mSize]; uint8* d = new uint8[dec->mSize + 1];
dec->mData = d; dec->mData = d;
int i = 0; int i = 0;

View File

@ -123,6 +123,7 @@ const char* TokenNames[] =
"embedded", "embedded",
"'#define'", "'#define'",
"'#undef'",
"'#include'", "'#include'",
"'#if'", "'#if'",
"'#elif'", "'#elif'",
@ -241,6 +242,26 @@ void MacroDict::Insert(Macro * macro)
} }
} }
void MacroDict::Remove(const Ident* ident)
{
if (mHashSize > 0)
{
int hm = mHashSize - 1;
int hi = ident->mHash & hm;
while (mHash[hi])
{
if (ident == mHash[hi]->mIdent)
{
mHash[hi]->mIdent = nullptr;
return;
}
hi = (hi + 1) & hm;
}
}
}
Macro* MacroDict::Lookup(const Ident* ident) Macro* MacroDict::Lookup(const Ident* ident)
{ {
if (mHashSize > 0) if (mHashSize > 0)
@ -512,6 +533,15 @@ void Scanner::NextToken(void)
mOffset += slen; mOffset += slen;
} }
} }
else if (mToken == TK_PREP_UNDEF)
{
NextRawToken();
if (mToken == TK_IDENT)
{
mDefines->Remove(mTokenIdent);
}
}
else if (mToken == TK_PREP_IFDEF) else if (mToken == TK_PREP_IFDEF)
{ {
NextRawToken(); NextRawToken();
@ -1045,6 +1075,8 @@ void Scanner::NextRawToken(void)
if (!strcmp(tkprep, "define")) if (!strcmp(tkprep, "define"))
mToken = TK_PREP_DEFINE; mToken = TK_PREP_DEFINE;
else if (!strcmp(tkprep, "undef"))
mToken = TK_PREP_UNDEF;
else if (!strcmp(tkprep, "include")) else if (!strcmp(tkprep, "include"))
mToken = TK_PREP_INCLUDE; mToken = TK_PREP_INCLUDE;
else if (!strcmp(tkprep, "if")) else if (!strcmp(tkprep, "if"))

View File

@ -121,6 +121,7 @@ enum Token
TK_EMBEDDED, TK_EMBEDDED,
TK_PREP_DEFINE, TK_PREP_DEFINE,
TK_PREP_UNDEF,
TK_PREP_INCLUDE, TK_PREP_INCLUDE,
TK_PREP_IF, TK_PREP_IF,
TK_PREP_ELIF, TK_PREP_ELIF,
@ -165,6 +166,7 @@ public:
~MacroDict(void); ~MacroDict(void);
void Insert(Macro * macro); void Insert(Macro * macro);
void Remove(const Ident* ident);
Macro* Lookup(const Ident* ident); Macro* Lookup(const Ident* ident);
protected: protected: