mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-31 22:31:14 +00:00
Fixing #488. Still fails on for() with no condition and an increment.
This commit is contained in:
parent
1852630b16
commit
be54089089
@ -202,7 +202,7 @@ switchCase:
|
|||||||
;
|
;
|
||||||
|
|
||||||
forLoop
|
forLoop
|
||||||
: forClassicInit ';' commaExpr ';' commaExpr? #forClassic
|
: forClassicInit ';' commaExpr? ';' commaExpr? #forClassic
|
||||||
| (declType declPointer*)? NAME COLON expr RANGE expr #forRange
|
| (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
@ -1521,12 +1521,23 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
StatementLabel repeatTarget = new StatementLabel(beginJumpLabel.getRef(), StatementSource.forClassic(ctx), comments);
|
StatementLabel repeatTarget = new StatementLabel(beginJumpLabel.getRef(), StatementSource.forClassic(ctx), comments);
|
||||||
addStatement(repeatTarget);
|
addStatement(repeatTarget);
|
||||||
// Add condition
|
// 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
|
// Add jump if condition was met
|
||||||
StatementConditionalJump doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
|
Statement doJmpStmt;
|
||||||
addStatement(doJmpStmt);
|
if(conditionRvalue!=null) {
|
||||||
Statement endJmpStmt = new StatementJump(endJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
|
doJmpStmt = new StatementConditionalJump(conditionRvalue, doJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
|
||||||
addStatement(endJmpStmt);
|
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);
|
StatementLabel doJumpTarget = new StatementLabel(doJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
|
||||||
addStatement(doJumpTarget);
|
addStatement(doJumpTarget);
|
||||||
// Add body
|
// Add body
|
||||||
@ -1544,7 +1555,8 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
|||||||
addStatement(beginJmpStmt);
|
addStatement(beginJmpStmt);
|
||||||
StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
|
StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef(), StatementSource.forClassic(ctx), Comment.NO_COMMENTS);
|
||||||
addStatement(endJumpTarget);
|
addStatement(endJumpTarget);
|
||||||
addDirectives(doJmpStmt, stmtForCtx.directive());
|
if(doJmpStmt instanceof StatementConditionalJump)
|
||||||
|
addDirectives((StatementConditionalJump) doJmpStmt, stmtForCtx.directive());
|
||||||
addLoopBreakLabel(loopStack.pop(), ctx);
|
addLoopBreakLabel(loopStack.pop(), ctx);
|
||||||
scopeStack.pop();
|
scopeStack.pop();
|
||||||
return null;
|
return null;
|
||||||
|
@ -42,10 +42,15 @@ public class TestPrograms {
|
|||||||
public TestPrograms() {
|
public TestPrograms() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
//public void testForEver() throws IOException, URISyntaxException {
|
public void testForEver2() throws IOException, URISyntaxException {
|
||||||
// compileAndCompare("for-ever.c");
|
compileAndCompare("for-ever-2.c", log());
|
||||||
//}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testForEver() throws IOException, URISyntaxException {
|
||||||
|
compileAndCompare("for-ever.c");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPointerToPointerProblem() throws IOException, URISyntaxException {
|
public void testPointerToPointerProblem() throws IOException, URISyntaxException {
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
// lazyNES balloon demo
|
// 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)
|
#pragma target(nes)
|
||||||
#include "lazynes.h"
|
#include "lazynes.h"
|
||||||
|
145
src/test/kc/complex/lazynes/bubbles.c
Normal file
145
src/test/kc/complex/lazynes/bubbles.c
Normal 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;
|
||||||
|
}
|
@ -1,4 +1,7 @@
|
|||||||
// lazyNES lazyhello demo
|
// 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
|
// Ported to KickC 2020 by Jesper Gravgaard
|
||||||
// Original Source VBCC alpha 2 http://www.ibaug.de/vbcc/vbcc6502_2.zip
|
// Original Source VBCC alpha 2 http://www.ibaug.de/vbcc/vbcc6502_2.zip
|
||||||
|
@ -40,7 +40,7 @@ void lnPush(uword o, ubyte a, void* s);
|
|||||||
// updateList: Pointer to update list
|
// updateList: Pointer to update list
|
||||||
//
|
//
|
||||||
// TODO: void lnList(void* updateList);
|
// TODO: void lnList(void* updateList);
|
||||||
// TODO: enum { lfHor=64, lfVer=128, lfEnd=255 };
|
enum { lfHor=64, lfVer=128, lfEnd=255 };
|
||||||
//
|
//
|
||||||
// remarks:
|
// remarks:
|
||||||
// - The format of the update list is an array of unsigned bytes.
|
// - The format of the update list is an array of unsigned bytes.
|
||||||
|
9
src/test/kc/for-ever-2.c
Normal file
9
src/test/kc/for-ever-2.c
Normal 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
11
src/test/ref/for-ever.asm
Normal 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
|
||||||
|
}
|
8
src/test/ref/for-ever.cfg
Normal file
8
src/test/ref/for-ever.cfg
Normal 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
148
src/test/ref/for-ever.log
Normal 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
|
||||||
|
|
4
src/test/ref/for-ever.sym
Normal file
4
src/test/ref/for-ever.sym
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
(const nomodify byte*) SCREEN = (byte*) 1024
|
||||||
|
(void()) main()
|
||||||
|
(label) main::@1
|
||||||
|
|
Loading…
Reference in New Issue
Block a user