Add __assume builtin function

This commit is contained in:
drmortalwombat 2022-01-08 15:51:17 +01:00
parent 085fba137f
commit 640007546f
13 changed files with 222 additions and 16 deletions

View File

@ -23,7 +23,7 @@ The goal is to implement the actual C standard and not some subset for performan
## Limits and Errors ## Limits and Errors
There are still several open areas, but most targets have been reached. The current Dhrystone performance is 61 iterations per second with byte code (11434) and 270 iterations with native code (12145 Bytes). There are still several open areas, but most targets have been reached. The current Dhrystone performance is 61 iterations per second with byte code (11504) and 278 iterations with native code (12184 Bytes).
### Language ### Language
@ -34,7 +34,7 @@ There are still several open areas, but most targets have been reached. The cur
### Standard Libraries ### Standard Libraries
* No file functions * No standard file functions, but CBM based file ops
### Runtime ### Runtime
@ -44,7 +44,6 @@ There are still several open areas, but most targets have been reached. The cur
### Optimizing ### Optimizing
* Complex loop optimization * Complex loop optimization
* Partial block domination analysis
* Auto variables placed on fixed stack for known call sequence * Auto variables placed on fixed stack for known call sequence
### Intermediate code generation ### Intermediate code generation
@ -54,15 +53,13 @@ There are still several open areas, but most targets have been reached. The cur
### Native code generation ### Native code generation
* More byte operation optimisation required
* Simple loop detection and optimisation not complete
## Compiler arguments ## Compiler arguments
The compiler is command line driven, and creates an executable .prg file. The compiler is command line driven, and creates an executable .prg file.
oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-e] [-n] [-dSYMBOL[=value]] {source.c} oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-e] [-n] [-dSYMBOL[=value]] {source.c}
* -v : verbose output for diagnostics
* -i : additional include paths * -i : additional include paths
* -o : optional output file name * -o : optional output file name
* -rt : alternative runtime library, replaces the crt.c * -rt : alternative runtime library, replaces the crt.c
@ -91,6 +88,8 @@ Will switch to the lowercase PETSCII font and translate the strings while printi
PETSCII string literals can also be generated using a "p" or "P" prefix such as: PETSCII string literals can also be generated using a "p" or "P" prefix such as:
printf(p"Hello World\n"); printf(p"Hello World\n");
Screen codes can be generated similar using "s" or "S" prefix.
Input from the console will also be translated accordingly. Input from the console will also be translated accordingly.
@ -113,6 +112,13 @@ A section of the file can be selected by providing a limit and or an offset into
}; };
## Language extensions for optimization
### Additional Optimizer information using __assume()
The compiler can be provided with additional information using the built in function __assume(cond). This can be useful to mark unreachable code using __assume(false) for e.g. the default of a switch statement. Another good option is to limit the value range of arguments to allow the compiler using byte operations without the need for integer promotion.
## Inline Assembler ## Inline Assembler

View File

@ -12,6 +12,8 @@ void spr_init(char * screen)
void spr_set(char sp, bool show, int xpos, int ypos, char image, char color, bool multi, bool xexpand, bool yexpand) void spr_set(char sp, bool show, int xpos, int ypos, char image, char color, bool multi, bool xexpand, bool yexpand)
{ {
__assume (sp < 8);
char m = 1 << sp; char m = 1 << sp;
if (show) if (show)
@ -47,6 +49,8 @@ void spr_set(char sp, bool show, int xpos, int ypos, char image, char color, boo
void spr_show(char sp, bool show) void spr_show(char sp, bool show)
{ {
__assume (sp < 8);
if (show) if (show)
vic.spr_enable |= 1 << sp; vic.spr_enable |= 1 << sp;
else else
@ -55,6 +59,8 @@ void spr_show(char sp, bool show)
void spr_move(char sp, int xpos, int ypos) void spr_move(char sp, int xpos, int ypos)
{ {
__assume (sp < 8);
vic.spr_pos[sp].y = ypos; vic.spr_pos[sp].y = ypos;
vic.spr_pos[sp].x = xpos & 0xff; vic.spr_pos[sp].x = xpos & 0xff;
if (xpos & 0x100) if (xpos & 0x100)
@ -65,11 +71,15 @@ void spr_move(char sp, int xpos, int ypos)
void spr_image(char sp, char image) void spr_image(char sp, char image)
{ {
__assume (sp < 8);
vspriteScreen[sp] = image; vspriteScreen[sp] = image;
} }
void spr_color(char sp, char color) void spr_color(char sp, char color)
{ {
__assume (sp < 8);
vic.spr_color[sp] = color; vic.spr_color[sp] = color;
} }

View File

@ -4250,6 +4250,9 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p
} }
return; return;
case IC_UNREACHABLE:
this->Close(proc->exitBlock, nullptr, BC_JUMPS);
return;
} }
i++; i++;

View File

@ -133,7 +133,8 @@ enum ExpressionType
EX_SWITCH, EX_SWITCH,
EX_CASE, EX_CASE,
EX_DEFAULT, EX_DEFAULT,
EX_CONDITIONAL EX_CONDITIONAL,
EX_ASSUME
}; };
class Expression class Expression

View File

@ -352,6 +352,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec)
break; break;
case EX_BREAK: case EX_BREAK:
case EX_CONTINUE: case EX_CONTINUE:
case EX_ASSUME:
break; break;
case EX_TYPE: case EX_TYPE:
break; break;

