mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-08 14:37:40 +00:00
Fixed multi-output of comments.
This commit is contained in:
parent
3b87c1a7c5
commit
d217113afb
src
main/java/dk/camelot64/kickc/passes
test
@ -63,10 +63,11 @@ public class Pass1CallStack extends Pass2SsaOptimization {
|
||||
ProcedureRef procedureRef = call.getProcedure();
|
||||
Procedure procedure = getScope().getProcedure(procedureRef);
|
||||
if(Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
|
||||
boolean hasPrepare = (call.getParameters().size() > 0) || !SymbolType.VOID.equals(procedure.getReturnType());
|
||||
stmtIt.remove();
|
||||
stmtIt.add(new StatementCallPrepare(procedureRef, call.getParameters(), call.getSource(), call.getComments()));
|
||||
stmtIt.add(new StatementCallExecute(procedureRef, call.getSource(), call.getComments()));
|
||||
stmtIt.add(new StatementCallFinalize(call.getlValue(), procedureRef, call.getSource(), call.getComments()));
|
||||
stmtIt.add(new StatementCallPrepare(procedureRef, call.getParameters(), call.getSource(), hasPrepare?call.getComments():Comment.NO_COMMENTS));
|
||||
stmtIt.add(new StatementCallExecute(procedureRef, call.getSource(), hasPrepare?Comment.NO_COMMENTS:call.getComments()));
|
||||
stmtIt.add(new StatementCallFinalize(call.getlValue(), procedureRef, call.getSource(), Comment.NO_COMMENTS));
|
||||
getLog().append("Calling convention " + Procedure.CallingConvention.STACK_CALL + " adding prepare/execute/finalize for " + call.toString(getProgram(), false));
|
||||
}
|
||||
}
|
||||
@ -154,12 +155,14 @@ public class Pass1CallStack extends Pass2SsaOptimization {
|
||||
if(Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
|
||||
stmtIt.previous();
|
||||
final StatementSource source = call.getSource();
|
||||
final List<Comment> comments = call.getComments();
|
||||
List<Comment> comments = call.getComments();
|
||||
final List<Variable> parameterDefs = procedure.getParameters();
|
||||
for(int i=0;i<parameterDefs.size();i++) {
|
||||
final RValue parameterVal = call.getParameters().get(i);
|
||||
final Variable parameterDef = parameterDefs.get(i);
|
||||
generateStackPushValues(parameterVal, parameterDef.getType(), statement.getSource(), statement.getComments(), stmtIt);
|
||||
generateStackPushValues(parameterVal, parameterDef.getType(), source, comments, stmtIt);
|
||||
// Clear comments - enduring they are only output once
|
||||
comments = Comment.NO_COMMENTS;
|
||||
}
|
||||
// Push additional bytes for padding if needed
|
||||
long stackFrameByteSize = CallingConventionStack.getStackFrameByteSize(procedure);
|
||||
@ -264,6 +267,8 @@ public class Pass1CallStack extends Pass2SsaOptimization {
|
||||
final Variable memberVar = memberVars.get(i);
|
||||
final RValue memberValue = memberValues.get(i);
|
||||
generateStackPushValues(memberValue, memberVar.getType(), source, comments, stmtIt);
|
||||
// Clear comments ensuring they are only output once
|
||||
comments = Comment.NO_COMMENTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -279,6 +279,11 @@ public class TestPrograms {
|
||||
compileAndCompare("declared-memory-var-0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcedureCallingConventionStack12() throws IOException, URISyntaxException {
|
||||
compileAndCompare("procedure-callingconvention-stack-12");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcedureCallingConventionStack11() throws IOException, URISyntaxException {
|
||||
compileAndCompare("procedure-callingconvention-stack-11");
|
||||
|
28
src/test/kc/procedure-callingconvention-stack-12.kc
Normal file
28
src/test/kc/procedure-callingconvention-stack-12.kc
Normal file
@ -0,0 +1,28 @@
|
||||
// Test a procedure with calling convention stack
|
||||
// Test that comments are handled correctly
|
||||
|
||||
#pragma calling(__stackcall)
|
||||
#pragma var_model(ma_zp)
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
char idx = 0;
|
||||
|
||||
void main(void) {
|
||||
// Print "hello"
|
||||
print("hello", 1);
|
||||
// Print "world"
|
||||
print("world", 2);
|
||||
}
|
||||
|
||||
void print(char* str, char spacing) {
|
||||
while(*str) {
|
||||
SCREEN[idx++] = *(str++);
|
||||
for(char c=0;c<spacing;c++)
|
||||
SCREEN[idx++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
104
src/test/ref/procedure-callingconvention-stack-12.asm
Normal file
104
src/test/ref/procedure-callingconvention-stack-12.asm
Normal file
@ -0,0 +1,104 @@
|
||||
// Test a procedure with calling convention stack
|
||||
// Test that comments are handled correctly
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const STACK_BASE = $103
|
||||
.label idx = 4
|
||||
__bbegin:
|
||||
// idx = 0
|
||||
lda #0
|
||||
sta.z idx
|
||||
jsr main
|
||||
rts
|
||||
// print(byte* zp(2) str, byte zp(5) spacing)
|
||||
print: {
|
||||
.const OFFSET_STACK_STR = 1
|
||||
.const OFFSET_STACK_SPACING = 0
|
||||
.label c = 6
|
||||
.label str = 2
|
||||
.label spacing = 5
|
||||
// }
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_STR,x
|
||||
sta.z str
|
||||
lda STACK_BASE+OFFSET_STACK_STR+1,x
|
||||
sta.z str+1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_SPACING,x
|
||||
sta.z spacing
|
||||
__b1:
|
||||
// while(*str)
|
||||
ldy #0
|
||||
lda (str),y
|
||||
cmp #0
|
||||
bne __b2
|
||||
// }
|
||||
rts
|
||||
__b2:
|
||||
// SCREEN[idx++] = *(str++)
|
||||
ldx.z idx
|
||||
ldy #0
|
||||
lda (str),y
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = *(str++);
|
||||
inc.z idx
|
||||
inc.z str
|
||||
bne !+
|
||||
inc.z str+1
|
||||
!:
|
||||
// c=0
|
||||
lda #0
|
||||
sta.z c
|
||||
__b3:
|
||||
// for(char c=0;c<spacing;c++)
|
||||
lda.z c
|
||||
cmp.z spacing
|
||||
bcc __b4
|
||||
jmp __b1
|
||||
__b4:
|
||||
// SCREEN[idx++] = ' '
|
||||
lda #' '
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// SCREEN[idx++] = ' ';
|
||||
inc.z idx
|
||||
// for(char c=0;c<spacing;c++)
|
||||
inc.z c
|
||||
jmp __b3
|
||||
}
|
||||
main: {
|
||||
// print("hello", 1)
|
||||
// Print "hello"
|
||||
lda #>str
|
||||
pha
|
||||
lda #<str
|
||||
pha
|
||||
lda #1
|
||||
pha
|
||||
jsr print
|
||||
tsx
|
||||
txa
|
||||
axs #-3
|
||||
txs
|
||||
// print("world", 2)
|
||||
// Print "world"
|
||||
lda #>str1
|
||||
pha
|
||||
lda #<str1
|
||||
pha
|
||||
lda #2
|
||||
pha
|
||||
jsr print
|
||||
tsx
|
||||
txa
|
||||
axs #-3
|
||||
txs
|
||||
// }
|
||||
rts
|
||||
str: .text "hello"
|
||||
.byte 0
|
||||
str1: .text "world"
|
||||
.byte 0
|
||||
}
|
51
src/test/ref/procedure-callingconvention-stack-12.cfg
Normal file
51
src/test/ref/procedure-callingconvention-stack-12.cfg
Normal file
@ -0,0 +1,51 @@
|
||||
@begin: scope:[] from
|
||||
[0] (byte) idx ← (byte) 0
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] callexecute main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
__stackcall (void()) print((byte*) print::str , (byte) print::spacing)
|
||||
print: scope:[print] from
|
||||
[4] (byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET_STACK_STR)
|
||||
[5] (byte) print::spacing#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_SPACING)
|
||||
to:print::@1
|
||||
print::@1: scope:[print] from print print::@3
|
||||
[6] (byte*) print::str#2 ← phi( print/(byte*) print::str#0 print::@3/(byte*) print::str#1 )
|
||||
[7] if((byte) 0!=*((byte*) print::str#2)) goto print::@2
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print::@1
|
||||
[8] return
|
||||
to:@return
|
||||
print::@2: scope:[print] from print::@1
|
||||
[9] *((const byte*) SCREEN + (byte) idx) ← *((byte*) print::str#2)
|
||||
[10] (byte) idx ← ++ (byte) idx
|
||||
[11] (byte*) print::str#1 ← ++ (byte*) print::str#2
|
||||
[12] (byte) print::c ← (byte) 0
|
||||
to:print::@3
|
||||
print::@3: scope:[print] from print::@2 print::@4
|
||||
[13] if((byte) print::c<(byte) print::spacing#0) goto print::@4
|
||||
to:print::@1
|
||||
print::@4: scope:[print] from print::@3
|
||||
[14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' '
|
||||
[15] (byte) idx ← ++ (byte) idx
|
||||
[16] (byte) print::c ← ++ (byte) print::c
|
||||
to:print::@3
|
||||
|
||||
__stackcall (void()) main()
|
||||
main: scope:[main] from
|
||||
[17] stackpush(byte*) ← (const byte*) main::str
|
||||
[18] stackpush(byte) ← (byte) 1
|
||||
[19] callexecute print
|
||||
sideeffect stackpullbytes((number) 3)
|
||||
[21] stackpush(byte*) ← (const byte*) main::str1
|
||||
[22] stackpush(byte) ← (byte) 2
|
||||
[23] callexecute print
|
||||
sideeffect stackpullbytes((number) 3)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[25] return
|
||||
to:@return
|
796
src/test/ref/procedure-callingconvention-stack-12.log
Normal file
796
src/test/ref/procedure-callingconvention-stack-12.log
Normal file
@ -0,0 +1,796 @@
|
||||
Warning! Adding boolean cast to non-boolean condition *((byte*) print::str)
|
||||
Culled Empty Block (label) @1
|
||||
Culled Empty Block (label) print::@11
|
||||
Culled Empty Block (label) print::@3
|
||||
Culled Empty Block (label) print::@12
|
||||
Culled Empty Block (label) print::@7
|
||||
Culled Empty Block (label) print::@6
|
||||
Culled Empty Block (label) print::@8
|
||||
Culled Empty Block (label) print::@9
|
||||
Culled Empty Block (label) print::@10
|
||||
Calling convention STACK_CALL adding prepare/execute/finalize for call print (const byte*) main::str (number) 1
|
||||
Calling convention STACK_CALL adding prepare/execute/finalize for call print (const byte*) main::str1 (number) 2
|
||||
Calling convention STACK_CALL adding prepare/execute/finalize for call main
|
||||
Calling convention STACK_CALL replacing param((byte*) print::str) with stackidx(byte*,(const byte) print::OFFSET_STACK_STR)
|
||||
Calling convention STACK_CALL replacing param((byte) print::spacing) with stackidx(byte,(const byte) print::OFFSET_STACK_SPACING)
|
||||
Calling convention STACK_CALL adding stack push stackpush(byte*) ← main::str
|
||||
Calling convention STACK_CALL adding stack push stackpush(byte) ← 1
|
||||
Calling convention STACK_CALL adding stack push stackpush(byte*) ← main::str1
|
||||
Calling convention STACK_CALL adding stack push stackpush(byte) ← 2
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte) idx ← (byte) 0
|
||||
to:@2
|
||||
|
||||
__stackcall (void()) main()
|
||||
main: scope:[main] from
|
||||
stackpush(byte*) ← (const byte*) main::str
|
||||
stackpush(byte) ← (number) 1
|
||||
callexecute print
|
||||
sideeffect stackpullbytes((number) 3)
|
||||
stackpush(byte*) ← (const byte*) main::str1
|
||||
stackpush(byte) ← (number) 2
|
||||
callexecute print
|
||||
sideeffect stackpullbytes((number) 3)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
|
||||
__stackcall (void()) print((byte*) print::str , (byte) print::spacing)
|
||||
print: scope:[print] from
|
||||
(byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET_STACK_STR)
|
||||
(byte) print::spacing#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_SPACING)
|
||||
to:print::@1
|
||||
print::@1: scope:[print] from print print::@4
|
||||
(byte) print::spacing#4 ← phi( print/(byte) print::spacing#0 print::@4/(byte) print::spacing#1 )
|
||||
(byte*) print::str#2 ← phi( print/(byte*) print::str#0 print::@4/(byte*) print::str#4 )
|
||||
(bool~) print::$1 ← (number) 0 != *((byte*) print::str#2)
|
||||
if((bool~) print::$1) goto print::@2
|
||||
to:print::@return
|
||||
print::@2: scope:[print] from print::@1
|
||||
(byte) print::spacing#2 ← phi( print::@1/(byte) print::spacing#4 )
|
||||
(byte*) print::str#3 ← phi( print::@1/(byte*) print::str#2 )
|
||||
*((const byte*) SCREEN + (byte) idx) ← *((byte*) print::str#3)
|
||||
(byte) idx ← ++ (byte) idx
|
||||
(byte*) print::str#1 ← ++ (byte*) print::str#3
|
||||
(byte) print::c ← (byte) 0
|
||||
to:print::@4
|
||||
print::@4: scope:[print] from print::@2 print::@5
|
||||
(byte*) print::str#4 ← phi( print::@2/(byte*) print::str#1 print::@5/(byte*) print::str#5 )
|
||||
(byte) print::spacing#1 ← phi( print::@2/(byte) print::spacing#2 print::@5/(byte) print::spacing#3 )
|
||||
(bool~) print::$0 ← (byte) print::c < (byte) print::spacing#1
|
||||
if((bool~) print::$0) goto print::@5
|
||||
to:print::@1
|
||||
print::@5: scope:[print] from print::@4
|
||||
(byte*) print::str#5 ← phi( print::@4/(byte*) print::str#4 )
|
||||
(byte) print::spacing#3 ← phi( print::@4/(byte) print::spacing#1 )
|
||||
*((const byte*) SCREEN + (byte) idx) ← (byte) ' '
|
||||
(byte) idx ← ++ (byte) idx
|
||||
(byte) print::c ← ++ (byte) print::c
|
||||
to:print::@4
|
||||
print::@return: scope:[print] from print::@1
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @begin
|
||||
callexecute main
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte*) SCREEN = (byte*)(number) $400
|
||||
(const word) STACK_BASE = (word) $103
|
||||
(byte) idx loadstore
|
||||
__stackcall (void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::str[(byte) 6] = (byte*) "hello"
|
||||
(const byte*) main::str1[(byte) 6] = (byte*) "world"
|
||||
__stackcall (void()) print((byte*) print::str , (byte) print::spacing)
|
||||
(bool~) print::$0
|
||||
(bool~) print::$1
|
||||
(label) print::@1
|
||||
(label) print::@2
|
||||
(label) print::@4
|
||||
(label) print::@5
|
||||
(label) print::@return
|
||||
(const byte) print::OFFSET_STACK_SPACING = (byte) 0
|
||||
(const byte) print::OFFSET_STACK_STR = (byte) 1
|
||||
(byte) print::c loadstore
|
||||
(byte) print::spacing
|
||||
(byte) print::spacing#0
|
||||
(byte) print::spacing#1
|
||||
(byte) print::spacing#2
|
||||
(byte) print::spacing#3
|
||||
(byte) print::spacing#4
|
||||
(byte*) print::str
|
||||
(byte*) print::str#0
|
||||
(byte*) print::str#1
|
||||
(byte*) print::str#2
|
||||
(byte*) print::str#3
|
||||
(byte*) print::str#4
|
||||
(byte*) print::str#5
|
||||
|
||||
Adding number conversion cast (unumber) 1 in stackpush(byte) ← (number) 1
|
||||
Adding number conversion cast (unumber) 2 in stackpush(byte) ← (number) 2
|
||||
Adding number conversion cast (unumber) 0 in (bool~) print::$1 ← (number) 0 != *((byte*) print::str#2)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast stackpush(byte) ← (unumber)(number) 1
|
||||
Inlining cast stackpush(byte) ← (unumber)(number) 2
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 1
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 1
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias (byte*) print::str#2 = (byte*) print::str#3
|
||||
Alias (byte) print::spacing#2 = (byte) print::spacing#4
|
||||
Alias (byte) print::spacing#1 = (byte) print::spacing#3
|
||||
Alias (byte*) print::str#4 = (byte*) print::str#5
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values (byte) print::spacing#1 (byte) print::spacing#2
|
||||
Identical Phi Values (byte*) print::str#4 (byte*) print::str#1
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Identical Phi Values (byte) print::spacing#2 (byte) print::spacing#0
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition (bool~) print::$1 [14] if((byte) 0!=*((byte*) print::str#2)) goto print::@2
|
||||
Simple Condition (bool~) print::$0 [21] if((byte) print::c<(byte) print::spacing#0) goto print::@5
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Added new block during phi lifting print::@13(between print::@4 and print::@1)
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
Calls in [main] to print:21 print:25
|
||||
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [6] print::str#6 ← print::str#0
|
||||
Coalesced [15] print::str#7 ← print::str#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Culled Empty Block (label) print::@13
|
||||
Renumbering block @2 to @1
|
||||
Renumbering block print::@4 to print::@3
|
||||
Renumbering block print::@5 to print::@4
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] (byte) idx ← (byte) 0
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] callexecute main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
__stackcall (void()) print((byte*) print::str , (byte) print::spacing)
|
||||
print: scope:[print] from
|
||||
[4] (byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET_STACK_STR)
|
||||
[5] (byte) print::spacing#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_SPACING)
|
||||
to:print::@1
|
||||
print::@1: scope:[print] from print print::@3
|
||||
[6] (byte*) print::str#2 ← phi( print/(byte*) print::str#0 print::@3/(byte*) print::str#1 )
|
||||
[7] if((byte) 0!=*((byte*) print::str#2)) goto print::@2
|
||||
to:print::@return
|
||||
print::@return: scope:[print] from print::@1
|
||||
[8] return
|
||||
to:@return
|
||||
print::@2: scope:[print] from print::@1
|
||||
[9] *((const byte*) SCREEN + (byte) idx) ← *((byte*) print::str#2)
|
||||
[10] (byte) idx ← ++ (byte) idx
|
||||
[11] (byte*) print::str#1 ← ++ (byte*) print::str#2
|
||||
[12] (byte) print::c ← (byte) 0
|
||||
to:print::@3
|
||||
print::@3: scope:[print] from print::@2 print::@4
|
||||
[13] if((byte) print::c<(byte) print::spacing#0) goto print::@4
|
||||
to:print::@1
|
||||
print::@4: scope:[print] from print::@3
|
||||
[14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' '
|
||||
[15] (byte) idx ← ++ (byte) idx
|
||||
[16] (byte) print::c ← ++ (byte) print::c
|
||||
to:print::@3
|
||||
|
||||
__stackcall (void()) main()
|
||||
main: scope:[main] from
|
||||
[17] stackpush(byte*) ← (const byte*) main::str
|
||||
[18] stackpush(byte) ← (byte) 1
|
||||
[19] callexecute print
|
||||
sideeffect stackpullbytes((number) 3)
|
||||
[21] stackpush(byte*) ← (const byte*) main::str1
|
||||
[22] stackpush(byte) ← (byte) 2
|
||||
[23] callexecute print
|
||||
sideeffect stackpullbytes((number) 3)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[25] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte) idx loadstore 16.095238095238095
|
||||
__stackcall (void()) main()
|
||||
__stackcall (void()) print((byte*) print::str , (byte) print::spacing)
|
||||
(byte) print::c loadstore 62.8
|
||||
(byte) print::spacing
|
||||
(byte) print::spacing#0 9.363636363636363
|
||||
(byte*) print::str
|
||||
(byte*) print::str#0 2.0
|
||||
(byte*) print::str#1 18.666666666666664
|
||||
(byte*) print::str#2 34.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ print::str#2 print::str#0 print::str#1 ]
|
||||
Added variable idx to live range equivalence class [ idx ]
|
||||
Added variable print::spacing#0 to live range equivalence class [ print::spacing#0 ]
|
||||
Added variable print::c to live range equivalence class [ print::c ]
|
||||
Complete equivalence classes
|
||||
[ print::str#2 print::str#0 print::str#1 ]
|
||||
[ idx ]
|
||||
[ print::spacing#0 ]
|
||||
[ print::c ]
|
||||
Allocated zp[2]:2 [ print::str#2 print::str#0 print::str#1 ]
|
||||
Allocated zp[1]:4 [ idx ]
|
||||
Allocated zp[1]:5 [ print::spacing#0 ]
|
||||
Allocated zp[1]:6 [ print::c ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Test a procedure with calling convention stack
|
||||
// Test that comments are handled correctly
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const STACK_BASE = $103
|
||||
.label idx = 4
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] (byte) idx ← (byte) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z idx
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] callexecute main -- jsr
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// print
|
||||
// print(byte* zp(2) str, byte zp(5) spacing)
|
||||
print: {
|
||||
.const OFFSET_STACK_STR = 1
|
||||
.const OFFSET_STACK_SPACING = 0
|
||||
.label c = 6
|
||||
.label str = 2
|
||||
.label spacing = 5
|
||||
// [4] (byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET_STACK_STR) -- pbuz1=_stackidxptr_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_STR,x
|
||||
sta.z str
|
||||
lda STACK_BASE+OFFSET_STACK_STR+1,x
|
||||
sta.z str+1
|
||||
// [5] (byte) print::spacing#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_SPACING) -- vbuz1=_stackidxbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_SPACING,x
|
||||
sta.z spacing
|
||||
// [6] phi from print print::@3 to print::@1 [phi:print/print::@3->print::@1]
|
||||
__b1_from_print:
|
||||
__b1_from___b3:
|
||||
// [6] phi (byte*) print::str#2 = (byte*) print::str#0 [phi:print/print::@3->print::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
// print::@1
|
||||
__b1:
|
||||
// [7] if((byte) 0!=*((byte*) print::str#2)) goto print::@2 -- vbuc1_neq__deref_pbuz1_then_la1
|
||||
ldy #0
|
||||
lda (str),y
|
||||
cmp #0
|
||||
bne __b2
|
||||
jmp __breturn
|
||||
// print::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
// print::@2
|
||||
__b2:
|
||||
// [9] *((const byte*) SCREEN + (byte) idx) ← *((byte*) print::str#2) -- pbuc1_derefidx_vbuz1=_deref_pbuz2
|
||||
ldx.z idx
|
||||
ldy #0
|
||||
lda (str),y
|
||||
sta SCREEN,x
|
||||
// [10] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
|
||||
inc.z idx
|
||||
// [11] (byte*) print::str#1 ← ++ (byte*) print::str#2 -- pbuz1=_inc_pbuz1
|
||||
inc.z str
|
||||
bne !+
|
||||
inc.z str+1
|
||||
!:
|
||||
// [12] (byte) print::c ← (byte) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z c
|
||||
jmp __b3
|
||||
// print::@3
|
||||
__b3:
|
||||
// [13] if((byte) print::c<(byte) print::spacing#0) goto print::@4 -- vbuz1_lt_vbuz2_then_la1
|
||||
lda.z c
|
||||
cmp.z spacing
|
||||
bcc __b4
|
||||
jmp __b1_from___b3
|
||||
// print::@4
|
||||
__b4:
|
||||
// [14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
|
||||
lda #' '
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// [15] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
|
||||
inc.z idx
|
||||
// [16] (byte) print::c ← ++ (byte) print::c -- vbuz1=_inc_vbuz1
|
||||
inc.z c
|
||||
jmp __b3
|
||||
}
|
||||
// main
|
||||
main: {
|
||||
// [17] stackpush(byte*) ← (const byte*) main::str -- _stackpushptr_=pbuc1
|
||||
// Print "hello"
|
||||
lda #>str
|
||||
pha
|
||||
lda #<str
|
||||
pha
|
||||
// [18] stackpush(byte) ← (byte) 1 -- _stackpushbyte_=vbuc1
|
||||
lda #1
|
||||
pha
|
||||
// [19] callexecute print -- jsr
|
||||
jsr print
|
||||
// sideeffect stackpullbytes((number) 3) -- _stackpullbyte_3
|
||||
tsx
|
||||
txa
|
||||
axs #-3
|
||||
txs
|
||||
// [21] stackpush(byte*) ← (const byte*) main::str1 -- _stackpushptr_=pbuc1
|
||||
// Print "world"
|
||||
lda #>str1
|
||||
pha
|
||||
lda #<str1
|
||||
pha
|
||||
// [22] stackpush(byte) ← (byte) 2 -- _stackpushbyte_=vbuc1
|
||||
lda #2
|
||||
pha
|
||||
// [23] callexecute print -- jsr
|
||||
jsr print
|
||||
// sideeffect stackpullbytes((number) 3) -- _stackpullbyte_3
|
||||
tsx
|
||||
txa
|
||||
axs #-3
|
||||
txs
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [25] return
|
||||
rts
|
||||
str: .text "hello"
|
||||
.byte 0
|
||||
str1: .text "world"
|
||||
.byte 0
|
||||
}
|
||||
// File Data
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a
|
||||
Statement [4] (byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET_STACK_STR) [ idx print::str#0 ] ( main:2::print:19 [ idx print::str#0 ] main:2::print:23 [ idx print::str#0 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [5] (byte) print::spacing#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_SPACING) [ idx print::str#0 print::spacing#0 ] ( main:2::print:19 [ idx print::str#0 print::spacing#0 ] main:2::print:23 [ idx print::str#0 print::spacing#0 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [7] if((byte) 0!=*((byte*) print::str#2)) goto print::@2 [ idx print::spacing#0 print::str#2 ] ( main:2::print:19 [ idx print::spacing#0 print::str#2 ] main:2::print:23 [ idx print::spacing#0 print::str#2 ] ) always clobbers reg byte a reg byte y
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:5 [ print::spacing#0 ]
|
||||
Removing always clobbered register reg byte y as potential for zp[1]:5 [ print::spacing#0 ]
|
||||
Statement [9] *((const byte*) SCREEN + (byte) idx) ← *((byte*) print::str#2) [ idx print::spacing#0 print::str#2 ] ( main:2::print:19 [ idx print::spacing#0 print::str#2 ] main:2::print:23 [ idx print::spacing#0 print::str#2 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Removing always clobbered register reg byte x as potential for zp[1]:5 [ print::spacing#0 ]
|
||||
Statement [12] (byte) print::c ← (byte) 0 [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a
|
||||
Statement [13] if((byte) print::c<(byte) print::spacing#0) goto print::@4 [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a
|
||||
Statement [14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a reg byte y
|
||||
Statement [17] stackpush(byte*) ← (const byte*) main::str [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a
|
||||
Statement [18] stackpush(byte) ← (byte) 1 [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a
|
||||
Statement sideeffect stackpullbytes((number) 3) always clobbers reg byte a reg byte x
|
||||
Statement [21] stackpush(byte*) ← (const byte*) main::str1 [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a
|
||||
Statement [22] stackpush(byte) ← (byte) 2 [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a
|
||||
Statement sideeffect stackpullbytes((number) 3) always clobbers reg byte a reg byte x
|
||||
Statement [0] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a
|
||||
Statement [4] (byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET_STACK_STR) [ idx print::str#0 ] ( main:2::print:19 [ idx print::str#0 ] main:2::print:23 [ idx print::str#0 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [5] (byte) print::spacing#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_SPACING) [ idx print::str#0 print::spacing#0 ] ( main:2::print:19 [ idx print::str#0 print::spacing#0 ] main:2::print:23 [ idx print::str#0 print::spacing#0 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [7] if((byte) 0!=*((byte*) print::str#2)) goto print::@2 [ idx print::spacing#0 print::str#2 ] ( main:2::print:19 [ idx print::spacing#0 print::str#2 ] main:2::print:23 [ idx print::spacing#0 print::str#2 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [9] *((const byte*) SCREEN + (byte) idx) ← *((byte*) print::str#2) [ idx print::spacing#0 print::str#2 ] ( main:2::print:19 [ idx print::spacing#0 print::str#2 ] main:2::print:23 [ idx print::spacing#0 print::str#2 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Statement [12] (byte) print::c ← (byte) 0 [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a
|
||||
Statement [13] if((byte) print::c<(byte) print::spacing#0) goto print::@4 [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a
|
||||
Statement [14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' [ idx print::spacing#0 print::str#1 print::c ] ( main:2::print:19 [ idx print::spacing#0 print::str#1 print::c ] main:2::print:23 [ idx print::spacing#0 print::str#1 print::c ] ) always clobbers reg byte a reg byte y
|
||||
Statement [17] stackpush(byte*) ← (const byte*) main::str [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a
|
||||
Statement [18] stackpush(byte) ← (byte) 1 [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a
|
||||
Statement sideeffect stackpullbytes((number) 3) always clobbers reg byte a reg byte x
|
||||
Statement [21] stackpush(byte*) ← (const byte*) main::str1 [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a
|
||||
Statement [22] stackpush(byte) ← (byte) 2 [ idx ] ( main:2 [ idx ] ) always clobbers reg byte a
|
||||
Statement sideeffect stackpullbytes((number) 3) always clobbers reg byte a reg byte x
|
||||
Potential registers zp[2]:2 [ print::str#2 print::str#0 print::str#1 ] : zp[2]:2 ,
|
||||
Potential registers zp[1]:4 [ idx ] : zp[1]:4 ,
|
||||
Potential registers zp[1]:5 [ print::spacing#0 ] : zp[1]:5 ,
|
||||
Potential registers zp[1]:6 [ print::c ] : zp[1]:6 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [print] 62.8: zp[1]:6 [ print::c ] 54.67: zp[2]:2 [ print::str#2 print::str#0 print::str#1 ] 9.36: zp[1]:5 [ print::spacing#0 ]
|
||||
Uplift Scope [] 16.1: zp[1]:4 [ idx ]
|
||||
Uplift Scope [main]
|
||||
|
||||
Uplifting [print] best 4156 combination zp[1]:6 [ print::c ] zp[2]:2 [ print::str#2 print::str#0 print::str#1 ] zp[1]:5 [ print::spacing#0 ]
|
||||
Uplifting [] best 4156 combination zp[1]:4 [ idx ]
|
||||
Uplifting [main] best 4156 combination
|
||||
Attempting to uplift remaining variables inzp[1]:6 [ print::c ]
|
||||
Uplifting [print] best 4156 combination zp[1]:6 [ print::c ]
|
||||
Attempting to uplift remaining variables inzp[1]:4 [ idx ]
|
||||
Uplifting [] best 4156 combination zp[1]:4 [ idx ]
|
||||
Attempting to uplift remaining variables inzp[1]:5 [ print::spacing#0 ]
|
||||
Uplifting [print] best 4156 combination zp[1]:5 [ print::spacing#0 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a procedure with calling convention stack
|
||||
// Test that comments are handled correctly
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const STACK_BASE = $103
|
||||
.label idx = 4
|
||||
// @begin
|
||||
__bbegin:
|
||||
// [0] (byte) idx ← (byte) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z idx
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
__b1_from___bbegin:
|
||||
jmp __b1
|
||||
// @1
|
||||
__b1:
|
||||
// [2] callexecute main -- jsr
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
__bend_from___b1:
|
||||
jmp __bend
|
||||
// @end
|
||||
__bend:
|
||||
// print
|
||||
// print(byte* zp(2) str, byte zp(5) spacing)
|
||||
print: {
|
||||
.const OFFSET_STACK_STR = 1
|
||||
.const OFFSET_STACK_SPACING = 0
|
||||
.label c = 6
|
||||
.label str = 2
|
||||
.label spacing = 5
|
||||
// [4] (byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET_STACK_STR) -- pbuz1=_stackidxptr_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_STR,x
|
||||
sta.z str
|
||||
lda STACK_BASE+OFFSET_STACK_STR+1,x
|
||||
sta.z str+1
|
||||
// [5] (byte) print::spacing#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_SPACING) -- vbuz1=_stackidxbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_SPACING,x
|
||||
sta.z spacing
|
||||
// [6] phi from print print::@3 to print::@1 [phi:print/print::@3->print::@1]
|
||||
__b1_from_print:
|
||||
__b1_from___b3:
|
||||
// [6] phi (byte*) print::str#2 = (byte*) print::str#0 [phi:print/print::@3->print::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
// print::@1
|
||||
__b1:
|
||||
// [7] if((byte) 0!=*((byte*) print::str#2)) goto print::@2 -- vbuc1_neq__deref_pbuz1_then_la1
|
||||
ldy #0
|
||||
lda (str),y
|
||||
cmp #0
|
||||
bne __b2
|
||||
jmp __breturn
|
||||
// print::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
// print::@2
|
||||
__b2:
|
||||
// [9] *((const byte*) SCREEN + (byte) idx) ← *((byte*) print::str#2) -- pbuc1_derefidx_vbuz1=_deref_pbuz2
|
||||
ldx.z idx
|
||||
ldy #0
|
||||
lda (str),y
|
||||
sta SCREEN,x
|
||||
// [10] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
|
||||
inc.z idx
|
||||
// [11] (byte*) print::str#1 ← ++ (byte*) print::str#2 -- pbuz1=_inc_pbuz1
|
||||
inc.z str
|
||||
bne !+
|
||||
inc.z str+1
|
||||
!:
|
||||
// [12] (byte) print::c ← (byte) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z c
|
||||
jmp __b3
|
||||
// print::@3
|
||||
__b3:
|
||||
// [13] if((byte) print::c<(byte) print::spacing#0) goto print::@4 -- vbuz1_lt_vbuz2_then_la1
|
||||
lda.z c
|
||||
cmp.z spacing
|
||||
bcc __b4
|
||||
jmp __b1_from___b3
|
||||
// print::@4
|
||||
__b4:
|
||||
// [14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
|
||||
lda #' '
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// [15] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
|
||||
inc.z idx
|
||||
// [16] (byte) print::c ← ++ (byte) print::c -- vbuz1=_inc_vbuz1
|
||||
inc.z c
|
||||
jmp __b3
|
||||
}
|
||||
// main
|
||||
main: {
|
||||
// [17] stackpush(byte*) ← (const byte*) main::str -- _stackpushptr_=pbuc1
|
||||
// Print "hello"
|
||||
lda #>str
|
||||
pha
|
||||
lda #<str
|
||||
pha
|
||||
// [18] stackpush(byte) ← (byte) 1 -- _stackpushbyte_=vbuc1
|
||||
lda #1
|
||||
pha
|
||||
// [19] callexecute print -- jsr
|
||||
jsr print
|
||||
// sideeffect stackpullbytes((number) 3) -- _stackpullbyte_3
|
||||
tsx
|
||||
txa
|
||||
axs #-3
|
||||
txs
|
||||
// [21] stackpush(byte*) ← (const byte*) main::str1 -- _stackpushptr_=pbuc1
|
||||
// Print "world"
|
||||
lda #>str1
|
||||
pha
|
||||
lda #<str1
|
||||
pha
|
||||
// [22] stackpush(byte) ← (byte) 2 -- _stackpushbyte_=vbuc1
|
||||
lda #2
|
||||
pha
|
||||
// [23] callexecute print -- jsr
|
||||
jsr print
|
||||
// sideeffect stackpullbytes((number) 3) -- _stackpullbyte_3
|
||||
tsx
|
||||
txa
|
||||
axs #-3
|
||||
txs
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [25] return
|
||||
rts
|
||||
str: .text "hello"
|
||||
.byte 0
|
||||
str1: .text "world"
|
||||
.byte 0
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __bend
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __breturn
|
||||
Removing instruction jmp __b3
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label __b1_from___b3 with __b1
|
||||
Removing instruction __b1_from___bbegin:
|
||||
Removing instruction __bend_from___b1:
|
||||
Removing instruction __b1_from_print:
|
||||
Removing instruction __b1_from___b3:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b1:
|
||||
Removing instruction __bend:
|
||||
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) @begin
|
||||
(label) @end
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(const word) STACK_BASE = (word) $103
|
||||
(byte) idx loadstore zp[1]:4 16.095238095238095
|
||||
__stackcall (void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::str[(byte) 6] = (byte*) "hello"
|
||||
(const byte*) main::str1[(byte) 6] = (byte*) "world"
|
||||
__stackcall (void()) print((byte*) print::str , (byte) print::spacing)
|
||||
(label) print::@1
|
||||
(label) print::@2
|
||||
(label) print::@3
|
||||
(label) print::@4
|
||||
(label) print::@return
|
||||
(const byte) print::OFFSET_STACK_SPACING = (byte) 0
|
||||
(const byte) print::OFFSET_STACK_STR = (byte) 1
|
||||
(byte) print::c loadstore zp[1]:6 62.8
|
||||
(byte) print::spacing
|
||||
(byte) print::spacing#0 spacing zp[1]:5 9.363636363636363
|
||||
(byte*) print::str
|
||||
(byte*) print::str#0 str zp[2]:2 2.0
|
||||
(byte*) print::str#1 str zp[2]:2 18.666666666666664
|
||||
(byte*) print::str#2 str zp[2]:2 34.0
|
||||
|
||||
zp[2]:2 [ print::str#2 print::str#0 print::str#1 ]
|
||||
zp[1]:4 [ idx ]
|
||||
zp[1]:5 [ print::spacing#0 ]
|
||||
zp[1]:6 [ print::c ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 4063
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention stack
|
||||
// Test that comments are handled correctly
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(__bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.const STACK_BASE = $103
|
||||
.label idx = 4
|
||||
// @begin
|
||||
__bbegin:
|
||||
// idx = 0
|
||||
// [0] (byte) idx ← (byte) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z idx
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] callexecute main -- jsr
|
||||
jsr main
|
||||
rts
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// print
|
||||
// print(byte* zp(2) str, byte zp(5) spacing)
|
||||
print: {
|
||||
.const OFFSET_STACK_STR = 1
|
||||
.const OFFSET_STACK_SPACING = 0
|
||||
.label c = 6
|
||||
.label str = 2
|
||||
.label spacing = 5
|
||||
// }
|
||||
// [4] (byte*) print::str#0 ← stackidx(byte*,(const byte) print::OFFSET_STACK_STR) -- pbuz1=_stackidxptr_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_STR,x
|
||||
sta.z str
|
||||
lda STACK_BASE+OFFSET_STACK_STR+1,x
|
||||
sta.z str+1
|
||||
// [5] (byte) print::spacing#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_SPACING) -- vbuz1=_stackidxbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_SPACING,x
|
||||
sta.z spacing
|
||||
// [6] phi from print print::@3 to print::@1 [phi:print/print::@3->print::@1]
|
||||
// [6] phi (byte*) print::str#2 = (byte*) print::str#0 [phi:print/print::@3->print::@1#0] -- register_copy
|
||||
// print::@1
|
||||
__b1:
|
||||
// while(*str)
|
||||
// [7] if((byte) 0!=*((byte*) print::str#2)) goto print::@2 -- vbuc1_neq__deref_pbuz1_then_la1
|
||||
ldy #0
|
||||
lda (str),y
|
||||
cmp #0
|
||||
bne __b2
|
||||
// print::@return
|
||||
// }
|
||||
// [8] return
|
||||
rts
|
||||
// print::@2
|
||||
__b2:
|
||||
// SCREEN[idx++] = *(str++)
|
||||
// [9] *((const byte*) SCREEN + (byte) idx) ← *((byte*) print::str#2) -- pbuc1_derefidx_vbuz1=_deref_pbuz2
|
||||
ldx.z idx
|
||||
ldy #0
|
||||
lda (str),y
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = *(str++);
|
||||
// [10] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
|
||||
inc.z idx
|
||||
// [11] (byte*) print::str#1 ← ++ (byte*) print::str#2 -- pbuz1=_inc_pbuz1
|
||||
inc.z str
|
||||
bne !+
|
||||
inc.z str+1
|
||||
!:
|
||||
// c=0
|
||||
// [12] (byte) print::c ← (byte) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z c
|
||||
// print::@3
|
||||
__b3:
|
||||
// for(char c=0;c<spacing;c++)
|
||||
// [13] if((byte) print::c<(byte) print::spacing#0) goto print::@4 -- vbuz1_lt_vbuz2_then_la1
|
||||
lda.z c
|
||||
cmp.z spacing
|
||||
bcc __b4
|
||||
jmp __b1
|
||||
// print::@4
|
||||
__b4:
|
||||
// SCREEN[idx++] = ' '
|
||||
// [14] *((const byte*) SCREEN + (byte) idx) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
|
||||
lda #' '
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// SCREEN[idx++] = ' ';
|
||||
// [15] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1
|
||||
inc.z idx
|
||||
// for(char c=0;c<spacing;c++)
|
||||
// [16] (byte) print::c ← ++ (byte) print::c -- vbuz1=_inc_vbuz1
|
||||
inc.z c
|
||||
jmp __b3
|
||||
}
|
||||
// main
|
||||
main: {
|
||||
// print("hello", 1)
|
||||
// [17] stackpush(byte*) ← (const byte*) main::str -- _stackpushptr_=pbuc1
|
||||
// Print "hello"
|
||||
lda #>str
|
||||
pha
|
||||
lda #<str
|
||||
pha
|
||||
// [18] stackpush(byte) ← (byte) 1 -- _stackpushbyte_=vbuc1
|
||||
lda #1
|
||||
pha
|
||||
// [19] callexecute print -- jsr
|
||||
jsr print
|
||||
// sideeffect stackpullbytes((number) 3) -- _stackpullbyte_3
|
||||
tsx
|
||||
txa
|
||||
axs #-3
|
||||
txs
|
||||
// print("world", 2)
|
||||
// [21] stackpush(byte*) ← (const byte*) main::str1 -- _stackpushptr_=pbuc1
|
||||
// Print "world"
|
||||
lda #>str1
|
||||
pha
|
||||
lda #<str1
|
||||
pha
|
||||
// [22] stackpush(byte) ← (byte) 2 -- _stackpushbyte_=vbuc1
|
||||
lda #2
|
||||
pha
|
||||
// [23] callexecute print -- jsr
|
||||
jsr print
|
||||
// sideeffect stackpullbytes((number) 3) -- _stackpullbyte_3
|
||||
tsx
|
||||
txa
|
||||
axs #-3
|
||||
txs
|
||||
// main::@return
|
||||
// }
|
||||
// [25] return
|
||||
rts
|
||||
str: .text "hello"
|
||||
.byte 0
|
||||
str1: .text "world"
|
||||
.byte 0
|
||||
}
|
||||
// File Data
|
||||
|
30
src/test/ref/procedure-callingconvention-stack-12.sym
Normal file
30
src/test/ref/procedure-callingconvention-stack-12.sym
Normal file
@ -0,0 +1,30 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(const word) STACK_BASE = (word) $103
|
||||
(byte) idx loadstore zp[1]:4 16.095238095238095
|
||||
__stackcall (void()) main()
|
||||
(label) main::@return
|
||||
(const byte*) main::str[(byte) 6] = (byte*) "hello"
|
||||
(const byte*) main::str1[(byte) 6] = (byte*) "world"
|
||||
__stackcall (void()) print((byte*) print::str , (byte) print::spacing)
|
||||
(label) print::@1
|
||||
(label) print::@2
|
||||
(label) print::@3
|
||||
(label) print::@4
|
||||
(label) print::@return
|
||||
(const byte) print::OFFSET_STACK_SPACING = (byte) 0
|
||||
(const byte) print::OFFSET_STACK_STR = (byte) 1
|
||||
(byte) print::c loadstore zp[1]:6 62.8
|
||||
(byte) print::spacing
|
||||
(byte) print::spacing#0 spacing zp[1]:5 9.363636363636363
|
||||
(byte*) print::str
|
||||
(byte*) print::str#0 str zp[2]:2 2.0
|
||||
(byte*) print::str#1 str zp[2]:2 18.666666666666664
|
||||
(byte*) print::str#2 str zp[2]:2 34.0
|
||||
|
||||
zp[2]:2 [ print::str#2 print::str#0 print::str#1 ]
|
||||
zp[1]:4 [ idx ]
|
||||
zp[1]:5 [ print::spacing#0 ]
|
||||
zp[1]:6 [ print::c ]
|
Loading…
x
Reference in New Issue
Block a user