1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-04-07 06:37:31 +00:00

Added some hardcoded address parameter tests.

This commit is contained in:
jespergravgaard 2019-12-26 00:57:19 +01:00
parent 655dc48b7b
commit 08d268f130
19 changed files with 1678 additions and 6 deletions

View File

@ -169,7 +169,8 @@ public abstract class Scope implements Symbol, Serializable {
public Variable getVariable(String name) {
Variable symbol = (Variable) getSymbol(name);
if(symbol!=null && !symbol.isVariable()) throw new InternalError("Symbol is not a variable! "+symbol.toString());
if(symbol!=null && !symbol.isVariable())
throw new InternalError("Symbol is not a variable! "+symbol.toString());
return symbol;
}

View File

@ -6,7 +6,13 @@ import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAsm;
import dk.camelot64.kickc.model.statements.StatementKickAsm;
import dk.camelot64.kickc.model.values.*;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Symbol;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.ConstantRef;
import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.SymbolRef;
import java.util.List;
import java.util.Map;
@ -39,7 +45,7 @@ public class Pass3AssertConstants extends Pass2SsaAssertion {
throw new CompileError("Error! KickAssembler bytes is not constant " + bytes.toString(), statement);
}
RValue cycles = ((StatementKickAsm) statement).getCycles();
if(cycles!= null && !(cycles instanceof ConstantValue)) {
if(cycles != null && !(cycles instanceof ConstantValue)) {
throw new CompileError("Error! KickAssembler cycles is not constant " + cycles.toString(), statement);
}
} else if(statement instanceof StatementAsm) {
@ -47,9 +53,18 @@ public class Pass3AssertConstants extends Pass2SsaAssertion {
Map<String, SymbolRef> referenced = statementAsm.getReferenced();
for(String label : referenced.keySet()) {
SymbolRef symbolRef = referenced.get(label);
if(!(symbolRef instanceof ConstantRef) && !(symbolRef instanceof ProcedureRef)) {
Symbol symbol = getScope().getSymbol(symbolRef);
if(symbol instanceof Procedure)
// Referencing procedures are fine!
continue;
else if(symbol instanceof Variable && ((Variable) symbol).isKindConstant())
// Referencing constants are fine!
continue;
else if(symbol instanceof Variable && ((Variable) symbol).isKindLoadStore())
// Referencing load/store is fine!
continue;
else
throw new CompileError("Error! Inline ASM reference is not constant " + label, statement);
}
}
} else if(statement instanceof StatementKickAsm) {
StatementKickAsm statementAsm = (StatementKickAsm) statement;

View File

@ -276,7 +276,10 @@ public class Pass4CodeGeneration {
signature.append(param.getType().getTypeName()).append(" ");
if(allocation instanceof Registers.RegisterZpMem) {
Registers.RegisterZpMem registerZp = (Registers.RegisterZpMem) allocation;
signature.append("zeropage(").append(AsmFormat.getAsmNumber(registerZp.getZp())).append(")");
signature.append("zp(").append(AsmFormat.getAsmNumber(registerZp.getZp())).append(")");
} else if(allocation instanceof Registers.RegisterMainMem) {
Registers.RegisterMainMem registerMainMem = (Registers.RegisterMainMem) allocation;
signature.append("mem(").append(AsmFormat.getAsmNumber(registerMainMem.getAddress())).append(")");
} else if(allocation instanceof Registers.RegisterAByte) {
signature.append("register(A)");
} else if(allocation instanceof Registers.RegisterXByte) {

View File

@ -37,6 +37,21 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testRegister0() throws IOException, URISyntaxException {
compileAndCompare("register-0");
}
@Test
public void testAddress6() throws IOException, URISyntaxException {
compileAndCompare("address-6");
}
@Test
public void testAddress5() throws IOException, URISyntaxException {
compileAndCompare("address-5");
}
@Test
public void testAddress4() throws IOException, URISyntaxException {
compileAndCompare("address-4");

21
src/test/kc/address-5.kc Normal file
View File

@ -0,0 +1,21 @@
// Test declaring a variable as at a hard-coded address
// zero-page hard-coded address parameter
void main() {
print('c');
print('m');
print('l');
}
const char* SCREEN = 0x0400;
volatile char __address(0x03) idx;
void print(char __address(0x02) ch) {
asm {
ldx idx
lda ch
sta SCREEN,x
inc idx
}
}

21
src/test/kc/address-6.kc Normal file
View File

@ -0,0 +1,21 @@
// Test declaring a variable as at a hard-coded address
// mainmem-page hard-coded address parameter
void main() {
print('c');
print('m');
print('l');
}
const char* SCREEN = 0x0400;
volatile char __address(0x3000) idx;
void print(char __address(0x3001) ch) {
asm {
ldx idx
lda ch
sta SCREEN,x
inc idx
}
}

22
src/test/kc/register-0.kc Normal file
View File

@ -0,0 +1,22 @@
// Test declaring a variable as at a hard-coded register
// hard-coded register parameter
void main() {
print('c');
print('m');
print('l');
}
const char* SCREEN = 0x0400;
volatile char __address(0x03) idx;
void print(char register(A) ch) {
// Force usage of ch
kickasm(uses ch) {{ }}
asm {
ldx idx
sta SCREEN,x
inc idx
}
}

View File

@ -0,0 +1,33 @@
// Test declaring a variable as at a hard-coded address
// zero-page hard-coded address parameter
.pc = $801 "Basic"
:BasicUpstart(__b1)
.pc = $80d "Program"
.label SCREEN = $400
.label idx = 3
__b1:
lda #0
sta.z idx
jsr main
rts
main: {
lda #'c'
sta.z print.ch
jsr print
lda #'m'
sta.z print.ch
jsr print
lda #'l'
sta.z print.ch
jsr print
rts
}
// print(byte zeropage(2) ch)
print: {
.label ch = 2
ldx idx
lda ch
sta SCREEN,x
inc idx
rts
}

View File

@ -0,0 +1,37 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] (byte) idx ← (byte) 0
to:@2
@2: scope:[] from @1
[2] phi()
[3] call main
to:@end
@end: scope:[] from @2
[4] phi()
(void()) main()
main: scope:[main] from @2
[5] (byte) print::ch ← (byte) 'c'
[6] call print
to:main::@1
main::@1: scope:[main] from main
[7] (byte) print::ch ← (byte) 'm'
[8] call print
to:main::@2
main::@2: scope:[main] from main::@1
[9] (byte) print::ch ← (byte) 'l'
[10] call print
to:main::@return
main::@return: scope:[main] from main::@2
[11] return
to:@return
(void()) print((byte) print::ch)
print: scope:[print] from main main::@1 main::@2
asm { ldxidx ldach staSCREEN,x incidx }
to:print::@return
print::@return: scope:[print] from print
[13] return
to:@return

421
src/test/ref/address-5.log Normal file
View File

@ -0,0 +1,421 @@
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @2
(byte) print::ch ← (byte) 'c'
call print
to:main::@1
main::@1: scope:[main] from main
(byte) print::ch ← (byte) 'm'
call print
to:main::@2
main::@2: scope:[main] from main::@1
(byte) print::ch ← (byte) 'l'
call print
to:main::@3
main::@3: scope:[main] from main::@2
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@1: scope:[] from @begin
(byte) idx ← (byte) 0
to:@2
(void()) print((byte) print::ch)
print: scope:[print] from main main::@1 main::@2
asm { ldxidx ldach staSCREEN,x incidx }
to:print::@return
print::@return: scope:[print] from print
return
to:@return
@2: scope:[] from @1
call main
to:@3
@3: scope:[] from @2
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @3
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*)(number) $400
(byte) idx loadstore !zp[-1]:3
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(void()) print((byte) print::ch)
(label) print::@return
(byte) print::ch loadstore !zp[-1]:2
Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @3
Adding NOP phi() at start of @end
Adding NOP phi() at start of main::@3
CALL GRAPH
Calls in [] to main:3
Calls in [main] to print:7 print:9 print:11
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @3
Culled Empty Block (label) main::@3
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] (byte) idx ← (byte) 0
to:@2
@2: scope:[] from @1
[2] phi()
[3] call main
to:@end
@end: scope:[] from @2
[4] phi()
(void()) main()
main: scope:[main] from @2
[5] (byte) print::ch ← (byte) 'c'
[6] call print
to:main::@1
main::@1: scope:[main] from main
[7] (byte) print::ch ← (byte) 'm'
[8] call print
to:main::@2
main::@2: scope:[main] from main::@1
[9] (byte) print::ch ← (byte) 'l'
[10] call print
to:main::@return
main::@return: scope:[main] from main::@2
[11] return
to:@return
(void()) print((byte) print::ch)
print: scope:[print] from main main::@1 main::@2
asm { ldxidx ldach staSCREEN,x incidx }
to:print::@return
print::@return: scope:[print] from print
[13] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) idx loadstore !zp[-1]:3 0.2222222222222222
(void()) main()
(void()) print((byte) print::ch)
(byte) print::ch loadstore !zp[-1]:2 2.0
Initial phi equivalence classes
Added variable idx to live range equivalence class [ idx ]
Added variable print::ch to live range equivalence class [ print::ch ]
Complete equivalence classes
[ idx ]
[ print::ch ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Test declaring a variable as at a hard-coded address
// zero-page hard-coded address parameter
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label idx = 3
// @begin
__bbegin:
jmp __b1
// @1
__b1:
// [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z idx
// [2] phi from @1 to @2 [phi:@1->@2]
__b2_from___b1:
jmp __b2
// @2
__b2:
// [3] call main
jsr main
// [4] phi from @2 to @end [phi:@2->@end]
__bend_from___b2:
jmp __bend
// @end
__bend:
// main
main: {
// [5] (byte) print::ch ← (byte) 'c' -- vbuz1=vbuc1
lda #'c'
sta.z print.ch
// [6] call print
jsr print
jmp __b1
// main::@1
__b1:
// [7] (byte) print::ch ← (byte) 'm' -- vbuz1=vbuc1
lda #'m'
sta.z print.ch
// [8] call print
jsr print
jmp __b2
// main::@2
__b2:
// [9] (byte) print::ch ← (byte) 'l' -- vbuz1=vbuc1
lda #'l'
sta.z print.ch
// [10] call print
jsr print
jmp __breturn
// main::@return
__breturn:
// [11] return
rts
}
// print
// print(byte zeropage(2) ch)
print: {
.label ch = 2
// asm { ldxidx ldach staSCREEN,x incidx }
ldx idx
lda ch
sta SCREEN,x
inc idx
jmp __breturn
// print::@return
__breturn:
// [13] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [1] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a
Statement [5] (byte) print::ch ← (byte) 'c' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a
Statement [7] (byte) print::ch ← (byte) 'm' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a
Statement [9] (byte) print::ch ← (byte) 'l' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a
Statement asm { ldxidx ldach staSCREEN,x incidx } always clobbers reg byte a reg byte x
Potential registers zp[1]:3 [ idx ] : zp[1]:3 ,
Potential registers zp[1]:2 [ print::ch ] : zp[1]:2 ,
REGISTER UPLIFT SCOPES
Uplift Scope [print] 2: zp[1]:2 [ print::ch ]
Uplift Scope [] 0.22: zp[1]:3 [ idx ]
Uplift Scope [main]
Uplifting [print] best 123 combination zp[1]:2 [ print::ch ]
Uplifting [] best 123 combination zp[1]:3 [ idx ]
Uplifting [main] best 123 combination
Attempting to uplift remaining variables inzp[1]:2 [ print::ch ]
Uplifting [print] best 123 combination zp[1]:2 [ print::ch ]
Attempting to uplift remaining variables inzp[1]:3 [ idx ]
Uplifting [] best 123 combination zp[1]:3 [ idx ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test declaring a variable as at a hard-coded address
// zero-page hard-coded address parameter
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label idx = 3
// @begin
__bbegin:
jmp __b1
// @1
__b1:
// [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z idx
// [2] phi from @1 to @2 [phi:@1->@2]
__b2_from___b1:
jmp __b2
// @2
__b2:
// [3] call main
jsr main
// [4] phi from @2 to @end [phi:@2->@end]
__bend_from___b2:
jmp __bend
// @end
__bend:
// main
main: {
// [5] (byte) print::ch ← (byte) 'c' -- vbuz1=vbuc1
lda #'c'
sta.z print.ch
// [6] call print
jsr print
jmp __b1
// main::@1
__b1:
// [7] (byte) print::ch ← (byte) 'm' -- vbuz1=vbuc1
lda #'m'
sta.z print.ch
// [8] call print
jsr print
jmp __b2
// main::@2
__b2:
// [9] (byte) print::ch ← (byte) 'l' -- vbuz1=vbuc1
lda #'l'
sta.z print.ch
// [10] call print
jsr print
jmp __breturn
// main::@return
__breturn:
// [11] return
rts
}
// print
// print(byte zeropage(2) ch)
print: {
.label ch = 2
// asm { ldxidx ldach staSCREEN,x incidx }
ldx idx
lda ch
sta SCREEN,x
inc idx
jmp __breturn
// print::@return
__breturn:
// [13] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b2_from___b1:
Removing instruction __bend_from___b2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b2:
Removing instruction __bend:
Removing instruction __b1:
Removing instruction __b2:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
FINAL SYMBOL TABLE
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte) idx loadstore !zp[-1]:3 zp[1]:3 0.2222222222222222
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(void()) print((byte) print::ch)
(label) print::@return
(byte) print::ch loadstore !zp[-1]:2 zp[1]:2 2.0
zp[1]:3 [ idx ]
zp[1]:2 [ print::ch ]
FINAL ASSEMBLER
Score: 81
// File Comments
// Test declaring a variable as at a hard-coded address
// zero-page hard-coded address parameter
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__b1)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label idx = 3
// @begin
// @1
__b1:
// idx
// [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z idx
// [2] phi from @1 to @2 [phi:@1->@2]
// @2
// [3] call main
jsr main
rts
// [4] phi from @2 to @end [phi:@2->@end]
// @end
// main
main: {
// print('c')
// [5] (byte) print::ch ← (byte) 'c' -- vbuz1=vbuc1
lda #'c'
sta.z print.ch
// [6] call print
jsr print
// main::@1
// print('m')
// [7] (byte) print::ch ← (byte) 'm' -- vbuz1=vbuc1
lda #'m'
sta.z print.ch
// [8] call print
jsr print
// main::@2
// print('l')
// [9] (byte) print::ch ← (byte) 'l' -- vbuz1=vbuc1
lda #'l'
sta.z print.ch
// [10] call print
jsr print
// main::@return
// }
// [11] return
rts
}
// print
// print(byte zeropage(2) ch)
print: {
.label ch = 2
// asm
// asm { ldxidx ldach staSCREEN,x incidx }
ldx idx
lda ch
sta SCREEN,x
inc idx
// print::@return
// }
// [13] return
rts
}
// File Data

View File

@ -0,0 +1,16 @@
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte) idx loadstore !zp[-1]:3 zp[1]:3 0.2222222222222222
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(void()) print((byte) print::ch)
(label) print::@return
(byte) print::ch loadstore !zp[-1]:2 zp[1]:2 2.0
zp[1]:3 [ idx ]
zp[1]:2 [ print::ch ]

View File

@ -0,0 +1,33 @@
// Test declaring a variable as at a hard-coded address
// mainmem-page hard-coded address parameter
.pc = $801 "Basic"
:BasicUpstart(__b1)
.pc = $80d "Program"
.label SCREEN = $400
.label idx = $3000
__b1:
lda #0
sta idx
jsr main
rts
main: {
lda #'c'
sta print.ch
jsr print
lda #'m'
sta print.ch
jsr print
lda #'l'
sta print.ch
jsr print
rts
}
// print(byte mem($3001) ch)
print: {
.label ch = $3001
ldx idx
lda ch
sta SCREEN,x
inc idx
rts
}

View File

@ -0,0 +1,37 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] (byte) idx ← (byte) 0
to:@2
@2: scope:[] from @1
[2] phi()
[3] call main
to:@end
@end: scope:[] from @2
[4] phi()
(void()) main()
main: scope:[main] from @2
[5] (byte) print::ch ← (byte) 'c'
[6] call print
to:main::@1
main::@1: scope:[main] from main
[7] (byte) print::ch ← (byte) 'm'
[8] call print
to:main::@2
main::@2: scope:[main] from main::@1
[9] (byte) print::ch ← (byte) 'l'
[10] call print
to:main::@return
main::@return: scope:[main] from main::@2
[11] return
to:@return
(void()) print((byte) print::ch)
print: scope:[print] from main main::@1 main::@2
asm { ldxidx ldach staSCREEN,x incidx }
to:print::@return
print::@return: scope:[print] from print
[13] return
to:@return

421
src/test/ref/address-6.log Normal file
View File

@ -0,0 +1,421 @@
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @2
(byte) print::ch ← (byte) 'c'
call print
to:main::@1
main::@1: scope:[main] from main
(byte) print::ch ← (byte) 'm'
call print
to:main::@2
main::@2: scope:[main] from main::@1
(byte) print::ch ← (byte) 'l'
call print
to:main::@3
main::@3: scope:[main] from main::@2
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@1: scope:[] from @begin
(byte) idx ← (byte) 0
to:@2
(void()) print((byte) print::ch)
print: scope:[print] from main main::@1 main::@2
asm { ldxidx ldach staSCREEN,x incidx }
to:print::@return
print::@return: scope:[print] from print
return
to:@return
@2: scope:[] from @1
call main
to:@3
@3: scope:[] from @2
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @3
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*)(number) $400
(byte) idx loadstore !mem[-1]:12288
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(void()) print((byte) print::ch)
(label) print::@return
(byte) print::ch loadstore !mem[-1]:12289
Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @3
Adding NOP phi() at start of @end
Adding NOP phi() at start of main::@3
CALL GRAPH
Calls in [] to main:3
Calls in [main] to print:7 print:9 print:11
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) @3
Culled Empty Block (label) main::@3
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] (byte) idx ← (byte) 0
to:@2
@2: scope:[] from @1
[2] phi()
[3] call main
to:@end
@end: scope:[] from @2
[4] phi()
(void()) main()
main: scope:[main] from @2
[5] (byte) print::ch ← (byte) 'c'
[6] call print
to:main::@1
main::@1: scope:[main] from main
[7] (byte) print::ch ← (byte) 'm'
[8] call print
to:main::@2
main::@2: scope:[main] from main::@1
[9] (byte) print::ch ← (byte) 'l'
[10] call print
to:main::@return
main::@return: scope:[main] from main::@2
[11] return
to:@return
(void()) print((byte) print::ch)
print: scope:[print] from main main::@1 main::@2
asm { ldxidx ldach staSCREEN,x incidx }
to:print::@return
print::@return: scope:[print] from print
[13] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) idx loadstore !mem[-1]:12288 0.2222222222222222
(void()) main()
(void()) print((byte) print::ch)
(byte) print::ch loadstore !mem[-1]:12289 2.0
Initial phi equivalence classes
Added variable idx to live range equivalence class [ idx ]
Added variable print::ch to live range equivalence class [ print::ch ]
Complete equivalence classes
[ idx ]
[ print::ch ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Test declaring a variable as at a hard-coded address
// mainmem-page hard-coded address parameter
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label idx = $3000
// @begin
__bbegin:
jmp __b1
// @1
__b1:
// [1] (byte) idx ← (byte) 0 -- vbum1=vbuc1
lda #0
sta idx
// [2] phi from @1 to @2 [phi:@1->@2]
__b2_from___b1:
jmp __b2
// @2
__b2:
// [3] call main
jsr main
// [4] phi from @2 to @end [phi:@2->@end]
__bend_from___b2:
jmp __bend
// @end
__bend:
// main
main: {
// [5] (byte) print::ch ← (byte) 'c' -- vbum1=vbuc1
lda #'c'
sta print.ch
// [6] call print
jsr print
jmp __b1
// main::@1
__b1:
// [7] (byte) print::ch ← (byte) 'm' -- vbum1=vbuc1
lda #'m'
sta print.ch
// [8] call print
jsr print
jmp __b2
// main::@2
__b2:
// [9] (byte) print::ch ← (byte) 'l' -- vbum1=vbuc1
lda #'l'
sta print.ch
// [10] call print
jsr print
jmp __breturn
// main::@return
__breturn:
// [11] return
rts
}
// print
// print(byte mem($3001) ch)
print: {
.label ch = $3001
// asm { ldxidx ldach staSCREEN,x incidx }
ldx idx
lda ch
sta SCREEN,x
inc idx
jmp __breturn
// print::@return
__breturn:
// [13] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [1] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a
Statement [5] (byte) print::ch ← (byte) 'c' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a
Statement [7] (byte) print::ch ← (byte) 'm' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a
Statement [9] (byte) print::ch ← (byte) 'l' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a
Statement asm { ldxidx ldach staSCREEN,x incidx } always clobbers reg byte a reg byte x
Potential registers mem[1]:12288 [ idx ] : mem[1]:12288 ,
Potential registers mem[1]:12289 [ print::ch ] : mem[1]:12289 ,
REGISTER UPLIFT SCOPES
Uplift Scope [print] 2: mem[1]:12289 [ print::ch ]
Uplift Scope [] 0.22: mem[1]:12288 [ idx ]
Uplift Scope [main]
Uplifting [print] best 127 combination mem[1]:12289 [ print::ch ]
Uplifting [] best 127 combination mem[1]:12288 [ idx ]
Uplifting [main] best 127 combination
Attempting to uplift remaining variables inmem[1]:12289 [ print::ch ]
Uplifting [print] best 127 combination mem[1]:12289 [ print::ch ]
Attempting to uplift remaining variables inmem[1]:12288 [ idx ]
Uplifting [] best 127 combination mem[1]:12288 [ idx ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test declaring a variable as at a hard-coded address
// mainmem-page hard-coded address parameter
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label idx = $3000
// @begin
__bbegin:
jmp __b1
// @1
__b1:
// [1] (byte) idx ← (byte) 0 -- vbum1=vbuc1
lda #0
sta idx
// [2] phi from @1 to @2 [phi:@1->@2]
__b2_from___b1:
jmp __b2
// @2
__b2:
// [3] call main
jsr main
// [4] phi from @2 to @end [phi:@2->@end]
__bend_from___b2:
jmp __bend
// @end
__bend:
// main
main: {
// [5] (byte) print::ch ← (byte) 'c' -- vbum1=vbuc1
lda #'c'
sta print.ch
// [6] call print
jsr print
jmp __b1
// main::@1
__b1:
// [7] (byte) print::ch ← (byte) 'm' -- vbum1=vbuc1
lda #'m'
sta print.ch
// [8] call print
jsr print
jmp __b2
// main::@2
__b2:
// [9] (byte) print::ch ← (byte) 'l' -- vbum1=vbuc1
lda #'l'
sta print.ch
// [10] call print
jsr print
jmp __breturn
// main::@return
__breturn:
// [11] return
rts
}
// print
// print(byte mem($3001) ch)
print: {
.label ch = $3001
// asm { ldxidx ldach staSCREEN,x incidx }
ldx idx
lda ch
sta SCREEN,x
inc idx
jmp __breturn
// print::@return
__breturn:
// [13] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b2_from___b1:
Removing instruction __bend_from___b2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b2:
Removing instruction __bend:
Removing instruction __b1:
Removing instruction __b2:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
FINAL SYMBOL TABLE
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte) idx loadstore !mem[-1]:12288 mem[1]:12288 0.2222222222222222
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(void()) print((byte) print::ch)
(label) print::@return
(byte) print::ch loadstore !mem[-1]:12289 mem[1]:12289 2.0
mem[1]:12288 [ idx ]
mem[1]:12289 [ print::ch ]
FINAL ASSEMBLER
Score: 85
// File Comments
// Test declaring a variable as at a hard-coded address
// mainmem-page hard-coded address parameter
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__b1)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label idx = $3000
// @begin
// @1
__b1:
// idx
// [1] (byte) idx ← (byte) 0 -- vbum1=vbuc1
lda #0
sta idx
// [2] phi from @1 to @2 [phi:@1->@2]
// @2
// [3] call main
jsr main
rts
// [4] phi from @2 to @end [phi:@2->@end]
// @end
// main
main: {
// print('c')
// [5] (byte) print::ch ← (byte) 'c' -- vbum1=vbuc1
lda #'c'
sta print.ch
// [6] call print
jsr print
// main::@1
// print('m')
// [7] (byte) print::ch ← (byte) 'm' -- vbum1=vbuc1
lda #'m'
sta print.ch
// [8] call print
jsr print
// main::@2
// print('l')
// [9] (byte) print::ch ← (byte) 'l' -- vbum1=vbuc1
lda #'l'
sta print.ch
// [10] call print
jsr print
// main::@return
// }
// [11] return
rts
}
// print
// print(byte mem($3001) ch)
print: {
.label ch = $3001
// asm
// asm { ldxidx ldach staSCREEN,x incidx }
ldx idx
lda ch
sta SCREEN,x
inc idx
// print::@return
// }
// [13] return
rts
}
// File Data

View File

@ -0,0 +1,16 @@
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte) idx loadstore !mem[-1]:12288 mem[1]:12288 0.2222222222222222
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(void()) print((byte) print::ch)
(label) print::@return
(byte) print::ch loadstore !mem[-1]:12289 mem[1]:12289 2.0
mem[1]:12288 [ idx ]
mem[1]:12289 [ print::ch ]

View File

@ -0,0 +1,30 @@
// Test declaring a variable as at a hard-coded register
// hard-coded register parameter
.pc = $801 "Basic"
:BasicUpstart(__b1)
.pc = $80d "Program"
.label SCREEN = $400
.label idx = 3
__b1:
lda #0
sta.z idx
jsr main
rts
main: {
lda #'c'
jsr print
lda #'m'
jsr print
lda #'l'
jsr print
rts
}
// print(byte register(A) ch)
print: {
// Force usage of ch
ldx idx
sta SCREEN,x
inc idx
rts
}

View File

@ -0,0 +1,39 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] (byte) idx ← (byte) 0
to:@2
@2: scope:[] from @1
[2] phi()
[3] call main
to:@end
@end: scope:[] from @2
[4] phi()
(void()) main()
main: scope:[main] from @2
[5] phi()
[6] call print
to:main::@1
main::@1: scope:[main] from main
[7] phi()
[8] call print
to:main::@2
main::@2: scope:[main] from main::@1
[9] phi()
[10] call print
to:main::@return
main::@return: scope:[main] from main::@2
[11] return
to:@return
(void()) print((byte) print::ch)
print: scope:[print] from main main::@1 main::@2
[12] (byte) print::ch#3 ← phi( main/(byte) 'c' main::@1/(byte) 'm' main::@2/(byte) 'l' )
kickasm( uses print::ch#3) {{ }}
asm { ldxidx staSCREEN,x incidx }
to:print::@return
print::@return: scope:[print] from print
[15] return
to:@return

474
src/test/ref/register-0.log Normal file
View File

@ -0,0 +1,474 @@
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
(void()) main()
main: scope:[main] from @2
(byte) print::ch#0 ← (byte) 'c'
call print
to:main::@1
main::@1: scope:[main] from main
(byte) print::ch#1 ← (byte) 'm'
call print
to:main::@2
main::@2: scope:[main] from main::@1
(byte) print::ch#2 ← (byte) 'l'
call print
to:main::@3
main::@3: scope:[main] from main::@2
to:main::@return
main::@return: scope:[main] from main::@3
return
to:@return
@1: scope:[] from @begin
(byte) idx ← (byte) 0
to:@2
(void()) print((byte) print::ch)
print: scope:[print] from main main::@1 main::@2
(byte) print::ch#3 ← phi( main/(byte) print::ch#0 main::@1/(byte) print::ch#1 main::@2/(byte) print::ch#2 )
kickasm( uses print::ch#3) {{ }}
asm { ldxidx staSCREEN,x incidx }
to:print::@return
print::@return: scope:[print] from print
return
to:@return
@2: scope:[] from @1
call main
to:@3
@3: scope:[] from @2
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @3
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*)(number) $400
(byte) idx loadstore !zp[-1]:3
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(void()) print((byte) print::ch)
(label) print::@return
(byte) print::ch !reg byte a
(byte) print::ch#0 !reg byte a
(byte) print::ch#1 !reg byte a
(byte) print::ch#2 !reg byte a
(byte) print::ch#3 !reg byte a
Simplifying constant pointer cast (byte*) 1024
Successful SSA optimization PassNCastSimplification
Constant (const byte) print::ch#0 = 'c'
Constant (const byte) print::ch#1 = 'm'
Constant (const byte) print::ch#2 = 'l'
Successful SSA optimization Pass2ConstantIdentification
Inlining constant with var siblings (const byte) print::ch#0
Inlining constant with var siblings (const byte) print::ch#1
Inlining constant with var siblings (const byte) print::ch#2
Constant inlined print::ch#2 = (byte) 'l'
Constant inlined print::ch#1 = (byte) 'm'
Constant inlined print::ch#0 = (byte) 'c'
Successful SSA optimization Pass2ConstantInlining
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @3
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::@1
Adding NOP phi() at start of main::@2
Adding NOP phi() at start of main::@3
CALL GRAPH
Calls in [] to main:3
Calls in [main] to print:7 print:9 print:11
Created 1 initial phi equivalence classes
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @3
Culled Empty Block (label) main::@3
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @2
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::@1
Adding NOP phi() at start of main::@2
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] (byte) idx ← (byte) 0
to:@2
@2: scope:[] from @1
[2] phi()
[3] call main
to:@end
@end: scope:[] from @2
[4] phi()
(void()) main()
main: scope:[main] from @2
[5] phi()
[6] call print
to:main::@1
main::@1: scope:[main] from main
[7] phi()
[8] call print
to:main::@2
main::@2: scope:[main] from main::@1
[9] phi()
[10] call print
to:main::@return
main::@return: scope:[main] from main::@2
[11] return
to:@return
(void()) print((byte) print::ch)
print: scope:[print] from main main::@1 main::@2
[12] (byte) print::ch#3 ← phi( main/(byte) 'c' main::@1/(byte) 'm' main::@2/(byte) 'l' )
kickasm( uses print::ch#3) {{ }}
asm { ldxidx staSCREEN,x incidx }
to:print::@return
print::@return: scope:[print] from print
[15] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) idx loadstore !zp[-1]:3 0.18181818181818182
(void()) main()
(void()) print((byte) print::ch)
(byte) print::ch !reg byte a
(byte) print::ch#3 !reg byte a
Initial phi equivalence classes
[ print::ch#3 ]
Added variable idx to live range equivalence class [ idx ]
Complete equivalence classes
[ print::ch#3 ]
[ idx ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Test declaring a variable as at a hard-coded register
// hard-coded register parameter
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label idx = 3
// @begin
__bbegin:
jmp __b1
// @1
__b1:
// [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z idx
// [2] phi from @1 to @2 [phi:@1->@2]
__b2_from___b1:
jmp __b2
// @2
__b2:
// [3] call main
// [5] phi from @2 to main [phi:@2->main]
main_from___b2:
jsr main
// [4] phi from @2 to @end [phi:@2->@end]
__bend_from___b2:
jmp __bend
// @end
__bend:
// main
main: {
// [6] call print
// [12] phi from main to print [phi:main->print]
print_from_main:
// [12] phi (byte) print::ch#3 = (byte) 'c' [phi:main->print#0] -- vbuaa=vbuc1
lda #'c'
jsr print
// [7] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main:
jmp __b1
// main::@1
__b1:
// [8] call print
// [12] phi from main::@1 to print [phi:main::@1->print]
print_from___b1:
// [12] phi (byte) print::ch#3 = (byte) 'm' [phi:main::@1->print#0] -- vbuaa=vbuc1
lda #'m'
jsr print
// [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
__b2_from___b1:
jmp __b2
// main::@2
__b2:
// [10] call print
// [12] phi from main::@2 to print [phi:main::@2->print]
print_from___b2:
// [12] phi (byte) print::ch#3 = (byte) 'l' [phi:main::@2->print#0] -- vbuaa=vbuc1
lda #'l'
jsr print
jmp __breturn
// main::@return
__breturn:
// [11] return
rts
}
// print
// print(byte register(A) ch)
print: {
// kickasm( uses print::ch#3) {{ }}
// Force usage of ch
// asm { ldxidx staSCREEN,x incidx }
ldx idx
sta SCREEN,x
inc idx
jmp __breturn
// print::@return
__breturn:
// [15] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [1] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a
Statement asm { ldxidx staSCREEN,x incidx } always clobbers reg byte x
Potential registers reg byte a [ print::ch#3 ] : reg byte a ,
Potential registers zp[1]:3 [ idx ] : zp[1]:3 ,
REGISTER UPLIFT SCOPES
Uplift Scope [] 0.18: zp[1]:3 [ idx ]
Uplift Scope [main]
Uplift Scope [print] 0: reg byte a [ print::ch#3 ]
Uplifting [] best 366 combination zp[1]:3 [ idx ]
Uplifting [main] best 366 combination
Uplifting [print] best 366 combination reg byte a [ print::ch#3 ]
Attempting to uplift remaining variables inzp[1]:3 [ idx ]
Uplifting [] best 366 combination zp[1]:3 [ idx ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Test declaring a variable as at a hard-coded register
// hard-coded register parameter
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label idx = 3
// @begin
__bbegin:
jmp __b1
// @1
__b1:
// [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z idx
// [2] phi from @1 to @2 [phi:@1->@2]
__b2_from___b1:
jmp __b2
// @2
__b2:
// [3] call main
// [5] phi from @2 to main [phi:@2->main]
main_from___b2:
jsr main
// [4] phi from @2 to @end [phi:@2->@end]
__bend_from___b2:
jmp __bend
// @end
__bend:
// main
main: {
// [6] call print
// [12] phi from main to print [phi:main->print]
print_from_main:
// [12] phi (byte) print::ch#3 = (byte) 'c' [phi:main->print#0] -- vbuaa=vbuc1
lda #'c'
jsr print
// [7] phi from main to main::@1 [phi:main->main::@1]
__b1_from_main:
jmp __b1
// main::@1
__b1:
// [8] call print
// [12] phi from main::@1 to print [phi:main::@1->print]
print_from___b1:
// [12] phi (byte) print::ch#3 = (byte) 'm' [phi:main::@1->print#0] -- vbuaa=vbuc1
lda #'m'
jsr print
// [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
__b2_from___b1:
jmp __b2
// main::@2
__b2:
// [10] call print
// [12] phi from main::@2 to print [phi:main::@2->print]
print_from___b2:
// [12] phi (byte) print::ch#3 = (byte) 'l' [phi:main::@2->print#0] -- vbuaa=vbuc1
lda #'l'
jsr print
jmp __breturn
// main::@return
__breturn:
// [11] return
rts
}
// print
// print(byte register(A) ch)
print: {
// kickasm( uses print::ch#3) {{ }}
// Force usage of ch
// asm { ldxidx staSCREEN,x incidx }
ldx idx
sta SCREEN,x
inc idx
jmp __breturn
// print::@return
__breturn:
// [15] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __bend
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label __bbegin with __b1
Removing instruction __bbegin:
Removing instruction __b2_from___b1:
Removing instruction main_from___b2:
Removing instruction __bend_from___b2:
Removing instruction __b1_from_main:
Removing instruction print_from___b1:
Removing instruction __b2_from___b1:
Removing instruction print_from___b2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b2:
Removing instruction __bend:
Removing instruction print_from_main:
Removing instruction __b1:
Removing instruction __b2:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Adding RTS to root block
Succesful ASM optimization Pass5AddMainRts
FINAL SYMBOL TABLE
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte) idx loadstore !zp[-1]:3 zp[1]:3 0.18181818181818182
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(void()) print((byte) print::ch)
(label) print::@return
(byte) print::ch !reg byte a
(byte) print::ch#3 !reg byte a
reg byte a [ print::ch#3 ]
zp[1]:3 [ idx ]
FINAL ASSEMBLER
Score: 324
// File Comments
// Test declaring a variable as at a hard-coded register
// hard-coded register parameter
// Upstart
.pc = $801 "Basic"
:BasicUpstart(__b1)
.pc = $80d "Program"
// Global Constants & labels
.label SCREEN = $400
.label idx = 3
// @begin
// @1
__b1:
// idx
// [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1
lda #0
sta.z idx
// [2] phi from @1 to @2 [phi:@1->@2]
// @2
// [3] call main
// [5] phi from @2 to main [phi:@2->main]
jsr main
rts
// [4] phi from @2 to @end [phi:@2->@end]
// @end
// main
main: {
// print('c')
// [6] call print
// [12] phi from main to print [phi:main->print]
// [12] phi (byte) print::ch#3 = (byte) 'c' [phi:main->print#0] -- vbuaa=vbuc1
lda #'c'
jsr print
// [7] phi from main to main::@1 [phi:main->main::@1]
// main::@1
// print('m')
// [8] call print
// [12] phi from main::@1 to print [phi:main::@1->print]
// [12] phi (byte) print::ch#3 = (byte) 'm' [phi:main::@1->print#0] -- vbuaa=vbuc1
lda #'m'
jsr print
// [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
// main::@2
// print('l')
// [10] call print
// [12] phi from main::@2 to print [phi:main::@2->print]
// [12] phi (byte) print::ch#3 = (byte) 'l' [phi:main::@2->print#0] -- vbuaa=vbuc1
lda #'l'
jsr print
// main::@return
// }
// [11] return
rts
}
// print
// print(byte register(A) ch)
print: {
// kickasm
// kickasm( uses print::ch#3) {{ }}
// Force usage of ch
// asm
// asm { ldxidx staSCREEN,x incidx }
ldx idx
sta SCREEN,x
inc idx
// print::@return
// }
// [15] return
rts
}
// File Data

View File

@ -0,0 +1,17 @@
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte*) SCREEN = (byte*) 1024
(byte) idx loadstore !zp[-1]:3 zp[1]:3 0.18181818181818182
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(void()) print((byte) print::ch)
(label) print::@return
(byte) print::ch !reg byte a
(byte) print::ch#3 !reg byte a
reg byte a [ print::ch#3 ]
zp[1]:3 [ idx ]