View File

@ -2501,6 +2501,9 @@ void InterInstruction::Disassemble(FILE* file)
case IC_RETURN: case IC_RETURN:
fprintf(file, "RET"); fprintf(file, "RET");
break; break;
case IC_UNREACHABLE:
fprintf(file, "UNREACHABLE");
break;
} }
static char typechars[] = "NBCILFP"; static char typechars[] = "NBCILFP";
@ -2562,6 +2565,7 @@ InterCodeBasicBlock::InterCodeBasicBlock(void)
mLoopHead = false; mLoopHead = false;
mChecked = false; mChecked = false;
mTraceIndex = -1; mTraceIndex = -1;
mUnreachable = false;
} }
InterCodeBasicBlock::~InterCodeBasicBlock(void) InterCodeBasicBlock::~InterCodeBasicBlock(void)
@ -5371,7 +5375,7 @@ bool InterCodeBasicBlock::PushSinglePathResultInstructions(void)
if (ins->mDst.mTemp >= 0 && !providedTemps[ins->mDst.mTemp] && !requiredTemps[ins->mDst.mTemp]) if (ins->mDst.mTemp >= 0 && !providedTemps[ins->mDst.mTemp] && !requiredTemps[ins->mDst.mTemp])
{ {
int j = 0; int j = 0;
while (j < ins->mNumOperands && !(ins->mSrc[j].mTemp >= 0 && providedTemps[ins->mSrc[j].mTemp]) && !IsTempModifiedOnPath(ins->mSrc[j].mTemp, i + 1)) while (j < ins->mNumOperands && (ins->mSrc[j].mTemp < 0 || !(providedTemps[ins->mSrc[j].mTemp] || IsTempModifiedOnPath(ins->mSrc[j].mTemp, i + 1))))
j++; j++;
if (j == ins->mNumOperands && IsMoveable(ins->mCode) && (ins->mCode != IC_LOAD || !hadStore)) if (j == ins->mNumOperands && IsMoveable(ins->mCode) && (ins->mCode != IC_LOAD || !hadStore))
@ -5741,6 +5745,66 @@ bool InterCodeBasicBlock::IsEqual(const InterCodeBasicBlock* block) const
return false; return false;
} }
bool InterCodeBasicBlock::DropUnreachable(void)
{
if (!mVisited)
{
mVisited = true;
int i = 0;
while (i < mInstructions.Size() && mInstructions[i]->mCode != IC_UNREACHABLE)
i++;
if (i < mInstructions.Size())
{
// kill all instructions after this
mInstructions.SetSize(i + 1);
mFalseJump = nullptr;
mTrueJump = nullptr;
if (mInstructions.Size() == 1)
mUnreachable = true;
}
else
{
if (mFalseJump)
{
if (mFalseJump->DropUnreachable())
{
mInstructions.Last()->mCode = IC_JUMP;
mInstructions.Last()->mNumOperands = 0;
mFalseJump = nullptr;
if (mTrueJump->DropUnreachable())
{
mTrueJump = nullptr;
mInstructions.SetSize(mInstructions.Size() - 1);
if (mInstructions.Size() == 0)
mUnreachable = true;
}
}
else if (mTrueJump->DropUnreachable())
{
mInstructions.Last()->mCode = IC_JUMP;
mInstructions.Last()->mNumOperands = 0;
mTrueJump = mFalseJump;
mFalseJump = nullptr;
}
}
else if (mTrueJump && mTrueJump->DropUnreachable())
{
mTrueJump = nullptr;
mInstructions.SetSize(mInstructions.Size() - 1);
if (mInstructions.Size() == 0)
mUnreachable = true;
}
}
}
return mUnreachable;
}
bool InterCodeBasicBlock::OptimizeIntervalCompare(void) bool InterCodeBasicBlock::OptimizeIntervalCompare(void)
{ {
bool changed = false; bool changed = false;
@ -7480,6 +7544,21 @@ void InterCodeProcedure::Close(void)
DisassembleDebug("Simplified range limited relational ops"); DisassembleDebug("Simplified range limited relational ops");
#endif #endif
#if 1
ResetVisited();
mEntryBlock->DropUnreachable();
ResetEntryBlocks();
ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr);
BuildDataFlowSets();
TempForwarding();
RemoveUnusedInstructions();
DisassembleDebug("Removed unreachable branches");
#endif
MapVariables(); MapVariables();
DisassembleDebug("mapped variabled"); DisassembleDebug("mapped variabled");

View File

@ -35,7 +35,8 @@ enum InterCode
IC_RETURN_STRUCT, IC_RETURN_STRUCT,
IC_RETURN, IC_RETURN,
IC_ASSEMBLER, IC_ASSEMBLER,
IC_JUMPF IC_JUMPF,
IC_UNREACHABLE
}; };
enum InterType enum InterType
@ -448,7 +449,7 @@ public:
InterCodeBasicBlock * mTrueJump, * mFalseJump, * mDominator; InterCodeBasicBlock * mTrueJump, * mFalseJump, * mDominator;
GrowingInstructionArray mInstructions; GrowingInstructionArray mInstructions;
bool mVisited, mInPath, mLoopHead, mChecked, mConditionBlockTrue; bool mVisited, mInPath, mLoopHead, mChecked, mConditionBlockTrue, mUnreachable;
NumberSet mLocalRequiredTemps, mLocalProvidedTemps; NumberSet mLocalRequiredTemps, mLocalProvidedTemps;
NumberSet mEntryRequiredTemps, mEntryProvidedTemps; NumberSet mEntryRequiredTemps, mEntryProvidedTemps;
@ -572,6 +573,8 @@ public:
void CompactInstructions(void); void CompactInstructions(void);
bool OptimizeIntervalCompare(void); bool OptimizeIntervalCompare(void);
bool DropUnreachable(void);
}; };
class InterCodeModule; class InterCodeModule;

