Add check for __interrupt attribute on function pointers call from interrupt code

This commit is contained in:
drmortalwombat 2022-02-15 09:49:46 +01:00
parent fdb112a037
commit 1221649a3d
17 changed files with 143 additions and 21 deletions

View File

@ -129,6 +129,9 @@ rem @echo off
@call :test ptrinittest.c @call :test ptrinittest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test ptrarraycmptest.c
@if %errorlevel% neq 0 goto :error
@exit /b 0 @exit /b 0
:error :error

View File

@ -0,0 +1,39 @@
#include <assert.h>
struct X
{
int a;
};
X x[5] = {
{1}, {2}, {3}, {4}, {5}
};
X * y;
int main(void)
{
y = x;
assert(y == x);
y = x + 1;
assert(y == x + 1);
y = &(x[2]);
assert(y == x + 2);
y = x + 3;
assert(y == &(x[3]));
y = x ;
assert(y == (struct X*)x);
y = x;
assert(x == y);
y = x + 1;
assert(x + 1 == y);
y = &(x[2]);
assert(x + 2 == y);
y = x + 3;
assert(&(x[3]) == y);
y = x ;
assert((struct X*)x == y);
return 0;
}

View File

@ -273,7 +273,7 @@ bool Compiler::GenerateCode(void)
} }
#endif #endif
for (int i = 0; i < mInterCodeModule->mProcedures.Size(); i++) for (int i = mInterCodeModule->mProcedures.Size() - 1; i >=0; i--)
{ {
InterCodeProcedure* proc = mInterCodeModule->mProcedures[i]; InterCodeProcedure* proc = mInterCodeModule->mProcedures[i];

View File

@ -557,6 +557,9 @@ bool Declaration::IsSubType(const Declaration* dec) const
if (dl || dr) if (dl || dr)
return false; return false;
if ((mFlags & DTF_INTERRUPT) && !(dec->mFlags & DTF_INTERRUPT))
return false;
if ((mFlags & DTF_VARIADIC) != (dec->mFlags & DTF_VARIADIC)) if ((mFlags & DTF_VARIADIC) != (dec->mFlags & DTF_VARIADIC))
return false; return false;
@ -682,7 +685,7 @@ bool Declaration::CanAssign(const Declaration* fromType) const
} }
else if (mBase->mType == DT_TYPE_FUNCTION && fromType->mType == DT_TYPE_FUNCTION) else if (mBase->mType == DT_TYPE_FUNCTION && fromType->mType == DT_TYPE_FUNCTION)
{ {
return mBase->IsSame(fromType); return mBase->IsSubType(fromType);
} }
else if (mBase->mType == DT_TYPE_VOID && fromType->mType == DT_TYPE_ASSEMBLER) else if (mBase->mType == DT_TYPE_VOID && fromType->mType == DT_TYPE_ASSEMBLER)
{ {

View File

@ -76,6 +76,7 @@ static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 33);
static const uint64 DTF_FUNC_RECURSIVE = (1ULL << 34); static const uint64 DTF_FUNC_RECURSIVE = (1ULL << 34);
static const uint64 DTF_FUNC_ANALYZING = (1ULL << 35); static const uint64 DTF_FUNC_ANALYZING = (1ULL << 35);
static const uint64 DTF_FUNC_CONSTEXPR = (1ULL << 36); static const uint64 DTF_FUNC_CONSTEXPR = (1ULL << 36);
static const uint64 DTF_FUNC_INTRSAVE = (1ULL << 37);
static const uint64 DTF_VAR_ALIASING = (1ULL << 37); static const uint64 DTF_VAR_ALIASING = (1ULL << 37);

View File

@ -18,6 +18,7 @@ enum ErrorID
EWARN_UNKNOWN_PRAGMA, EWARN_UNKNOWN_PRAGMA,
EWARN_INDEX_OUT_OF_BOUNDS, EWARN_INDEX_OUT_OF_BOUNDS,
EWARN_SYNTAX, EWARN_SYNTAX,
EWARN_NOT_INTERRUPT_SAFE,
EERR_GENERIC = 3000, EERR_GENERIC = 3000,
EERR_FILE_NOT_FOUND, EERR_FILE_NOT_FOUND,

View File

@ -159,6 +159,8 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec)
mFunctions.Push(dec); mFunctions.Push(dec);
dec->mFlags |= DTF_ANALYZED; dec->mFlags |= DTF_ANALYZED;
dec->mFlags |= DTF_FUNC_INTRSAVE;
if ((dec->mFlags & DTF_INTRINSIC) && !dec->mValue) if ((dec->mFlags & DTF_INTRINSIC) && !dec->mValue)
dec->mFlags |= DTF_FUNC_CONSTEXPR; dec->mFlags |= DTF_FUNC_CONSTEXPR;
else if (dec->mFlags & DTF_DEFINED) else if (dec->mFlags & DTF_DEFINED)
@ -325,6 +327,13 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec)
case EX_CALL: case EX_CALL:
ldec = Analyze(exp->mLeft, procDec); ldec = Analyze(exp->mLeft, procDec);
RegisterCall(procDec, ldec); RegisterCall(procDec, ldec);
if (!(GetProcFlags(ldec) & (DTF_FUNC_INTRSAVE | DTF_INTERRUPT)))
{
procDec->mFlags &= ~DTF_FUNC_INTRSAVE;
if (procDec->mFlags & DTF_INTERRUPT)
mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent->mString);
}
if (exp->mRight) if (exp->mRight)
RegisterProc(Analyze(exp->mRight, procDec)); RegisterProc(Analyze(exp->mRight, procDec));
break; break;
@ -423,6 +432,20 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec)
return TheVoidTypeDeclaration; return TheVoidTypeDeclaration;
} }
uint64 GlobalAnalyzer::GetProcFlags(Declaration* to) const
{
if (to->mType == DT_CONST_FUNCTION)
return to->mFlags;
else if (to->mType == DT_TYPE_FUNCTION)
return to->mFlags;
else if (to->mType == DT_TYPE_POINTER && to->mBase->mType == DT_TYPE_FUNCTION)
return GetProcFlags(to->mBase);
else if (to->mType == DT_VARIABLE || to->mType == DT_ARGUMENT)
return GetProcFlags(to->mBase);
else
return 0;
}
void GlobalAnalyzer::RegisterCall(Declaration* from, Declaration* to) void GlobalAnalyzer::RegisterCall(Declaration* from, Declaration* to)
{ {
if (from) if (from)

View File

@ -27,6 +27,7 @@ protected:
Declaration* Analyze(Expression* exp, Declaration* procDec); Declaration* Analyze(Expression* exp, Declaration* procDec);
uint64 GetProcFlags(Declaration* to) const;
void RegisterCall(Declaration* from, Declaration* to); void RegisterCall(Declaration* from, Declaration* to);
void RegisterProc(Declaration* to); void RegisterProc(Declaration* to);
}; };

