mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-26 12:49:21 +00:00
Fixed literal strings initializing char* in array or struct. Closes #297
This commit is contained in:
parent
1898956932
commit
41c257a9df
@ -15485,3 +15485,91 @@ bcc {la1}
|
||||
sta $ff
|
||||
cpy $ff
|
||||
bcc {la1}
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vbuc1)_derefidx_vbuz2_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vbsc1)_derefidx_vbuz2_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vwuc1)_derefidx_vbuz2_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vwsc1)_derefidx_vbuz2_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vduc1)_derefidx_vbuz2_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vdsc1)_derefidx_vbuz2_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT pbuc1_derefidx_vbuz1=(qbuz2_derefidx_vbuc2)_derefidx_vbuz3
|
||||
ldx {z1}
|
||||
ldy #{c2}
|
||||
lda ({z2}),y
|
||||
sta $fe
|
||||
iny
|
||||
lda ({z2}),y
|
||||
sta $ff
|
||||
ldy {z3}
|
||||
lda ($fe),y
|
||||
sta {c1},x
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vbuc1)_derefidx_vbuaa_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vbsc1)_derefidx_vbuaa_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vwuc1)_derefidx_vbuaa_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vwsc1)_derefidx_vbuaa_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vduc1)_derefidx_vbuaa_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vdsc1)_derefidx_vbuaa_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vbuc1)_derefidx_vbuxx_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vbsc1)_derefidx_vbuxx_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vwuc1)_derefidx_vbuxx_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vwsc1)_derefidx_vbuxx_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vduc1)_derefidx_vbuxx_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vdsc1)_derefidx_vbuxx_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vbuc1)_derefidx_vbuyy_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vbsc1)_derefidx_vbuyy_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vwuc1)_derefidx_vbuyy_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vwsc1)_derefidx_vbuyy_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vduc1)_derefidx_vbuyy_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT 0_neq_(qbuz1_derefidx_vdsc1)_derefidx_vbuyy_then_la1
|
||||
NO_SYNTHESIS
|
||||
//FRAGMENT qbuz1=qbuc1
|
||||
lda #<{c1}
|
||||
sta {z1}
|
||||
lda #>{c1}
|
||||
sta {z1}+1
|
||||
//FRAGMENT pbuc1_neq__deref_qbuz1_then_la1
|
||||
ldy #0
|
||||
lda #<{c1}
|
||||
cmp ({z1}),y
|
||||
bne {la1}
|
||||
iny
|
||||
lda #>{c1}
|
||||
cmp ({z1}),y
|
||||
bne {la1}
|
||||
//FRAGMENT pbuz1=_deref_qbuz2
|
||||
ldy #0
|
||||
lda ({z2}),y
|
||||
sta {z1}
|
||||
iny
|
||||
lda ({z2}),y
|
||||
sta {z1}+1
|
||||
//FRAGMENT qbuz1=qbuz1_plus_vbuc1
|
||||
lda #{c1}
|
||||
clc
|
||||
adc {z1}
|
||||
sta {z1}
|
||||
bcc !+
|
||||
inc {z1}+1
|
||||
!:
|
||||
|
@ -497,6 +497,11 @@ public interface ProgramValue {
|
||||
public void set(Value value) {
|
||||
arrayList.getElements().set(idx, (ConstantValue) value);
|
||||
}
|
||||
|
||||
public ConstantArrayList getArrayList() {
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Member of a constant struct value. */
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.StatementCallPrepare;
|
||||
@ -10,10 +11,7 @@ import dk.camelot64.kickc.model.symbols.Scope;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||
import dk.camelot64.kickc.model.values.ConstantString;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.Value;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -28,7 +26,7 @@ public class Pass1ExtractInlineStrings extends Pass1Base {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
String nameHint = null;
|
||||
if(currentStmt instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) currentStmt;
|
||||
@ -55,11 +53,36 @@ public class Pass1ExtractInlineStrings extends Pass1Base {
|
||||
}
|
||||
}
|
||||
}
|
||||
Scope blockScope = Pass1ExtractInlineStrings.this.getProgram().getScope().getScope(currentBlock.getScope());
|
||||
Value value = programValue.get();
|
||||
if(value instanceof ConstantString) {
|
||||
if(value instanceof ConstantString && currentStmt!=null) {
|
||||
// String in statement expression
|
||||
Scope blockScope = Pass1ExtractInlineStrings.this.getProgram().getScope().getScope(currentBlock.getScope());
|
||||
Variable strConst = Pass1ExtractInlineStrings.this.createStringConstantVar(blockScope, (ConstantString) programValue.get(), nameHint);
|
||||
programValue.set(strConst.getRef());
|
||||
} else if(value instanceof ConstantString && programValue instanceof ProgramValue.ProgramValueConstantStructMember) {
|
||||
// Struct member initialization
|
||||
final ProgramValue.ProgramValueConstantStructMember constantStructMember = (ProgramValue.ProgramValueConstantStructMember) programValue;
|
||||
final SymbolVariableRef memberRef = constantStructMember.getMemberRef();
|
||||
final Variable memberDef = getScope().getVar(memberRef);
|
||||
if(memberDef.getType() instanceof SymbolTypePointer) {
|
||||
if(((SymbolTypePointer) memberDef.getType()).getArraySpec()==null) {
|
||||
// Member is not an array - create a string.
|
||||
nameHint = memberDef.getFullName().replace("::","_").toLowerCase();
|
||||
Variable strConst = Pass1ExtractInlineStrings.this.createStringConstantVar(getScope(), (ConstantString) programValue.get(), nameHint);
|
||||
programValue.set(strConst.getRef());
|
||||
}
|
||||
}
|
||||
} else if(value instanceof ConstantString && programValue instanceof ProgramValue.ProgramValueConstantArrayElement) {
|
||||
// Array element initialization
|
||||
final ProgramValue.ProgramValueConstantArrayElement constantArrayElement = (ProgramValue.ProgramValueConstantArrayElement) programValue;
|
||||
final SymbolType elementType = constantArrayElement.getArrayList().getElementType();
|
||||
if(elementType instanceof SymbolTypePointer) {
|
||||
if(((SymbolTypePointer) elementType).getArraySpec()==null) {
|
||||
// Element is not an array - create a string.
|
||||
Variable strConst = Pass1ExtractInlineStrings.this.createStringConstantVar(getScope(), (ConstantString) programValue.get(), null);
|
||||
programValue.set(strConst.getRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
|
@ -2049,11 +2049,10 @@ public class TestProgramsFast extends TestPrograms {
|
||||
compileAndCompare("struct-ptr-30.c");
|
||||
}
|
||||
|
||||
// TODO: Fix problem with structs containing pointer elements
|
||||
//@Test
|
||||
//public void testStructPtr29() throws IOException {
|
||||
// compileAndCompare("struct-ptr-29.c");
|
||||
//}
|
||||
@Test
|
||||
public void testStructPtr29() throws IOException {
|
||||
compileAndCompare("struct-ptr-29.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructPtr28() throws IOException {
|
||||
@ -3072,13 +3071,10 @@ public class TestProgramsFast extends TestPrograms {
|
||||
compileAndCompare("pointer-cast.c");
|
||||
}
|
||||
|
||||
// TODO: Fix literal string array initialization. https://gitlab.com/camelot/kickc/issues/297
|
||||
/*
|
||||
@Test
|
||||
public void testLiteralStringArray() throws IOException {
|
||||
compileAndCompare("literal-string-array.c");
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testLiteralWordPointer0() throws IOException {
|
||||
|
79
src/test/ref/literal-string-array.asm
Normal file
79
src/test/ref/literal-string-array.asm
Normal file
@ -0,0 +1,79 @@
|
||||
// Tests literal string array
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="literal-string-array.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
.const SIZEOF_POINTER = 2
|
||||
.label SCREEN = $400
|
||||
.label NUL = 0
|
||||
.segment Code
|
||||
main: {
|
||||
.label c = 4
|
||||
.label msg = 2
|
||||
ldx #0
|
||||
lda #<msgs
|
||||
sta.z msg
|
||||
lda #>msgs
|
||||
sta.z msg+1
|
||||
__b1:
|
||||
// while(*msg)
|
||||
ldy #0
|
||||
tya
|
||||
cmp (msg),y
|
||||
bne __b2
|
||||
iny
|
||||
cmp (msg),y
|
||||
bne __b2
|
||||
// }
|
||||
rts
|
||||
__b2:
|
||||
// char* c = *msg
|
||||
ldy #0
|
||||
lda (msg),y
|
||||
sta.z c
|
||||
iny
|
||||
lda (msg),y
|
||||
sta.z c+1
|
||||
__b3:
|
||||
// while(*c)
|
||||
ldy #0
|
||||
lda (c),y
|
||||
cmp #0
|
||||
bne __b4
|
||||
// msg++;
|
||||
lda #SIZEOF_POINTER
|
||||
clc
|
||||
adc.z msg
|
||||
sta.z msg
|
||||
bcc !+
|
||||
inc.z msg+1
|
||||
!:
|
||||
jmp __b1
|
||||
__b4:
|
||||
// SCREEN[i++] = *c++
|
||||
ldy #0
|
||||
lda (c),y
|
||||
sta SCREEN,x
|
||||
// SCREEN[i++] = *c++;
|
||||
inx
|
||||
inc.z c
|
||||
bne !+
|
||||
inc.z c+1
|
||||
!:
|
||||
jmp __b3
|
||||
}
|
||||
.segment Data
|
||||
// Works
|
||||
// char*[] msgs = { (char*)"hello", (char*)"cruel", (char*)"world", (char*)NUL };
|
||||
// Not working
|
||||
msgs: .word __0, __1, __2, NUL
|
||||
__0: .text "hello"
|
||||
.byte 0
|
||||
__1: .text "cruel"
|
||||
.byte 0
|
||||
__2: .text "world"
|
||||
.byte 0
|
29
src/test/ref/literal-string-array.cfg
Normal file
29
src/test/ref/literal-string-array.cfg
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@5
|
||||
[1] main::i#4 = phi( main/0, main::@5/main::i#2 )
|
||||
[1] main::msg#2 = phi( main/msgs, main::@5/main::msg#1 )
|
||||
[2] if((byte*)0!=*main::msg#2) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[4] main::c#0 = *main::msg#2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@4
|
||||
[5] main::i#2 = phi( main::@2/main::i#4, main::@4/main::i#1 )
|
||||
[5] main::c#2 = phi( main::@2/main::c#0, main::@4/main::c#1 )
|
||||
[6] if(0!=*main::c#2) goto main::@4
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@3
|
||||
[7] main::msg#1 = main::msg#2 + SIZEOF_POINTER
|
||||
to:main::@1
|
||||
main::@4: scope:[main] from main::@3
|
||||
[8] SCREEN[main::i#2] = *main::c#2
|
||||
[9] main::i#1 = ++ main::i#2
|
||||
[10] main::c#1 = ++ main::c#2
|
||||
to:main::@3
|
483
src/test/ref/literal-string-array.log
Normal file
483
src/test/ref/literal-string-array.log
Normal file
@ -0,0 +1,483 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
main::i#0 = 0
|
||||
main::msg#0 = msgs
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@5
|
||||
main::i#5 = phi( main/main::i#0, main::@5/main::i#6 )
|
||||
main::msg#2 = phi( main/main::msg#0, main::@5/main::msg#1 )
|
||||
main::$0 = (byte*)0 != *main::msg#2
|
||||
if(main::$0) goto main::@2
|
||||
to:main::@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
main::i#4 = phi( main::@1/main::i#5 )
|
||||
main::msg#3 = phi( main::@1/main::msg#2 )
|
||||
main::c#0 = *main::msg#3
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@4
|
||||
main::msg#5 = phi( main::@2/main::msg#3, main::@4/main::msg#6 )
|
||||
main::i#3 = phi( main::@2/main::i#4, main::@4/main::i#1 )
|
||||
main::c#2 = phi( main::@2/main::c#0, main::@4/main::c#1 )
|
||||
main::$1 = 0 != *main::c#2
|
||||
if(main::$1) goto main::@4
|
||||
to:main::@5
|
||||
main::@4: scope:[main] from main::@3
|
||||
main::msg#6 = phi( main::@3/main::msg#5 )
|
||||
main::i#2 = phi( main::@3/main::i#3 )
|
||||
main::c#3 = phi( main::@3/main::c#2 )
|
||||
SCREEN[main::i#2] = *main::c#3
|
||||
main::i#1 = ++ main::i#2
|
||||
main::c#1 = ++ main::c#3
|
||||
to:main::@3
|
||||
main::@5: scope:[main] from main::@3
|
||||
main::i#6 = phi( main::@3/main::i#3 )
|
||||
main::msg#4 = phi( main::@3/main::msg#5 )
|
||||
main::msg#1 = main::msg#4 + SIZEOF_POINTER
|
||||
to:main::@1
|
||||
main::@return: scope:[main] from main::@1
|
||||
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
|
||||
constant byte* $0[6] = "hello"
|
||||
constant byte* $1[6] = "cruel"
|
||||
constant byte* $2[6] = "world"
|
||||
constant void* const NUL = (void*)0
|
||||
constant byte* const SCREEN = (byte*)$400
|
||||
constant byte SIZEOF_POINTER = 2
|
||||
void __start()
|
||||
void main()
|
||||
bool~ main::$0
|
||||
bool~ main::$1
|
||||
byte* main::c
|
||||
byte* main::c#0
|
||||
byte* main::c#1
|
||||
byte* main::c#2
|
||||
byte* main::c#3
|
||||
byte main::i
|
||||
byte main::i#0
|
||||
byte main::i#1
|
||||
byte main::i#2
|
||||
byte main::i#3
|
||||
byte main::i#4
|
||||
byte main::i#5
|
||||
byte main::i#6
|
||||
byte** main::msg
|
||||
byte** main::msg#0
|
||||
byte** main::msg#1
|
||||
byte** main::msg#2
|
||||
byte** main::msg#3
|
||||
byte** main::msg#4
|
||||
byte** main::msg#5
|
||||
byte** main::msg#6
|
||||
constant byte** msgs[] = { $0, $1, $2, NUL }
|
||||
|
||||
Adding number conversion cast (unumber) 0 in main::$1 = 0 != *main::c#2
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant pointer cast (void*) 0
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias main::msg#2 = main::msg#3
|
||||
Alias main::i#4 = main::i#5
|
||||
Alias main::c#2 = main::c#3
|
||||
Alias main::i#2 = main::i#3 main::i#6
|
||||
Alias main::msg#4 = main::msg#6 main::msg#5
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values main::msg#4 main::msg#2
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition main::$0 [4] if((byte*)0!=*main::msg#2) goto main::@2
|
||||
Simple Condition main::$1 [8] if(0!=*main::c#2) goto main::@4
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant main::i#0 = 0
|
||||
Constant main::msg#0 = msgs
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
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
|
||||
Inlining constant with var siblings main::i#0
|
||||
Inlining constant with var siblings main::msg#0
|
||||
Constant inlined main::i#0 = 0
|
||||
Constant inlined main::msg#0 = msgs
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of main
|
||||
CALL GRAPH
|
||||
|
||||
Created 4 initial phi equivalence classes
|
||||
Coalesced [5] main::c#4 = main::c#0
|
||||
Coalesced [6] main::i#8 = main::i#4
|
||||
Coalesced [10] main::msg#7 = main::msg#1
|
||||
Coalesced (already) [11] main::i#7 = main::i#2
|
||||
Coalesced [15] main::c#5 = main::c#1
|
||||
Coalesced [16] main::i#9 = main::i#1
|
||||
Coalesced down to 3 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::@5
|
||||
[1] main::i#4 = phi( main/0, main::@5/main::i#2 )
|
||||
[1] main::msg#2 = phi( main/msgs, main::@5/main::msg#1 )
|
||||
[2] if((byte*)0!=*main::msg#2) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[4] main::c#0 = *main::msg#2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@4
|
||||
[5] main::i#2 = phi( main::@2/main::i#4, main::@4/main::i#1 )
|
||||
[5] main::c#2 = phi( main::@2/main::c#0, main::@4/main::c#1 )
|
||||
[6] if(0!=*main::c#2) goto main::@4
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@3
|
||||
[7] main::msg#1 = main::msg#2 + SIZEOF_POINTER
|
||||
to:main::@1
|
||||
main::@4: scope:[main] from main::@3
|
||||
[8] SCREEN[main::i#2] = *main::c#2
|
||||
[9] main::i#1 = ++ main::i#2
|
||||
[10] main::c#1 = ++ main::c#2
|
||||
to:main::@3
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
void main()
|
||||
byte* main::c
|
||||
byte* main::c#0 22.0
|
||||
byte* main::c#1 202.0
|
||||
byte* main::c#2 103.75
|
||||
byte main::i
|
||||
byte main::i#1 101.0
|
||||
byte main::i#2 81.25
|
||||
byte main::i#4 7.333333333333333
|
||||
byte** main::msg
|
||||
byte** main::msg#1 22.0
|
||||
byte** main::msg#2 5.5
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::msg#2 main::msg#1 ]
|
||||
[ main::i#4 main::i#2 main::i#1 ]
|
||||
[ main::c#2 main::c#0 main::c#1 ]
|
||||
Complete equivalence classes
|
||||
[ main::msg#2 main::msg#1 ]
|
||||
[ main::i#4 main::i#2 main::i#1 ]
|
||||
[ main::c#2 main::c#0 main::c#1 ]
|
||||
Allocated zp[2]:2 [ main::msg#2 main::msg#1 ]
|
||||
Allocated zp[1]:4 [ main::i#4 main::i#2 main::i#1 ]
|
||||
Allocated zp[2]:5 [ main::c#2 main::c#0 main::c#1 ]
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [2] if((byte*)0!=*main::msg#2) goto main::@2 [ main::msg#2 main::i#4 ] ( [ main::msg#2 main::i#4 ] { } ) always clobbers reg byte a reg byte y
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:4 [ main::i#4 main::i#2 main::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp[1]:4 [ main::i#4 main::i#2 main::i#1 ]
|
||||
Statement [4] main::c#0 = *main::msg#2 [ main::msg#2 main::i#4 main::c#0 ] ( [ main::msg#2 main::i#4 main::c#0 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [6] if(0!=*main::c#2) goto main::@4 [ main::msg#2 main::i#2 main::c#2 ] ( [ main::msg#2 main::i#2 main::c#2 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [7] main::msg#1 = main::msg#2 + SIZEOF_POINTER [ main::msg#1 main::i#2 ] ( [ main::msg#1 main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [8] SCREEN[main::i#2] = *main::c#2 [ main::msg#2 main::i#2 main::c#2 ] ( [ main::msg#2 main::i#2 main::c#2 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [2] if((byte*)0!=*main::msg#2) goto main::@2 [ main::msg#2 main::i#4 ] ( [ main::msg#2 main::i#4 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [4] main::c#0 = *main::msg#2 [ main::msg#2 main::i#4 main::c#0 ] ( [ main::msg#2 main::i#4 main::c#0 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [6] if(0!=*main::c#2) goto main::@4 [ main::msg#2 main::i#2 main::c#2 ] ( [ main::msg#2 main::i#2 main::c#2 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [7] main::msg#1 = main::msg#2 + SIZEOF_POINTER [ main::msg#1 main::i#2 ] ( [ main::msg#1 main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [8] SCREEN[main::i#2] = *main::c#2 [ main::msg#2 main::i#2 main::c#2 ] ( [ main::msg#2 main::i#2 main::c#2 ] { } ) always clobbers reg byte a reg byte y
|
||||
Potential registers zp[2]:2 [ main::msg#2 main::msg#1 ] : zp[2]:2 ,
|
||||
Potential registers zp[1]:4 [ main::i#4 main::i#2 main::i#1 ] : zp[1]:4 , reg byte x ,
|
||||
Potential registers zp[2]:5 [ main::c#2 main::c#0 main::c#1 ] : zp[2]:5 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 327.75: zp[2]:5 [ main::c#2 main::c#0 main::c#1 ] 189.58: zp[1]:4 [ main::i#4 main::i#2 main::i#1 ] 27.5: zp[2]:2 [ main::msg#2 main::msg#1 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 5641 combination zp[2]:5 [ main::c#2 main::c#0 main::c#1 ] reg byte x [ main::i#4 main::i#2 main::i#1 ] zp[2]:2 [ main::msg#2 main::msg#1 ]
|
||||
Uplifting [] best 5641 combination
|
||||
Allocated (was zp[2]:5) zp[2]:4 [ main::c#2 main::c#0 main::c#1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Tests literal string array
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="literal-string-array.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_POINTER = 2
|
||||
.label SCREEN = $400
|
||||
.label NUL = 0
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.label c = 4
|
||||
.label msg = 2
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [1] phi main::i#4 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [1] phi main::msg#2 = msgs [phi:main->main::@1#1] -- qbuz1=qbuc1
|
||||
lda #<msgs
|
||||
sta.z msg
|
||||
lda #>msgs
|
||||
sta.z msg+1
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [2] if((byte*)0!=*main::msg#2) goto main::@2 -- pbuc1_neq__deref_qbuz1_then_la1
|
||||
ldy #0
|
||||
lda #<0
|
||||
cmp (msg),y
|
||||
bne __b2
|
||||
iny
|
||||
lda #>0
|
||||
cmp (msg),y
|
||||
bne __b2
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [3] return
|
||||
rts
|
||||
// main::@2
|
||||
__b2:
|
||||
// [4] main::c#0 = *main::msg#2 -- pbuz1=_deref_qbuz2
|
||||
ldy #0
|
||||
lda (msg),y
|
||||
sta.z c
|
||||
iny
|
||||
lda (msg),y
|
||||
sta.z c+1
|
||||
// [5] phi from main::@2 main::@4 to main::@3 [phi:main::@2/main::@4->main::@3]
|
||||
__b3_from___b2:
|
||||
__b3_from___b4:
|
||||
// [5] phi main::i#2 = main::i#4 [phi:main::@2/main::@4->main::@3#0] -- register_copy
|
||||
// [5] phi main::c#2 = main::c#0 [phi:main::@2/main::@4->main::@3#1] -- register_copy
|
||||
jmp __b3
|
||||
// main::@3
|
||||
__b3:
|
||||
// [6] if(0!=*main::c#2) goto main::@4 -- 0_neq__deref_pbuz1_then_la1
|
||||
ldy #0
|
||||
lda (c),y
|
||||
cmp #0
|
||||
bne __b4
|
||||
jmp __b5
|
||||
// main::@5
|
||||
__b5:
|
||||
// [7] main::msg#1 = main::msg#2 + SIZEOF_POINTER -- qbuz1=qbuz1_plus_vbuc1
|
||||
lda #SIZEOF_POINTER
|
||||
clc
|
||||
adc.z msg
|
||||
sta.z msg
|
||||
bcc !+
|
||||
inc.z msg+1
|
||||
!:
|
||||
// [1] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
|
||||
__b1_from___b5:
|
||||
// [1] phi main::i#4 = main::i#2 [phi:main::@5->main::@1#0] -- register_copy
|
||||
// [1] phi main::msg#2 = main::msg#1 [phi:main::@5->main::@1#1] -- register_copy
|
||||
jmp __b1
|
||||
// main::@4
|
||||
__b4:
|
||||
// [8] SCREEN[main::i#2] = *main::c#2 -- pbuc1_derefidx_vbuxx=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (c),y
|
||||
sta SCREEN,x
|
||||
// [9] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [10] main::c#1 = ++ main::c#2 -- pbuz1=_inc_pbuz1
|
||||
inc.z c
|
||||
bne !+
|
||||
inc.z c+1
|
||||
!:
|
||||
jmp __b3_from___b4
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
// Works
|
||||
// char*[] msgs = { (char*)"hello", (char*)"cruel", (char*)"world", (char*)NUL };
|
||||
// Not working
|
||||
msgs: .word __0, __1, __2, NUL
|
||||
__0: .text "hello"
|
||||
.byte 0
|
||||
__1: .text "cruel"
|
||||
.byte 0
|
||||
__2: .text "world"
|
||||
.byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __breturn
|
||||
Removing instruction jmp __b3
|
||||
Removing instruction jmp __b5
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing instruction lda #<0 with TYA
|
||||
Removing instruction lda #>0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label __b3_from___b4 with __b3
|
||||
Removing instruction __b3_from___b2:
|
||||
Removing instruction __b3_from___b4:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b1_from_main:
|
||||
Removing instruction __breturn:
|
||||
Removing instruction __b5:
|
||||
Removing instruction __b1_from___b5:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
constant byte* $0[6] = "hello"
|
||||
constant byte* $1[6] = "cruel"
|
||||
constant byte* $2[6] = "world"
|
||||
constant void* const NUL = (void*) 0
|
||||
constant byte* const SCREEN = (byte*) 1024
|
||||
constant byte SIZEOF_POINTER = 2
|
||||
void main()
|
||||
byte* main::c
|
||||
byte* main::c#0 c zp[2]:4 22.0
|
||||
byte* main::c#1 c zp[2]:4 202.0
|
||||
byte* main::c#2 c zp[2]:4 103.75
|
||||
byte main::i
|
||||
byte main::i#1 reg byte x 101.0
|
||||
byte main::i#2 reg byte x 81.25
|
||||
byte main::i#4 reg byte x 7.333333333333333
|
||||
byte** main::msg
|
||||
byte** main::msg#1 msg zp[2]:2 22.0
|
||||
byte** main::msg#2 msg zp[2]:2 5.5
|
||||
constant byte** msgs[] = { $0, $1, $2, NUL }
|
||||
|
||||
zp[2]:2 [ main::msg#2 main::msg#1 ]
|
||||
reg byte x [ main::i#4 main::i#2 main::i#1 ]
|
||||
zp[2]:4 [ main::c#2 main::c#0 main::c#1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 4961
|
||||
|
||||
// File Comments
|
||||
// Tests literal string array
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="literal-string-array.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_POINTER = 2
|
||||
.label SCREEN = $400
|
||||
.label NUL = 0
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.label c = 4
|
||||
.label msg = 2
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [1] phi main::i#4 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [1] phi main::msg#2 = msgs [phi:main->main::@1#1] -- qbuz1=qbuc1
|
||||
lda #<msgs
|
||||
sta.z msg
|
||||
lda #>msgs
|
||||
sta.z msg+1
|
||||
// main::@1
|
||||
__b1:
|
||||
// while(*msg)
|
||||
// [2] if((byte*)0!=*main::msg#2) goto main::@2 -- pbuc1_neq__deref_qbuz1_then_la1
|
||||
ldy #0
|
||||
tya
|
||||
cmp (msg),y
|
||||
bne __b2
|
||||
iny
|
||||
cmp (msg),y
|
||||
bne __b2
|
||||
// main::@return
|
||||
// }
|
||||
// [3] return
|
||||
rts
|
||||
// main::@2
|
||||
__b2:
|
||||
// char* c = *msg
|
||||
// [4] main::c#0 = *main::msg#2 -- pbuz1=_deref_qbuz2
|
||||
ldy #0
|
||||
lda (msg),y
|
||||
sta.z c
|
||||
iny
|
||||
lda (msg),y
|
||||
sta.z c+1
|
||||
// [5] phi from main::@2 main::@4 to main::@3 [phi:main::@2/main::@4->main::@3]
|
||||
// [5] phi main::i#2 = main::i#4 [phi:main::@2/main::@4->main::@3#0] -- register_copy
|
||||
// [5] phi main::c#2 = main::c#0 [phi:main::@2/main::@4->main::@3#1] -- register_copy
|
||||
// main::@3
|
||||
__b3:
|
||||
// while(*c)
|
||||
// [6] if(0!=*main::c#2) goto main::@4 -- 0_neq__deref_pbuz1_then_la1
|
||||
ldy #0
|
||||
lda (c),y
|
||||
cmp #0
|
||||
bne __b4
|
||||
// main::@5
|
||||
// msg++;
|
||||
// [7] main::msg#1 = main::msg#2 + SIZEOF_POINTER -- qbuz1=qbuz1_plus_vbuc1
|
||||
lda #SIZEOF_POINTER
|
||||
clc
|
||||
adc.z msg
|
||||
sta.z msg
|
||||
bcc !+
|
||||
inc.z msg+1
|
||||
!:
|
||||
// [1] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
|
||||
// [1] phi main::i#4 = main::i#2 [phi:main::@5->main::@1#0] -- register_copy
|
||||
// [1] phi main::msg#2 = main::msg#1 [phi:main::@5->main::@1#1] -- register_copy
|
||||
jmp __b1
|
||||
// main::@4
|
||||
__b4:
|
||||
// SCREEN[i++] = *c++
|
||||
// [8] SCREEN[main::i#2] = *main::c#2 -- pbuc1_derefidx_vbuxx=_deref_pbuz1
|
||||
ldy #0
|
||||
lda (c),y
|
||||
sta SCREEN,x
|
||||
// SCREEN[i++] = *c++;
|
||||
// [9] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [10] main::c#1 = ++ main::c#2 -- pbuz1=_inc_pbuz1
|
||||
inc.z c
|
||||
bne !+
|
||||
inc.z c+1
|
||||
!:
|
||||
jmp __b3
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
// Works
|
||||
// char*[] msgs = { (char*)"hello", (char*)"cruel", (char*)"world", (char*)NUL };
|
||||
// Not working
|
||||
msgs: .word __0, __1, __2, NUL
|
||||
__0: .text "hello"
|
||||
.byte 0
|
||||
__1: .text "cruel"
|
||||
.byte 0
|
||||
__2: .text "world"
|
||||
.byte 0
|
||||
|
23
src/test/ref/literal-string-array.sym
Normal file
23
src/test/ref/literal-string-array.sym
Normal file
@ -0,0 +1,23 @@
|
||||
constant byte* $0[6] = "hello"
|
||||
constant byte* $1[6] = "cruel"
|
||||
constant byte* $2[6] = "world"
|
||||
constant void* const NUL = (void*) 0
|
||||
constant byte* const SCREEN = (byte*) 1024
|
||||
constant byte SIZEOF_POINTER = 2
|
||||
void main()
|
||||
byte* main::c
|
||||
byte* main::c#0 c zp[2]:4 22.0
|
||||
byte* main::c#1 c zp[2]:4 202.0
|
||||
byte* main::c#2 c zp[2]:4 103.75
|
||||
byte main::i
|
||||
byte main::i#1 reg byte x 101.0
|
||||
byte main::i#2 reg byte x 81.25
|
||||
byte main::i#4 reg byte x 7.333333333333333
|
||||
byte** main::msg
|
||||
byte** main::msg#1 msg zp[2]:2 22.0
|
||||
byte** main::msg#2 msg zp[2]:2 5.5
|
||||
constant byte** msgs[] = { $0, $1, $2, NUL }
|
||||
|
||||
zp[2]:2 [ main::msg#2 main::msg#1 ]
|
||||
reg byte x [ main::i#4 main::i#2 main::i#1 ]
|
||||
zp[2]:4 [ main::c#2 main::c#0 main::c#1 ]
|
@ -1,75 +1,76 @@
|
||||
// Example of a struct containing a pointer
|
||||
.pc = $801 "Basic"
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="struct-ptr-29.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.const SIZEOF_STRUCT_PERSON = 3
|
||||
.const OFFSET_STRUCT_PERSON_NAME = 1
|
||||
.label SCREEN = $400
|
||||
.label idx = 5
|
||||
.segment Code
|
||||
main: {
|
||||
// print_person(&persons[0])
|
||||
ldx #0
|
||||
lda #<persons
|
||||
sta.z print_person.person
|
||||
lda #>persons
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
// print_person(&persons[1])
|
||||
lda #<persons+1*SIZEOF_STRUCT_PERSON
|
||||
sta.z print_person.person
|
||||
lda #>persons+1*SIZEOF_STRUCT_PERSON
|
||||
sta.z print_person.person+1
|
||||
jsr print_person
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// print_person(struct Person* zeropage(2) person)
|
||||
// print_person(struct Person* zp(2) person)
|
||||
print_person: {
|
||||
.label i = 4
|
||||
.label person = 2
|
||||
// SCREEN[idx++] = DIGIT[person->id]
|
||||
ldy #0
|
||||
lda (person),y
|
||||
tay
|
||||
lda DIGIT,y
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = DIGIT[person->id];
|
||||
inx
|
||||
// SCREEN[idx++] = ' '
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = ' ';
|
||||
inx
|
||||
stx.z idx
|
||||
lda #0
|
||||
sta.z i
|
||||
__b1:
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
cmp #0
|
||||
bne __b2
|
||||
// for(byte i=0; person->name[i]; i++)
|
||||
.assert "Missing ASM fragment Fragment not found 0_neq_(qbuz1_derefidx_vbuc1)_derefidx_vbuz2_then_la1. Attempted variations 0_neq_(qbuz1_derefidx_vbuc1)_derefidx_vbuz2_then_la1 0_neq_(qbuz1_derefidx_vbsc1)_derefidx_vbuz2_then_la1 0_neq_(qbuz1_derefidx_vwuc1)_derefidx_vbuz2_then_la1 0_neq_(qbuz1_derefidx_vwsc1)_derefidx_vbuz2_then_la1 0_neq_(qbuz1_derefidx_vduc1)_derefidx_vbuz2_then_la1 0_neq_(qbuz1_derefidx_vdsc1)_derefidx_vbuz2_then_la1 ", 0, 1
|
||||
// SCREEN[idx++] = ' '
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// SCREEN[idx++] = ' ';
|
||||
inx
|
||||
// }
|
||||
rts
|
||||
__b2:
|
||||
ldy #OFFSET_STRUCT_PERSON_NAME
|
||||
lda (person),y
|
||||
sta.z $fe
|
||||
iny
|
||||
lda (person),y
|
||||
sta.z $ff
|
||||
ldy.z i
|
||||
lda ($fe),y
|
||||
sta SCREEN,x
|
||||
inx
|
||||
inc.z i
|
||||
jmp __b1
|
||||
// SCREEN[idx++] = person->name[i]
|
||||
// SCREEN[idx++] = person->name[i];
|
||||
// for(byte i=0; person->name[i]; i++)
|
||||
}
|
||||
.segment Data
|
||||
persons: .byte 4
|
||||
.word person_name
|
||||
.byte 7
|
||||
.word person_name1
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
__0: .text "jesper"
|
||||
person_name: .text "jesper"
|
||||
.byte 0
|
||||
__1: .text "repsej"
|
||||
person_name1: .text "repsej"
|
||||
.byte 0
|
||||
persons: .byte 4
|
||||
.word __0
|
||||
.byte 7
|
||||
.word __1
|
||||
|
@ -1,49 +1,40 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
[5] call print_person
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
[1] call print_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[6] phi()
|
||||
[7] call print_person
|
||||
[2] phi()
|
||||
[3] call print_person
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[8] return
|
||||
[4] return
|
||||
to:@return
|
||||
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
void print_person(struct Person* print_person::person)
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
[9] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
|
||||
[9] (struct Person*) print_person::person#2 ← phi( main/(const struct Person[2]) persons main::@1/(const struct Person[2]) persons+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON )
|
||||
[10] *((const byte*) SCREEN + (byte) idx#13) ← *((const byte[]) DIGIT + *((byte*)(struct Person*) print_person::person#2))
|
||||
[11] (byte) idx#4 ← ++ (byte) idx#13
|
||||
[12] *((const byte*) SCREEN + (byte) idx#4) ← (byte) ' '
|
||||
[13] (byte) idx#5 ← ++ (byte) idx#4
|
||||
[5] idx#14 = phi( main/0, main::@1/idx#17 )
|
||||
[5] print_person::person#2 = phi( main/persons, main::@1/persons+1*SIZEOF_STRUCT_PERSON )
|
||||
[6] SCREEN[idx#14] = DIGIT[*((byte*)print_person::person#2)]
|
||||
[7] idx#3 = ++ idx#14
|
||||
[8] SCREEN[idx#3] = ' '
|
||||
[9] idx#4 = ++ idx#3
|
||||
to:print_person::@1
|
||||
print_person::@1: scope:[print_person] from print_person print_person::@2
|
||||
[14] (byte) idx#14 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
|
||||
[14] (byte) print_person::i#2 ← phi( print_person/(byte) 0 print_person::@2/(byte) print_person::i#1 )
|
||||
[15] if((byte) 0!=*(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2
|
||||
[10] idx#15 = phi( print_person/idx#4, print_person::@2/idx#5 )
|
||||
[10] print_person::i#2 = phi( print_person/0, print_person::@2/print_person::i#1 )
|
||||
[11] if(0!=(((byte**)print_person::person#2)[OFFSET_STRUCT_PERSON_NAME])[print_person::i#2]) goto print_person::@2
|
||||
to:print_person::@3
|
||||
print_person::@3: scope:[print_person] from print_person::@1
|
||||
[16] *((const byte*) SCREEN + (byte) idx#14) ← (byte) ' '
|
||||
[17] (byte) idx#16 ← ++ (byte) idx#14
|
||||
[12] SCREEN[idx#15] = ' '
|
||||
[13] idx#17 = ++ idx#15
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
[18] return
|
||||
[14] return
|
||||
to:@return
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
[19] *((const byte*) SCREEN + (byte) idx#14) ← *(*((byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)
|
||||
[20] (byte) idx#6 ← ++ (byte) idx#14
|
||||
[21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
|
||||
[15] SCREEN[idx#15] = (((byte**)print_person::person#2)[OFFSET_STRUCT_PERSON_NAME])[print_person::i#2]
|
||||
[16] idx#5 = ++ idx#15
|
||||
[17] print_person::i#1 = ++ print_person::i#2
|
||||
to:print_person::@1
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,38 +1,27 @@
|
||||
(const string) $0 = (string) "jesper"
|
||||
(const string) $1 = (string) "repsej"
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte[]) DIGIT = (string) "0123456789"
|
||||
(const byte) OFFSET_STRUCT_PERSON_NAME = (byte) 1
|
||||
(byte) Person::id
|
||||
(byte*) Person::name
|
||||
(const byte*) SCREEN = (byte*) 1024
|
||||
(const byte) SIZEOF_STRUCT_PERSON = (byte) 3
|
||||
(byte) idx
|
||||
(byte) idx#13 reg byte x 3.0
|
||||
(byte) idx#14 reg byte x 9.75
|
||||
(byte) idx#16 reg byte x 1.0
|
||||
(byte) idx#4 reg byte x 3.0
|
||||
(byte) idx#5 reg byte x 4.0
|
||||
(byte) idx#6 reg byte x 11.0
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(const struct Person[2]) persons = { { id: (byte) 4, name: (const string) $0 }, { id: (byte) 7, name: (const string) $1 } }
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(label) print_person::@1
|
||||
(label) print_person::@2
|
||||
(label) print_person::@3
|
||||
(label) print_person::@return
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#1 i zp[1]:4 22.0
|
||||
(byte) print_person::i#2 i zp[1]:4 11.0
|
||||
(struct Person*) print_person::person
|
||||
(struct Person*) print_person::person#2 person zp[2]:2
|
||||
constant byte* DIGIT[] = "0123456789"
|
||||
constant byte OFFSET_STRUCT_PERSON_NAME = 1
|
||||
constant byte* const SCREEN = (byte*) 1024
|
||||
constant byte SIZEOF_STRUCT_PERSON = 3
|
||||
byte idx
|
||||
byte idx#14 reg byte x 12.0
|
||||
byte idx#15 idx zp[1]:5 84.0
|
||||
byte idx#17 reg byte x 3.25
|
||||
byte idx#3 reg byte x 16.5
|
||||
byte idx#4 idx zp[1]:5 22.0
|
||||
byte idx#5 idx zp[1]:5 101.0
|
||||
void main()
|
||||
constant byte* person_name[7] = "jesper"
|
||||
constant byte* person_name1[7] = "repsej"
|
||||
constant struct Person* persons[2] = { { id: 4, name: person_name }, { id: 7, name: person_name1 } }
|
||||
void print_person(struct Person* print_person::person)
|
||||
byte print_person::i
|
||||
byte print_person::i#1 i zp[1]:4 202.0
|
||||
byte print_person::i#2 i zp[1]:4 101.0
|
||||
struct Person* print_person::person
|
||||
struct Person* print_person::person#2 person zp[2]:2
|
||||
|
||||
zp[2]:2 [ print_person::person#2 ]
|
||||
reg byte x [ idx#13 idx#16 ]
|
||||
reg byte x [ idx#14 idx#17 ]
|
||||
zp[1]:4 [ print_person::i#2 print_person::i#1 ]
|
||||
reg byte x [ idx#14 idx#5 idx#6 ]
|
||||
reg byte x [ idx#4 ]
|
||||
zp[1]:5 [ idx#15 idx#4 idx#5 ]
|
||||
reg byte x [ idx#3 ]
|
||||
|
Loading…
Reference in New Issue
Block a user