View File

@ -2605,6 +2605,25 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
return ExValue(TheVoidTypeDeclaration); return ExValue(TheVoidTypeDeclaration);
} }
case EX_ASSUME:
{
#if 1
InterCodeBasicBlock* tblock = new InterCodeBasicBlock();
proc->Append(tblock);
InterCodeBasicBlock* fblock = new InterCodeBasicBlock();
proc->Append(fblock);
TranslateLogic(procType, proc, block, tblock, fblock, exp->mLeft, inlineMapper);
InterInstruction* ins = new InterInstruction();
ins->mCode = IC_UNREACHABLE;
fblock->Append(ins);
fblock->Close(nullptr, nullptr);
block = tblock;
#endif
return ExValue(TheVoidTypeDeclaration);
}
case EX_LOGICAL_NOT: case EX_LOGICAL_NOT:
{ {
vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, breakBlock, continueBlock, inlineMapper);

View File

@ -6447,7 +6447,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
int l = Binlog(ins->mSrc[1].mIntConst & 0xffff); int l = Binlog(ins->mSrc[1].mIntConst & 0xffff);
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); if (!ins->mSrc[0].IsUByte() || ins->mSrc[0].mRange.mMaxValue > 15)
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bitshift"))); NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bitshift")));
@ -6466,7 +6467,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); if (!ins->mSrc[0].IsUByte() || ins->mSrc[0].mRange.mMaxValue > 15)
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
if (ins->mSrc[1].mTemp < 0) if (ins->mSrc[1].mTemp < 0)
@ -6570,7 +6572,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
int l = Binlog(ins->mSrc[1].mIntConst & 0xffff); int l = Binlog(ins->mSrc[1].mIntConst & 0xffff);
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); if (!ins->mSrc[0].IsUByte() || ins->mSrc[0].mRange.mMaxValue > 15)
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bitshift"))); NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bitshift")));
@ -6586,7 +6589,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); if (!ins->mSrc[0].IsUByte() || ins->mSrc[0].mRange.mMaxValue > 15)
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
if (ins->mSrc[1].mTemp < 0) if (ins->mSrc[1].mTemp < 0)
@ -6730,7 +6734,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
int l = Binlog(ins->mSrc[1].mIntConst & 0xffff); int l = Binlog(ins->mSrc[1].mIntConst & 0xffff);
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); if (!ins->mSrc[0].IsUByte() || ins->mSrc[0].mRange.mMaxValue > 15)
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bitshift"))); NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("bitshift")));
@ -6759,7 +6764,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f)); if (!ins->mSrc[0].IsUByte() || ins->mSrc[0].mRange.mMaxValue > 15)
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0x0f));
mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ASMIT_TAX, ASMIM_IMPLIED));
if (ins->mSrc[1].mTemp < 0) if (ins->mSrc[1].mTemp < 0)
@ -9671,6 +9677,39 @@ bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at)
return false; return false;
} }
bool NativeCodeBasicBlock::MoveLoadStoreOutOfXYRangeUp(int at)
{
int j = at - 1;
while (j >= 0)
{
if (mIns[j].MayBeChangedOnAddress(mIns[at + 2]))
return false;
if (mIns[j].ChangesAddress() && mIns[j].SameEffectiveAddress(mIns[at + 1]))
return false;
if (mIns[j].mType == ASMIT_LDA)
{
if (j > 0 && (mIns[j - 1].mType == ASMIT_CLC || mIns[j - 1].mType == ASMIT_SEC))
j--;
mIns.Insert(j, mIns[at + 2]);
mIns.Insert(j, mIns[at + 2]);
if (j > 0)
{
mIns[j].mLive |= mIns[j - 1].mLive;
mIns[j + 1].mLive |= mIns[j - 1].mLive;
}
mIns.Remove(at + 3);
mIns.Remove(at + 3);
return true;
}
j--;
}
return false;
}
bool NativeCodeBasicBlock::MoveAbsoluteLoadStoreUp(int at) bool NativeCodeBasicBlock::MoveAbsoluteLoadStoreUp(int at)
{ {
int j = at - 1; int j = at - 1;
@ -11702,6 +11741,20 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
#endif #endif
#if 1
for (int i = 0; i + 2 < mIns.Size(); i++)
{
if ((mIns[i + 0].mType == ASMIT_TAX || mIns[i + 0].mType == ASMIT_TAY) &&
mIns[i + 1].mType == ASMIT_LDA && (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & (LIVE_CPU_REG_Z | LIVE_CPU_REG_A)))
{
if (MoveLoadStoreOutOfXYRangeUp(i))
changed = true;
}
}
#endif
#if 1 #if 1
if (pass > 1) if (pass > 1)
{ {
@ -13056,6 +13109,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
progress = true; progress = true;
} }
#endif #endif
#if 1
else if (
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_LDA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress != mIns[i + 2].mAddress || mIns[i + 1].mMode == ASMIM_ABSOLUTE) &&
mIns[i + 2].mType == ASMIT_CLC &&
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 3].mAddress && !(mIns[i + 3].mLive & LIVE_MEM))
{
mIns[i + 3] = mIns[i + 1];
mIns[i + 3].mType = ASMIT_ADC;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
progress = true;
}
#endif
#if 1 #if 1
else if ( else if (
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE &&
@ -14942,6 +15011,9 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
} }
return; return;
case IC_UNREACHABLE:
block->Close(mExitBlock, nullptr, ASMIT_JMP);
return;
} }
i++; i++;