View File

@ -2627,6 +2627,16 @@ bool InterInstruction::ConstantFolding(void)
mNumOperands = 0; mNumOperands = 0;
return true; return true;
} }
else if (mSrc[0].mTemp == mSrc[1].mTemp)
{
mCode = IC_CONSTANT;
mConst.mIntConst = ::ConstantFolding(mOperator, mSrc[0].mType, 0, 0);
mConst.mType = IT_BOOL;
mSrc[0].mTemp == -1;
mSrc[1].mTemp == -1;
mNumOperands = 0;
return true;
}
break; break;
case IC_BINARY_OPERATOR: case IC_BINARY_OPERATOR:
if (mSrc[0].mTemp < 0 && mSrc[1].mTemp < 0) if (mSrc[0].mTemp < 0 && mSrc[1].mTemp < 0)
@ -8581,6 +8591,9 @@ void InterCodeProcedure::Close(void)
ResetVisited(); ResetVisited();
mEntryBlock->CollectOuterFrame(0, size, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode); mEntryBlock->CollectOuterFrame(0, size, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode);
if (mModule->mCompilerOptions & COPT_NATIVE)
mCallsByteCode = false;
mCommonFrameSize = size; mCommonFrameSize = size;
} }
else else
@ -9074,6 +9087,7 @@ void InterCodeProcedure::RemoveNonRelevantStatics(void)
{ {
ResetVisited(); ResetVisited();
mEntryBlock->RemoveNonRelevantStatics(); mEntryBlock->RemoveNonRelevantStatics();
RemoveUnusedInstructions();
} }
void InterCodeProcedure::MapVariables(void) void InterCodeProcedure::MapVariables(void)
@ -9390,7 +9404,7 @@ void InterCodeProcedure::Disassemble(FILE* file)
void InterCodeProcedure::Disassemble(const char* name, bool dumpSets) void InterCodeProcedure::Disassemble(const char* name, bool dumpSets)
{ {
#if 0 #if 1
#ifdef _WIN32 #ifdef _WIN32
FILE* file; FILE* file;
static bool initial = true; static bool initial = true;

View File

@ -1717,9 +1717,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case EX_RELATIONAL: case EX_RELATIONAL:
{ {
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper);
vl = Dereference(proc, block, vl); vl = Dereference(proc, block, vl, vl.mType->mType == DT_TYPE_ARRAY ? 1 : 0);
vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, breakBlock, continueBlock, inlineMapper);
vr = Dereference(proc, block, vr); vr = Dereference(proc, block, vr, vr.mType->mType == DT_TYPE_ARRAY ? 1 : 0);
InterInstruction * ins = new InterInstruction(); InterInstruction * ins = new InterInstruction();

View File

@ -48,6 +48,11 @@ struct ZeroPageSet
mBits[n >> 5] |= 1 << (n & 31); mBits[n >> 5] |= 1 << (n & 31);
} }
void operator -= (int n)
{
mBits[n >> 5] &= ~(1 << (n & 31));
}
bool operator[] (int n) const bool operator[] (int n) const
{ {
return (mBits[n >> 5] & (1 << (n & 31))) != 0; return (mBits[n >> 5] & (1 << (n & 31))) != 0;

View File

@ -8214,7 +8214,7 @@ void NativeCodeBasicBlock::CallFunction(InterCodeProcedure* proc, NativeCodeProc
} }
} }
void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterInstruction* ins) void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, NativeCodeProcedure * nproc, const InterInstruction* ins)
{ {
if (ins->mCode == IC_ASSEMBLER) if (ins->mCode == IC_ASSEMBLER)
{ {
@ -8232,10 +8232,22 @@ void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterIn
ins->mSrc[0].mLinkerObject->mNumTemporaries = ins->mNumOperands - 1; ins->mSrc[0].mLinkerObject->mNumTemporaries = ins->mNumOperands - 1;
} }
assert(ins->mSrc[0].mLinkerObject); if (ins->mSrc[0].mTemp < 0)
{
assert(ins->mSrc[0].mLinkerObject);
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bcexec")));
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_FEXEC));
}
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject));
if (ins->mDst.mTemp >= 0) if (ins->mDst.mTemp >= 0)
{ {
if (ins->mDst.mType == IT_FLOAT) if (ins->mDst.mType == IT_FLOAT)
@ -8658,7 +8670,7 @@ void NativeCodeBasicBlock::CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet&
case ASMIM_ABSOLUTE: case ASMIM_ABSOLUTE:
if (mIns[i].mType == ASMIT_JSR) if (mIns[i].mType == ASMIT_JSR)
{ {
if (mIns[i].mFlags & NCIF_RUNTIME) if ((mIns[i].mFlags & NCIF_RUNTIME) && !(mIns[i].mFlags & NCIF_FEXEC))
{ {
for (int j = 0; j < 4; j++) for (int j = 0; j < 4; j++)
{ {
@ -16028,6 +16040,20 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_PHA)); mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_PHA));
} }
bool usesStack = false;
if (zpLocal[BC_REG_STACK])
{
usesStack = true;
zpLocal -= BC_REG_STACK;
zpLocal -= BC_REG_STACK + 1;
}
if (usesStack)
{
mEntryBlock->mIns.Push(NativeCodeInstruction(ASMIT_DEC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
}
for (int i = 2; i < 256; i++) for (int i = 2; i < 256; i++)
{ {
if (zpLocal[i]) if (zpLocal[i])
@ -16045,6 +16071,10 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, i)); mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, i));
} }
} }
if (usesStack)
{
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_INC, ASMIM_ZERO_PAGE, BC_REG_STACK + 1));
}
if (proc->mHardwareInterrupt) if (proc->mHardwareInterrupt)
{ {
@ -16803,7 +16833,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
break; break;
case IC_CALL_NATIVE: case IC_CALL_NATIVE:
case IC_ASSEMBLER: case IC_ASSEMBLER:
block->CallAssembler(iproc, ins); block->CallAssembler(iproc, this, ins);
break; break;
case IC_PUSH_FRAME: case IC_PUSH_FRAME:
{ {

View File

@ -181,7 +181,7 @@ public:
NativeCodeBasicBlock * CopyValue(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc); NativeCodeBasicBlock * CopyValue(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc);
NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc); NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc);
void CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins); void CallAssembler(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
void ShiftRegisterLeft(InterCodeProcedure* proc, int reg, int shift); void ShiftRegisterLeft(InterCodeProcedure* proc, int reg, int shift);

View File

@ -962,7 +962,7 @@ Declaration* Parser::ParseDeclaration(bool variable)
} }
} }
Declaration* bdec = ParseBaseTypeDeclaration(0); Declaration* bdec = ParseBaseTypeDeclaration(typeFlags);
Declaration* rdec = nullptr, * ldec = nullptr; Declaration* rdec = nullptr, * ldec = nullptr;
@ -988,6 +988,8 @@ Declaration* Parser::ParseDeclaration(bool variable)
} }
} }
if (npdec->mBase->mType == DT_TYPE_FUNCTION)
npdec->mBase->mFlags |= storageFlags & (DTF_INTERRUPT | DTF_NATIVE | TK_FASTCALL);
if (definingType) if (definingType)
{ {

View File

@ -73,7 +73,7 @@ int main2(int argc, const char** argv)
#else #else
strcpy(strProductName, "oscar64"); strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.4.89"); strcpy(strProductVersion, "1.4.90");
#ifdef __APPLE__ #ifdef __APPLE__
uint32_t length = sizeof(basePath); uint32_t length = sizeof(basePath);

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,4,89,0 FILEVERSION 1,4,90,0
PRODUCTVERSION 1,4,89,0 PRODUCTVERSION 1,4,90,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "oscar64" VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler" VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.4.89.0" VALUE "FileVersion", "1.4.90.0"
VALUE "InternalName", "oscar64.exe" VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe" VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64" VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.4.89.0" VALUE "ProductVersion", "1.4.90.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -3752,15 +3752,15 @@
{ {
"Name" = "8:Microsoft Visual Studio" "Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64" "ProductName" = "8:oscar64"
"ProductCode" = "8:{96DACD5F-2EC0-4296-9AFE-FB3F0A377D2A}" "ProductCode" = "8:{713950ED-E82C-46AE-AEE1-B7696F19319F}"
"PackageCode" = "8:{49C9E61D-9B14-437A-A945-39BFE6ED8516}" "PackageCode" = "8:{9CE6068F-14BD-457A-B770-D8A1BA054207}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0" "AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE" "RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE" "RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE" "InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.4.89" "ProductVersion" = "8:1.4.90"
"Manufacturer" = "8:oscar64" "Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:" "ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:" "ARPHELPLINK" = "8:"