1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-24 20:32:39 +00:00

Fixing #488. Still fails on for() with no condition and an increment.

This commit is contained in:
jespergravgaard 2020-07-07 08:32:42 +02:00
parent 1852630b16
commit be54089089
14 changed files with 943 additions and 583 deletions

View File

@ -202,7 +202,7 @@ switchCase:
;
forLoop
: forClassicInit ';' commaExpr ';' commaExpr? #forClassic
: forClassicInit ';' commaExpr? ';' commaExpr? #forClassic
| (declType declPointer*)? NAME COLON expr RANGE expr #forRange
;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1521,12 +1521,23 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
StatementLabel repeatTarget = new StatementLabel(beginJumpLabel.getRef(), StatementSource.forClassic(ctx), comments);
addStatement(repeatTarget);
// Add condition
RValue rValue = addCondition(ctx.commaExpr(0), StatementSource.forClassic(ctx));
final KickCParser.CommaExprContext conditionCtx = ctx.commaExpr(0);
RValue conditionRvalue = null;
if(conditionCtx!=null) {
conditionRvalue = addCondition(conditionCtx, StatementSource.forClassic(ctx));
}
// Add jump if condition was met
StatementConditionalJump doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
addStatement(doJmpStmt);
Statement endJmpStmt = new StatementJump(endJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
addStatement(endJmpStmt);
Statement doJmpStmt;
if(conditionRvalue!=null) {
doJmpStmt = new StatementConditionalJump(conditionRvalue, doJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
addStatement(doJmpStmt);
Statement endJmpStmt = new StatementJump(endJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
addStatement(endJmpStmt);
} else {
// No condition - loop forever
doJmpStmt = new StatementJump( doJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
addStatement(doJmpStmt);
}
StatementLabel doJumpTarget = new StatementLabel(doJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
addStatement(doJumpTarget);
// Add body
@ -1544,7 +1555,8 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
addStatement(beginJmpStmt);
StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
addStatement(endJumpTarget);
addDirectives(doJmpStmt, stmtForCtx.directive());
if(doJmpStmt instanceof StatementConditionalJump)
addDirectives((StatementConditionalJump) doJmpStmt, stmtForCtx.directive());
addLoopBreakLabel(loopStack.pop(), ctx);
scopeStack.pop();
return null;

View File

@ -42,10 +42,15 @@ public class TestPrograms {
public TestPrograms() {
}
//@Test
//public void testForEver() throws IOException, URISyntaxException {
// compileAndCompare("for-ever.c");
//}
@Test
public void testForEver2() throws IOException, URISyntaxException {
compileAndCompare("for-ever-2.c", log());
}
@Test
public void testForEver() throws IOException, URISyntaxException {
compileAndCompare("for-ever.c");
}
@Test
public void testPointerToPointerProblem() throws IOException, URISyntaxException {

View File

@ -1,4 +1,10 @@
// lazyNES balloon demo
// lazyNES - As lazy as possible NES hardware support library for vbcc6502
// (happily cooperates with Shiru's famitone2 replay code)
// V1.0, 'Lazycow 2020
// Ported to KickC 2020 by Jesper Gravgaard
// Original Source VBCC alpha 2 http://www.ibaug.de/vbcc/vbcc6502_2.zip
#pragma target(nes)
#include "lazynes.h"

View File

@ -0,0 +1,145 @@
// lazyNES bubbles demo
// lazyNES - As lazy as possible NES hardware support library for vbcc6502
// (happily cooperates with Shiru's famitone2 replay code)
// V1.0, 'Lazycow 2020
// Ported to KickC 2020 by Jesper Gravgaard
// Original Source VBCC alpha 2 http://www.ibaug.de/vbcc/vbcc6502_2.zip
#pragma target(nes)
#include "lazynes.h"
enum {
F=3, // pseudo floating point shift value
maxDrawObjects=40,
dfAlive=1
};
typedef struct {
ubyte
f, // flags
s; // sprite image offset into bubbles[] table
sword
x, y; // coordinates (shifted)
sbyte
vx, vy, // velocity
ax, ay; // accelleration
} DrawObject;
DrawObject dTab[maxDrawObjects];
// print some text in the static area
//
void Print(uword offset, ubyte value) {
static ubyte b[]={0,0,10,'B','U','B','B','L','E','S',':',0,0,lfEnd};
b[0]=(offset>>8)|lfHor; b[1]=offset&255; b[11]=b[12]='0';
while (value>=10) { ++b[11]; value-=10; }
while (value>=1) { ++b[12]; value-=1; }
lnList(b);
}
//
//
int lnMain() {
static const ubyte bgColors[]={45,33,2};
static const ubyte bubblesPal[]={ 0, 37,22,5, 0, 42,26,10, 0, 33,18,3 };
static const ubyte bubbles[]={ // x-offset, y-offset, tile, palette+flags
0,0,7,0, 8,0,9,0, 128, // 16x16, red, offset 0
0,0,7,1, 8,0,9,1, 128, // 16x16, green, offset 9
0,0,7,2, 8,0,9,2, 128, // 16x16, blue, offest 18
0,4,11,0,128, // 8x8, red, offset 27
0,4,11,1,128, // 8x8, green, offset 32
0,4,11,2,128, // 8x8, blue, offset 37
},
bubbleTab[]={0,27,9,32,18,37}; // start offsets in bubbles[]
ubyte
i,
type=0,
stopIt=0,
objects=0;
uword
hScroll=0,
tics=0;
sbyte
hVel=0, hDir=1;
lnSync(lfBlank); // blank screen to enable lnPush() usage
lnPush(lnBackCol,3,bgColors); // set background colors
lnPush(lnSprPal0,3,&bubblesPal[1]); // set sprite colors
lnPush(lnSprPal1,3,&bubblesPal[5]);
lnPush(lnSprPal2,3,&bubblesPal[9]);
lnPPUCTRL|=32; // Select 8x16 sprites; has to be set after calling lnSync()!
// draw some backgrounds
{ //
static const ubyte g1[]={1}, g2[]={2,3,4,5}, g3[]={6,7,8,9};
ubyte x;
// draw a line: Sprite #0 will be placed ontop later to trigger the split
i=2; for (x=0;x<32;x+=1) lnPush(lnNameTab0+(i<<5)+x,1,g1);
// draw some diamond shapes
for (i=8;i<=24;i+=4) for (x=0;x<4;x+=1) {
lnPush(lnNameTab0+(i<<5)+12+x*4,4,g2);
lnPush(lnNameTab0+32+(i<<5)+12+x*4,4,g3);
}
}
// setup bubbles
type=0;
for (i=0;i<maxDrawObjects;i+=1) {
DrawObject* d=&dTab[i];
d->f=dfAlive;
d->s=bubbleTab[type];
type+=1; if (type>=6) type=0;
d->x=80<<F; d->vx=i; d->ax=1;
d->y=24<<F; d->vy=1<<F; d->ay=1;
}
while(1) {
DrawObject* d;
lnScroll(0,0); // reset scrolling offsets of area above split
lnScroll(hScroll>>6,32); // set scrolling offsets of area below split
hVel+=hDir; if (hVel>64 || hVel<-64) hDir=-hDir;
hScroll+=hVel;
// add 1st sprite (SPR0) at a fixed position on top of background blocks
// mandatory for the SPR0HIT check later with lnSync(lfSplit)
lnAddSpr(&bubbles[bubbleTab[5]],16,16);
lnSpr0Wait=55; // delay the set of scrolling registers a bit
// move bubbles
for (i=0,d=dTab; i<objects ;i+=1,++d) if (d->f&dfAlive) {
d->vx+=d->ax;
if (d->vx<-32) d->ax=1; else if (d->vx>32) d->ax=-1;
if (d->y>216<<F) d->vy=-1<<F; else if (d->y<24<<F) d->vy=1<<F;
d->x+=d->vx;
d->y+=d->vy;
lnAddSpr(&bubbles[d->s],d->x>>F,d->y>>F);
}
// activate new bubble?
tics+=1; if (tics>8) {
tics=0;
if (0==stopIt && objects<maxDrawObjects) objects+=1;
}
// display the amount of moving bubbles + spr0-bubble
Print(lnNameTab0+32,objects+1);
i=lnSync(lfSplit)&31; // sync with vblank, activate SPR0HIT splitscreen
// lnSync() returns the number of vblank NMI's that have been triggered
// since the last call of lnSync(). If the program code is too slow to
// move all objects in one frame (i>1), then we reduce the amount of
// objects (objects-=1) and everything moves with 60 fps again.
if (i>1 && objects>0) { objects-=1; stopIt=1; } // stop adding objects?
}
return 0;
}

View File

@ -1,4 +1,7 @@
// lazyNES lazyhello demo
// lazyNES - As lazy as possible NES hardware support library for vbcc6502
// (happily cooperates with Shiru's famitone2 replay code)
// V1.0, 'Lazycow 2020
// Ported to KickC 2020 by Jesper Gravgaard
// Original Source VBCC alpha 2 http://www.ibaug.de/vbcc/vbcc6502_2.zip

View File

@ -40,7 +40,7 @@ void lnPush(uword o, ubyte a, void* s);
// updateList: Pointer to update list
//
// TODO: void lnList(void* updateList);
// TODO: enum { lfHor=64, lfVer=128, lfEnd=255 };
enum { lfHor=64, lfVer=128, lfEnd=255 };
//
// remarks:
// - The format of the update list is an array of unsigned bytes.

9
src/test/kc/for-ever-2.c Normal file
View File

@ -0,0 +1,9 @@
// Test a for() loop that runs forever
char * const SCREEN = 0x0400;
void main() {
for (char i=0;;i++) {
SCREEN[i]++;
}
}

11
src/test/ref/for-ever.asm Normal file
View File

@ -0,0 +1,11 @@
// Test a for() loop that runs forever
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label SCREEN = $400
main: {
__b1:
// (*SCREEN)++;
inc SCREEN
jmp __b1
}

View File

@ -0,0 +1,8 @@
(void()) main()
main: scope:[main] from
[0] phi()
to:main::@1
main::@1: scope:[main] from main main::@1
[1] *((const nomodify byte*) SCREEN) ← ++ *((const nomodify byte*) SCREEN)
to:main::@1

148
src/test/ref/for-ever.log Normal file
View File

@ -0,0 +1,148 @@
CONTROL FLOW GRAPH SSA
(void()) main()
main: scope:[main] from __start
to:main::@1
main::@1: scope:[main] from main main::@1
*((const nomodify byte*) SCREEN) ← ++ *((const nomodify byte*) SCREEN)
to:main::@1
main::@return: scope:[main] from
return
to:@return
(void()) __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
(const nomodify byte*) SCREEN = (byte*)(number) $400
(void()) __start()
(label) __start::@1
(label) __start::@return
(void()) main()
(label) main::@1
(label) main::@return
Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification
Removing unused block main::@return
Successful SSA optimization Pass2EliminateUnusedBlocks
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Adding NOP phi() at start of main
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Adding NOP phi() at start of main
FINAL CONTROL FLOW GRAPH
(void()) main()
main: scope:[main] from
[0] phi()
to:main::@1
main::@1: scope:[main] from main main::@1
[1] *((const nomodify byte*) SCREEN) ← ++ *((const nomodify byte*) SCREEN)
to:main::@1
VARIABLE REGISTER WEIGHTS
(void()) main()
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Test a for() loop that runs forever
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// main
main: {
jmp __b1
// main::@1
__b1:
// [1] *((const nomodify byte*) SCREEN) ← ++ *((const nomodify byte*) SCREEN) -- _deref_pbuc1=_inc__deref_pbuc1
inc SCREEN
jmp __b1
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 120 combination
Uplifting [] best 120 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test a for() loop that runs forever
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// main
main: {
jmp __b1
// main::@1
__b1:
// [1] *((const nomodify byte*) SCREEN) ← ++ *((const nomodify byte*) SCREEN) -- _deref_pbuc1=_inc__deref_pbuc1
inc SCREEN
jmp __b1
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Succesful ASM optimization Pass5NextJumpElimination
FINAL SYMBOL TABLE
(const nomodify byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@1
FINAL ASSEMBLER
Score: 90
// File Comments
// Test a for() loop that runs forever
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
// main
main: {
// main::@1
__b1:
// (*SCREEN)++;
// [1] *((const nomodify byte*) SCREEN) ← ++ *((const nomodify byte*) SCREEN) -- _deref_pbuc1=_inc__deref_pbuc1
inc SCREEN
jmp __b1
}
// File Data

View File

@ -0,0 +1,4 @@
(const nomodify byte*) SCREEN = (byte*) 1024
(void()) main()
(label) main::@1