View File

@ -203,6 +203,7 @@ public:
bool MoveIndirectLoadStoreUp(int at); bool MoveIndirectLoadStoreUp(int at);
bool MoveAbsoluteLoadStoreUp(int at); bool MoveAbsoluteLoadStoreUp(int at);
bool MoveLoadStoreOutOfXYRangeUp(int at);
bool MoveLoadAddImmStoreUp(int at); bool MoveLoadAddImmStoreUp(int at);
bool MoveCLCLoadAddZPStoreUp(int at); bool MoveCLCLoadAddZPStoreUp(int at);
bool MoveLoadAddZPStoreUp(int at); bool MoveLoadAddZPStoreUp(int at);

View File

@ -1920,6 +1920,13 @@ Expression* Parser::ParseStatement(void)
exp = new Expression(mScanner->mLocation, EX_VOID); exp = new Expression(mScanner->mLocation, EX_VOID);
} }
break; break;
case TK_ASSUME:
mScanner->NextToken();
exp = new Expression(mScanner->mLocation, EX_ASSUME);
exp->mLeft = ParseParenthesisExpression();
break;
default: default:
exp = ParseExpression(); exp = ParseExpression();
} }

View File

@ -47,6 +47,7 @@ const char* TokenNames[] =
"'static'", "'static'",
"'extern'", "'extern'",
"'inline'", "'inline'",
"'__assume'",
"__asm", "__asm",
@ -1222,6 +1223,8 @@ void Scanner::NextRawToken(void)
mToken = TK_INLINE; mToken = TK_INLINE;
else if (!strcmp(tkident, "__asm")) else if (!strcmp(tkident, "__asm"))
mToken = TK_ASM; mToken = TK_ASM;
else if (!strcmp(tkident, "__assume"))
mToken = TK_ASSUME;
else else
{ {
mToken = TK_IDENT; mToken = TK_IDENT;

View File

@ -45,6 +45,7 @@ enum Token
TK_STATIC, TK_STATIC,
TK_EXTERN, TK_EXTERN,
TK_INLINE, TK_INLINE,
TK_ASSUME,
TK_ASM, TK_ASM,