Add check for __interrupt attribute on function pointers call from interrupt code
This commit is contained in:
parent
fdb112a037
commit
1221649a3d
|
@ -129,6 +129,9 @@ rem @echo off
|
|||
@call :test ptrinittest.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :test ptrarraycmptest.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@exit /b 0
|
||||
|
||||
:error
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -273,7 +273,7 @@ bool Compiler::GenerateCode(void)
|
|||
}
|
||||
#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];
|
||||
|
||||
|
|
|
@ -557,6 +557,9 @@ bool Declaration::IsSubType(const Declaration* dec) const
|
|||
if (dl || dr)
|
||||
return false;
|
||||
|
||||
if ((mFlags & DTF_INTERRUPT) && !(dec->mFlags & DTF_INTERRUPT))
|
||||
return false;
|
||||
|
||||
if ((mFlags & DTF_VARIADIC) != (dec->mFlags & DTF_VARIADIC))
|
||||
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)
|
||||
{
|
||||
return mBase->IsSame(fromType);
|
||||
return mBase->IsSubType(fromType);
|
||||
}
|
||||
else if (mBase->mType == DT_TYPE_VOID && fromType->mType == DT_TYPE_ASSEMBLER)
|
||||
{
|
||||
|
|
|
@ -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_ANALYZING = (1ULL << 35);
|
||||
static const uint64 DTF_FUNC_CONSTEXPR = (1ULL << 36);
|
||||
static const uint64 DTF_FUNC_INTRSAVE = (1ULL << 37);
|
||||
|
||||
static const uint64 DTF_VAR_ALIASING = (1ULL << 37);
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ enum ErrorID
|
|||
EWARN_UNKNOWN_PRAGMA,
|
||||
EWARN_INDEX_OUT_OF_BOUNDS,
|
||||
EWARN_SYNTAX,
|
||||
EWARN_NOT_INTERRUPT_SAFE,
|
||||
|
||||
EERR_GENERIC = 3000,
|
||||
EERR_FILE_NOT_FOUND,
|
||||
|
|
|
@ -159,6 +159,8 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec)
|
|||
mFunctions.Push(dec);
|
||||
|
||||
dec->mFlags |= DTF_ANALYZED;
|
||||
dec->mFlags |= DTF_FUNC_INTRSAVE;
|
||||
|
||||
if ((dec->mFlags & DTF_INTRINSIC) && !dec->mValue)
|
||||
dec->mFlags |= DTF_FUNC_CONSTEXPR;
|
||||
else if (dec->mFlags & DTF_DEFINED)
|
||||
|
@ -325,6 +327,13 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec)
|
|||
case EX_CALL:
|
||||
ldec = Analyze(exp->mLeft, procDec);
|
||||
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)
|
||||
RegisterProc(Analyze(exp->mRight, procDec));
|
||||
break;
|
||||
|
@ -423,6 +432,20 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec)
|
|||
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)
|
||||
{
|
||||
if (from)
|
||||
|
|
|
@ -27,6 +27,7 @@ protected:
|
|||
|
||||
Declaration* Analyze(Expression* exp, Declaration* procDec);
|
||||
|
||||
uint64 GetProcFlags(Declaration* to) const;
|
||||
void RegisterCall(Declaration* from, Declaration* to);
|
||||
void RegisterProc(Declaration* to);
|
||||
};
|
||||
|
|
|
@ -2627,6 +2627,16 @@ bool InterInstruction::ConstantFolding(void)
|
|||
mNumOperands = 0;
|
||||
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;
|
||||
case IC_BINARY_OPERATOR:
|
||||
if (mSrc[0].mTemp < 0 && mSrc[1].mTemp < 0)
|
||||
|
@ -8581,6 +8591,9 @@ void InterCodeProcedure::Close(void)
|
|||
|
||||
ResetVisited();
|
||||
mEntryBlock->CollectOuterFrame(0, size, mHasDynamicStack, mHasInlineAssembler, mCallsByteCode);
|
||||
|
||||
if (mModule->mCompilerOptions & COPT_NATIVE)
|
||||
mCallsByteCode = false;
|
||||
mCommonFrameSize = size;
|
||||
}
|
||||
else
|
||||
|
@ -9074,6 +9087,7 @@ void InterCodeProcedure::RemoveNonRelevantStatics(void)
|
|||
{
|
||||
ResetVisited();
|
||||
mEntryBlock->RemoveNonRelevantStatics();
|
||||
RemoveUnusedInstructions();
|
||||
}
|
||||
|
||||
void InterCodeProcedure::MapVariables(void)
|
||||
|
@ -9390,7 +9404,7 @@ void InterCodeProcedure::Disassemble(FILE* file)
|
|||
|
||||
void InterCodeProcedure::Disassemble(const char* name, bool dumpSets)
|
||||
{
|
||||
#if 0
|
||||
#if 1
|
||||
#ifdef _WIN32
|
||||
FILE* file;
|
||||
static bool initial = true;
|
||||
|
|
|
@ -1717,9 +1717,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
|||
case EX_RELATIONAL:
|
||||
{
|
||||
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 = Dereference(proc, block, vr);
|
||||
vr = Dereference(proc, block, vr, vr.mType->mType == DT_TYPE_ARRAY ? 1 : 0);
|
||||
|
||||
InterInstruction * ins = new InterInstruction();
|
||||
|
||||
|
|
|
@ -48,6 +48,11 @@ struct ZeroPageSet
|
|||
mBits[n >> 5] |= 1 << (n & 31);
|
||||
}
|
||||
|
||||
void operator -= (int n)
|
||||
{
|
||||
mBits[n >> 5] &= ~(1 << (n & 31));
|
||||
}
|
||||
|
||||
bool operator[] (int n) const
|
||||
{
|
||||
return (mBits[n >> 5] & (1 << (n & 31))) != 0;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -8232,10 +8232,22 @@ void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, const InterIn
|
|||
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.mType == IT_FLOAT)
|
||||
|
@ -8658,7 +8670,7 @@ void NativeCodeBasicBlock::CollectZeroPageSet(ZeroPageSet& locals, ZeroPageSet&
|
|||
case ASMIM_ABSOLUTE:
|
||||
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++)
|
||||
{
|
||||
|
@ -16028,6 +16040,20 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
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++)
|
||||
{
|
||||
if (zpLocal[i])
|
||||
|
@ -16045,6 +16071,10 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
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)
|
||||
{
|
||||
|
@ -16803,7 +16833,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
|
|||
break;
|
||||
case IC_CALL_NATIVE:
|
||||
case IC_ASSEMBLER:
|
||||
block->CallAssembler(iproc, ins);
|
||||
block->CallAssembler(iproc, this, ins);
|
||||
break;
|
||||
case IC_PUSH_FRAME:
|
||||
{
|
||||
|
|
|
@ -181,7 +181,7 @@ public:
|
|||
NativeCodeBasicBlock * CopyValue(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 ShiftRegisterLeft(InterCodeProcedure* proc, int reg, int shift);
|
||||
|
|
|
@ -962,7 +962,7 @@ Declaration* Parser::ParseDeclaration(bool variable)
|
|||
}
|
||||
}
|
||||
|
||||
Declaration* bdec = ParseBaseTypeDeclaration(0);
|
||||
Declaration* bdec = ParseBaseTypeDeclaration(typeFlags);
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -73,7 +73,7 @@ int main2(int argc, const char** argv)
|
|||
|
||||
#else
|
||||
strcpy(strProductName, "oscar64");
|
||||
strcpy(strProductVersion, "1.4.89");
|
||||
strcpy(strProductVersion, "1.4.90");
|
||||
|
||||
#ifdef __APPLE__
|
||||
uint32_t length = sizeof(basePath);
|
||||
|
|
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,4,89,0
|
||||
PRODUCTVERSION 1,4,89,0
|
||||
FILEVERSION 1,4,90,0
|
||||
PRODUCTVERSION 1,4,90,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -43,12 +43,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "oscar64"
|
||||
VALUE "FileDescription", "oscar64 compiler"
|
||||
VALUE "FileVersion", "1.4.89.0"
|
||||
VALUE "FileVersion", "1.4.90.0"
|
||||
VALUE "InternalName", "oscar64.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2021"
|
||||
VALUE "OriginalFilename", "oscar64.exe"
|
||||
VALUE "ProductName", "oscar64"
|
||||
VALUE "ProductVersion", "1.4.89.0"
|
||||
VALUE "ProductVersion", "1.4.90.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -3752,15 +3752,15 @@
|
|||
{
|
||||
"Name" = "8:Microsoft Visual Studio"
|
||||
"ProductName" = "8:oscar64"
|
||||
"ProductCode" = "8:{96DACD5F-2EC0-4296-9AFE-FB3F0A377D2A}"
|
||||
"PackageCode" = "8:{49C9E61D-9B14-437A-A945-39BFE6ED8516}"
|
||||
"ProductCode" = "8:{713950ED-E82C-46AE-AEE1-B7696F19319F}"
|
||||
"PackageCode" = "8:{9CE6068F-14BD-457A-B770-D8A1BA054207}"
|
||||
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
|
||||
"AspNetVersion" = "8:2.0.50727.0"
|
||||
"RestartWWWService" = "11:FALSE"
|
||||
"RemovePreviousVersions" = "11:TRUE"
|
||||
"DetectNewerInstalledVersion" = "11:TRUE"
|
||||
"InstallAllUsers" = "11:FALSE"
|
||||
"ProductVersion" = "8:1.4.89"
|
||||
"ProductVersion" = "8:1.4.90"
|
||||
"Manufacturer" = "8:oscar64"
|
||||
"ARPHELPTELEPHONE" = "8:"
|
||||
"ARPHELPLINK" = "8:"
|
||||
|
|
Loading…
Reference in New Issue