mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-16 08:33:37 +00:00
Fixed double emitting of strings inside arrays inside structs. Closes #312
This commit is contained in:
parent
edb12d8577
commit
4f6908ac80
@ -364,6 +364,7 @@ public class Compiler {
|
||||
constantOptimizations.add(new Pass2NopCastInlining(program));
|
||||
constantOptimizations.add(new Pass2MultiplyToShiftRewriting(program));
|
||||
constantOptimizations.add(new Pass2ConstantInlining(program));
|
||||
constantOptimizations.add(new Pass2ArrayInStructInlining(program));
|
||||
constantOptimizations.add(new Pass2ConstantAdditionElimination(program));
|
||||
constantOptimizations.add(new Pass2ConstantSimplification(program));
|
||||
constantOptimizations.addAll(getPass2Optimizations());
|
||||
|
@ -477,6 +477,10 @@ public interface ProgramValue {
|
||||
public void set(Value value) {
|
||||
structValue.setValue(memberRef, (ConstantValue) value);
|
||||
}
|
||||
|
||||
public VariableRef getMemberRef() {
|
||||
return memberRef;
|
||||
}
|
||||
}
|
||||
|
||||
/** Value inside a constant array filled expression. */
|
||||
|
@ -0,0 +1,80 @@
|
||||
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.symbols.ConstantVar;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeArray;
|
||||
import dk.camelot64.kickc.model.values.ConstantRef;
|
||||
import dk.camelot64.kickc.model.values.ConstantValue;
|
||||
import dk.camelot64.kickc.model.values.Value;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Compiler Pass inlining arrays inside literal structs
|
||||
*/
|
||||
public class Pass2ArrayInStructInlining extends Pass2SsaOptimization {
|
||||
|
||||
public Pass2ArrayInStructInlining(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
* Consolidate unnamed constants into other constants value
|
||||
*
|
||||
* @return true optimization was performed. false if no optimization was possible.
|
||||
*/
|
||||
@Override
|
||||
public boolean step() {
|
||||
Map<ConstantRef, ConstantValue> inline = new HashMap<>();
|
||||
inline.putAll(findArrayInStruct());
|
||||
|
||||
// Replace all usages of the constants in the control flow graph or symbol table
|
||||
replaceVariables(inline);
|
||||
// Remove from symbol table
|
||||
deleteSymbols(getScope(), inline.keySet());
|
||||
|
||||
for(ConstantRef constantRef : inline.keySet()) {
|
||||
getLog().append("Constant array inlined into struct " + constantRef.toString() + " = " + inline.get(constantRef).toString(getProgram()));
|
||||
}
|
||||
|
||||
return inline.size() > 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Find constant fixed size arrays inside structs.
|
||||
*
|
||||
* @return Map from constant name to constant value
|
||||
*/
|
||||
private Map<ConstantRef, ConstantValue> findArrayInStruct() {
|
||||
Map<ConstantRef, ConstantValue> inline = new HashMap<>();
|
||||
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
||||
Value value = programValue.get();
|
||||
if(programValue instanceof ProgramValue.ProgramValueConstantStructMember) {
|
||||
VariableRef memberRef = ((ProgramValue.ProgramValueConstantStructMember) programValue).getMemberRef();
|
||||
Variable structMemberVar = getScope().getVariable(memberRef);
|
||||
if(structMemberVar.getType() instanceof SymbolTypeArray) {
|
||||
if(((SymbolTypeArray) structMemberVar.getType()).getSize() != null) {
|
||||
if(value instanceof ConstantValue) {
|
||||
ConstantValue constantValue = (ConstantValue) value;
|
||||
if(constantValue.getType(getProgram().getScope()).equals(SymbolType.STRING)) {
|
||||
if(constantValue instanceof ConstantRef) {
|
||||
ConstantVar constantStringVar = getScope().getConstant((ConstantRef) constantValue);
|
||||
inline.put((ConstantRef) constantValue, constantStringVar.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return inline;
|
||||
}
|
||||
|
||||
}
|
@ -231,17 +231,6 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
|
||||
static ConstantValue createBinary(ConstantValue c1, OperatorBinary operator, ConstantValue c2, ProgramScope programScope) {
|
||||
|
||||
// Special handling of string append using +
|
||||
if(Operators.PLUS.equals(operator) && SymbolType.STRING.equals(c1.getType(programScope))) {
|
||||
if(c1 instanceof ConstantRef) {
|
||||
c1 = programScope.getConstant((ConstantRef) c1).getValue();
|
||||
}
|
||||
if(c2 instanceof ConstantRef) {
|
||||
c2 = programScope.getConstant((ConstantRef) c2).getValue();
|
||||
}
|
||||
return new ConstantBinary(c1, operator, c2);
|
||||
}
|
||||
|
||||
if(Operators.PLUS.equals(operator)) {
|
||||
return new ConstantBinary(c1, operator, c2);
|
||||
}
|
||||
|
@ -36,8 +36,7 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
|
||||
@Override
|
||||
public boolean step() {
|
||||
Map<ConstantRef, ConstantValue> inline = new HashMap<>();
|
||||
Map<ConstantRef, ConstantValue> aliasConstants = findAliasConstants();
|
||||
inline.putAll(aliasConstants);
|
||||
inline.putAll(findAliasConstants());
|
||||
inline.putAll(findUnnamedConstants());
|
||||
inline.putAll(findConstVarVersions());
|
||||
|
||||
|
@ -655,9 +655,14 @@ public class TestPrograms {
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testStructPtr34() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-ptr-34");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructPtr33() throws IOException, URISyntaxException {
|
||||
compileAndCompare("struct-ptr-33", log());
|
||||
compileAndCompare("struct-ptr-33");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -5,12 +5,9 @@ struct Person {
|
||||
char* name;
|
||||
};
|
||||
|
||||
char* name1 = "jesper";
|
||||
char* name2 = "repsej";
|
||||
|
||||
struct Person[2] persons = {
|
||||
{ 4, name1 },
|
||||
{ 7, name2 }
|
||||
{ 4, "jesper" },
|
||||
{ 7, "repsej" }
|
||||
};
|
||||
|
||||
void main() {
|
||||
|
29
src/test/kc/struct-ptr-34.kc
Normal file
29
src/test/kc/struct-ptr-34.kc
Normal file
@ -0,0 +1,29 @@
|
||||
// Example of a struct containing an array
|
||||
|
||||
struct Person {
|
||||
char id;
|
||||
char[16] name;
|
||||
};
|
||||
|
||||
void main() {
|
||||
struct Person jesper = { 4, "jesper" };
|
||||
print_person(jesper);
|
||||
|
||||
struct Person henriette = { 7, "henriette" };
|
||||
print_person(henriette);
|
||||
}
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
char idx = 0;
|
||||
char[] DIGIT = "0123456789";
|
||||
|
||||
void print_person(struct Person person) {
|
||||
SCREEN[idx++] = DIGIT[person.id];
|
||||
SCREEN[idx++] = ' ';
|
||||
for(byte i=0; person.name[i]; i++)
|
||||
SCREEN[idx++] = person.name[i];
|
||||
SCREEN[idx++] = ' ';
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,10 +65,6 @@ print_person: {
|
||||
inx
|
||||
rts
|
||||
}
|
||||
_0: .text "jgr"
|
||||
.byte 0
|
||||
_1: .text "hbg"
|
||||
.byte 0
|
||||
persons: .byte 1
|
||||
.text "jgr"
|
||||
.byte 0, 8
|
||||
|
@ -208,6 +208,9 @@ Constant inlined print_person::person#0 = (const struct Person[]) persons#0
|
||||
Constant inlined main::person#0 = (const struct Person[]) persons#0
|
||||
Constant inlined print_person::person#1 = (const struct Person*) main::person#1
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Constant array inlined into struct $0 = (string) "jgr"
|
||||
Constant array inlined into struct $1 = (string) "hbg"
|
||||
Successful SSA optimization Pass2ArrayInStructInlining
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
@ -490,10 +493,6 @@ print_person: {
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
_0: .text "jgr"
|
||||
.byte 0
|
||||
_1: .text "hbg"
|
||||
.byte 0
|
||||
persons: .byte 1
|
||||
.text "jgr"
|
||||
.byte 0, 8
|
||||
@ -682,10 +681,6 @@ print_person: {
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
_0: .text "jgr"
|
||||
.byte 0
|
||||
_1: .text "hbg"
|
||||
.byte 0
|
||||
persons: .byte 1
|
||||
.text "jgr"
|
||||
.byte 0, 8
|
||||
@ -720,8 +715,6 @@ Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(const string) $0 $0 = (string) "jgr"
|
||||
(const string) $1 $1 = (string) "hbg"
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
@ -745,7 +738,7 @@ FINAL SYMBOL TABLE
|
||||
(struct Person*) main::person
|
||||
(const struct Person*) main::person#1 person = (const struct Person[]) persons#0+(const byte) SIZEOF_STRUCT_PERSON
|
||||
(struct Person[]) persons
|
||||
(const struct Person[]) persons#0 persons = { { id: (byte) 1, initials: (const string) $0 }, { id: (byte) 8, initials: (const string) $1 } }
|
||||
(const struct Person[]) persons#0 persons = { { id: (byte) 1, initials: (string) "jgr" }, { id: (byte) 8, initials: (string) "hbg" } }
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(byte~) print_person::$0 reg byte a 4.0
|
||||
(byte[4]) print_person::$3 $3 zp ZP_WORD:4 4.0
|
||||
@ -894,10 +887,6 @@ print_person: {
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
_0: .text "jgr"
|
||||
.byte 0
|
||||
_1: .text "hbg"
|
||||
.byte 0
|
||||
persons: .byte 1
|
||||
.text "jgr"
|
||||
.byte 0, 8
|
||||
|
@ -1,5 +1,3 @@
|
||||
(const string) $0 $0 = (string) "jgr"
|
||||
(const string) $1 $1 = (string) "hbg"
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
@ -23,7 +21,7 @@
|
||||
(struct Person*) main::person
|
||||
(const struct Person*) main::person#1 person = (const struct Person[]) persons#0+(const byte) SIZEOF_STRUCT_PERSON
|
||||
(struct Person[]) persons
|
||||
(const struct Person[]) persons#0 persons = { { id: (byte) 1, initials: (const string) $0 }, { id: (byte) 8, initials: (const string) $1 } }
|
||||
(const struct Person[]) persons#0 persons = { { id: (byte) 1, initials: (string) "jgr" }, { id: (byte) 8, initials: (string) "hbg" } }
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(byte~) print_person::$0 reg byte a 4.0
|
||||
(byte[4]) print_person::$3 $3 zp ZP_WORD:4 4.0
|
||||
|
@ -63,13 +63,13 @@ print_person: {
|
||||
inc.z i
|
||||
jmp b1
|
||||
}
|
||||
name1: .text "jesper"
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
name2: .text "repsej"
|
||||
.byte 0
|
||||
DIGIT: .text "0123456789"
|
||||
_1: .text "repsej"
|
||||
.byte 0
|
||||
persons: .byte 4
|
||||
.word name1
|
||||
.word _0
|
||||
.byte 7
|
||||
.word name2
|
||||
.word _1
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
|
@ -4,17 +4,13 @@ Rewriting struct pointer member access *((struct Person*) print_person::person).
|
||||
Rewriting struct pointer member access *((struct Person*) print_person::person).name
|
||||
Rewriting struct pointer member access *((struct Person*) print_person::person).name
|
||||
Warning! Adding boolean cast to non-boolean condition *(*((byte**) print_person::$1) + (byte) print_person::i)
|
||||
Identified constant variable (byte*) name1
|
||||
Identified constant variable (byte*) name2
|
||||
Culled Empty Block (label) print_person::@4
|
||||
Culled Empty Block (label) print_person::@5
|
||||
Culled Empty Block (label) print_person::@6
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte*) name1#0 ← (const string) $0
|
||||
(byte*) name2#0 ← (const string) $1
|
||||
(struct Person[2]) persons#0 ← { { (number) 4, (byte*) name1#0 }, { (number) 7, (byte*) name2#0 } }
|
||||
(struct Person[2]) persons#0 ← { { (number) 4, (const string) $0 }, { (number) 7, (const string) $1 } }
|
||||
to:@1
|
||||
main: scope:[main] from @2
|
||||
(byte) idx#18 ← phi( @2/(byte) idx#20 )
|
||||
@ -140,10 +136,6 @@ SYMBOL TABLE SSA
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte*) name1
|
||||
(byte*) name1#0
|
||||
(byte*) name2
|
||||
(byte*) name2#0
|
||||
(struct Person[2]) persons
|
||||
(struct Person[2]) persons#0
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
@ -175,7 +167,7 @@ Adding number conversion cast (unumber) 0 in (byte) idx#3 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (byte) print_person::i#0 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (bool~) print_person::$3 ← (number) 0 != *(*((byte**) print_person::$1) + (byte) print_person::i#2)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Added casts to value list in (struct Person[2]) persons#0 ← (struct Person[2]){ (struct Person){ (byte)(number) 4, (byte*) name1#0 }, (struct Person){ (byte)(number) 7, (byte*) name2#0 } }
|
||||
Added casts to value list in (struct Person[2]) persons#0 ← (struct Person[2]){ (struct Person){ (byte)(number) 4, (const string) $0 }, (struct Person){ (byte)(number) 7, (const string) $1 } }
|
||||
Successful SSA optimization PassNAddInitializerValueListTypeCasts
|
||||
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
|
||||
Inlining cast (byte) idx#3 ← (unumber)(number) 0
|
||||
@ -215,16 +207,20 @@ Identical Phi Values (byte) idx#1 (byte) idx#16
|
||||
Identical Phi Values (struct Person*) print_person::person#3 (struct Person*) print_person::person#2
|
||||
Identical Phi Values (byte) idx#17 (byte) idx#1
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition (bool~) print_person::$3 [32] if((byte) 0!=*(*((byte**) print_person::$1) + (byte) print_person::i#2)) goto print_person::@2
|
||||
Simple Condition (bool~) print_person::$3 [30] if((byte) 0!=*(*((byte**) print_person::$1) + (byte) print_person::i#2)) goto print_person::@2
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Rewriting array member address-of to pointer addition [5] (struct Person*) print_person::person#0 ← (struct Person[2]) persons#0 + (byte~) main::$4
|
||||
Rewriting array member address-of to pointer addition [11] (struct Person*) print_person::person#1 ← (struct Person[2]) persons#0 + (byte~) main::$5
|
||||
Rewriting array member address-of to pointer addition [3] (struct Person*) print_person::person#0 ← (struct Person[2]) persons#0 + (byte~) main::$4
|
||||
Rewriting array member address-of to pointer addition [9] (struct Person*) print_person::person#1 ← (struct Person[2]) persons#0 + (byte~) main::$5
|
||||
Successful SSA optimization PassNArrayElementAddressOfRewriting
|
||||
Constant right-side identified [4] (byte~) main::$4 ← (byte) 0 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Constant right-side identified [10] (byte~) main::$5 ← (byte) 1 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Constant right-side identified [2] (byte~) main::$4 ← (byte) 0 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Constant right-side identified [8] (byte~) main::$5 ← (byte) 1 * (const byte) SIZEOF_STRUCT_PERSON
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) name1#0 = $0
|
||||
Constant (const byte*) name2#0 = $1
|
||||
Identified constant from value list (struct Person) { id: (byte) 4, name: (const string) $0 }
|
||||
Identified constant from value list (struct Person) { id: (byte) 7, name: (const string) $1 }
|
||||
Successful SSA optimization Pass2ConstantInitializerValueLists
|
||||
Identified constant from value list (struct Person[2]) { { id: (byte) 4, name: (const string) $0 }, { id: (byte) 7, name: (const string) $1 } }
|
||||
Successful SSA optimization Pass2ConstantInitializerValueLists
|
||||
Constant (const struct Person[2]) persons#0 = { { id: 4, name: $0 }, { id: 7, name: $1 } }
|
||||
Constant (const byte) main::$4 = 0*SIZEOF_STRUCT_PERSON
|
||||
Constant (const byte) main::$5 = 1*SIZEOF_STRUCT_PERSON
|
||||
Constant (const byte*) SCREEN#0 = (byte*) 1024
|
||||
@ -232,45 +228,35 @@ Constant (const byte) idx#20 = 0
|
||||
Constant (const byte[]) DIGIT#0 = $2
|
||||
Constant (const byte) print_person::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Converting *(pointer+n) to pointer[n] [24] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*) print_person::$0)) -- *((byte*)print_person::person#2 + OFFSET_STRUCT_PERSON_ID)
|
||||
Converting *(pointer+n) to pointer[n] [32] if((byte) 0!=*(*((byte**) print_person::$1) + (byte) print_person::i#2)) goto print_person::@2 -- *((byte**)print_person::person#2 + OFFSET_STRUCT_PERSON_NAME)
|
||||
Converting *(pointer+n) to pointer[n] [35] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**) print_person::$2) + (byte) print_person::i#2) -- *((byte**)print_person::person#2 + OFFSET_STRUCT_PERSON_NAME)
|
||||
Converting *(pointer+n) to pointer[n] [22] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*) print_person::$0)) -- *((byte*)print_person::person#2 + OFFSET_STRUCT_PERSON_ID)
|
||||
Converting *(pointer+n) to pointer[n] [30] if((byte) 0!=*(*((byte**) print_person::$1) + (byte) print_person::i#2)) goto print_person::@2 -- *((byte**)print_person::person#2 + OFFSET_STRUCT_PERSON_NAME)
|
||||
Converting *(pointer+n) to pointer[n] [33] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte**) print_person::$2) + (byte) print_person::i#2) -- *((byte**)print_person::person#2 + OFFSET_STRUCT_PERSON_NAME)
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_STRUCT_PERSON in
|
||||
Successful SSA optimization PassNSimplifyConstantZero
|
||||
Simplifying expression containing zero persons#0 in [5] (struct Person*) print_person::person#0 ← (struct Person[2]) persons#0 + (const byte) main::$4
|
||||
Simplifying expression containing zero (byte*)print_person::person#2 in [23] (byte*) print_person::$0 ← (byte*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_ID
|
||||
Simplifying expression containing zero (byte*)print_person::person#2 in [24] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_ID))
|
||||
Simplifying expression containing zero persons#0 in [3] (struct Person*) print_person::person#0 ← (const struct Person[2]) persons#0 + (const byte) main::$4
|
||||
Simplifying expression containing zero (byte*)print_person::person#2 in [21] (byte*) print_person::$0 ← (byte*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_ID
|
||||
Simplifying expression containing zero (byte*)print_person::person#2 in [22] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_ID))
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable (byte*) print_person::$0 and assignment [7] (byte*) print_person::$0 ← (byte*)(struct Person*) print_person::person#2
|
||||
Eliminating unused variable (byte**) print_person::$1 and assignment [13] (byte**) print_person::$1 ← (byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME
|
||||
Eliminating unused variable (byte**) print_person::$2 and assignment [15] (byte**) print_person::$2 ← (byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME
|
||||
Eliminating unused variable (byte*) print_person::$0 and assignment [6] (byte*) print_person::$0 ← (byte*)(struct Person*) print_person::person#2
|
||||
Eliminating unused variable (byte**) print_person::$1 and assignment [12] (byte**) print_person::$1 ← (byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME
|
||||
Eliminating unused variable (byte**) print_person::$2 and assignment [14] (byte**) print_person::$2 ← (byte**)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME
|
||||
Eliminating unused constant (const byte) main::$4
|
||||
Eliminating unused constant (const byte) OFFSET_STRUCT_PERSON_ID
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Identified constant from value list (struct Person) { id: (byte) 4, name: (const byte*) name1#0 }
|
||||
Identified constant from value list (struct Person) { id: (byte) 7, name: (const byte*) name2#0 }
|
||||
Successful SSA optimization Pass2ConstantInitializerValueLists
|
||||
Identified constant from value list (struct Person[2]) { { id: (byte) 4, name: (const byte*) name1#0 }, { id: (byte) 7, name: (const byte*) name2#0 } }
|
||||
Successful SSA optimization Pass2ConstantInitializerValueLists
|
||||
Constant (const struct Person[2]) persons#0 = { { id: 4, name: name1#0 }, { id: 7, name: name2#0 } }
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const struct Person*) print_person::person#0 = persons#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant right-side identified [1] (struct Person*) print_person::person#1 ← (const struct Person[2]) persons#0 + (const byte) main::$5
|
||||
Constant right-side identified [2] (struct Person*) print_person::person#1 ← (const struct Person[2]) persons#0 + (const byte) main::$5
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const struct Person*) print_person::person#0 = persons#0
|
||||
Constant (const struct Person*) print_person::person#1 = persons#0+main::$5
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Inlining constant with var siblings (const byte) print_person::i#0
|
||||
Inlining constant with var siblings (const struct Person*) print_person::person#0
|
||||
Inlining constant with var siblings (const struct Person*) print_person::person#1
|
||||
Inlining constant with var siblings (const byte) idx#20
|
||||
Constant inlined idx#20 = (byte) 0
|
||||
Constant inlined print_person::i#0 = (byte) 0
|
||||
Constant inlined main::$5 = (byte) 1*(const byte) SIZEOF_STRUCT_PERSON
|
||||
Constant inlined idx#20 = (byte) 0
|
||||
Constant inlined print_person::person#0 = (const struct Person[2]) persons#0
|
||||
Constant inlined $0 = (const byte*) name1#0
|
||||
Constant inlined $1 = (const byte*) name2#0
|
||||
Constant inlined print_person::i#0 = (byte) 0
|
||||
Constant inlined $2 = (const byte[]) DIGIT#0
|
||||
Constant inlined print_person::person#1 = (const struct Person[2]) persons#0+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
@ -362,8 +348,6 @@ VARIABLE REGISTER WEIGHTS
|
||||
(byte) idx#5 4.0
|
||||
(byte) idx#6 11.0
|
||||
(void()) main()
|
||||
(byte*) name1
|
||||
(byte*) name2
|
||||
(struct Person[2]) persons
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(byte) print_person::i
|
||||
@ -543,16 +527,16 @@ print_person: {
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
name1: .text "jesper"
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
name2: .text "repsej"
|
||||
.byte 0
|
||||
DIGIT: .text "0123456789"
|
||||
_1: .text "repsej"
|
||||
.byte 0
|
||||
persons: .byte 4
|
||||
.word name1
|
||||
.word _0
|
||||
.byte 7
|
||||
.word name2
|
||||
.word _1
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) [ print_person::person#2 idx#13 ] ( main:2::print_person:5 [ print_person::person#2 idx#13 ] main:2::print_person:7 [ print_person::person#2 idx#13 ] ) always clobbers reg byte a reg byte y
|
||||
@ -727,16 +711,16 @@ print_person: {
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
name1: .text "jesper"
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
name2: .text "repsej"
|
||||
.byte 0
|
||||
DIGIT: .text "0123456789"
|
||||
_1: .text "repsej"
|
||||
.byte 0
|
||||
persons: .byte 4
|
||||
.word name1
|
||||
.word _0
|
||||
.byte 7
|
||||
.word name2
|
||||
.word _1
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
@ -770,6 +754,8 @@ Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(const string) $0 $0 = (string) "jesper"
|
||||
(const string) $1 $1 = (string) "repsej"
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
@ -791,12 +777,8 @@ FINAL SYMBOL TABLE
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte*) name1
|
||||
(const byte*) name1#0 name1 = (string) "jesper"
|
||||
(byte*) name2
|
||||
(const byte*) name2#0 name2 = (string) "repsej"
|
||||
(struct Person[2]) persons
|
||||
(const struct Person[2]) persons#0 persons = { { id: (byte) 4, name: (const byte*) name1#0 }, { id: (byte) 7, name: (const byte*) name2#0 } }
|
||||
(const struct Person[2]) persons#0 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
|
||||
@ -943,14 +925,14 @@ print_person: {
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
name1: .text "jesper"
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
name2: .text "repsej"
|
||||
.byte 0
|
||||
DIGIT: .text "0123456789"
|
||||
_1: .text "repsej"
|
||||
.byte 0
|
||||
persons: .byte 4
|
||||
.word name1
|
||||
.word _0
|
||||
.byte 7
|
||||
.word name2
|
||||
.word _1
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
(const string) $0 $0 = (string) "jesper"
|
||||
(const string) $1 $1 = (string) "repsej"
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
@ -19,12 +21,8 @@
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(byte*) name1
|
||||
(const byte*) name1#0 name1 = (string) "jesper"
|
||||
(byte*) name2
|
||||
(const byte*) name2#0 name2 = (string) "repsej"
|
||||
(struct Person[2]) persons
|
||||
(const struct Person[2]) persons#0 persons = { { id: (byte) 4, name: (const byte*) name1#0 }, { id: (byte) 7, name: (const byte*) name2#0 } }
|
||||
(const struct Person[2]) persons#0 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
|
||||
|
@ -63,10 +63,6 @@ print_person: {
|
||||
iny
|
||||
jmp b1
|
||||
}
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
_1: .text "henriette"
|
||||
.byte 0
|
||||
persons: .byte 4
|
||||
.text "jesper"
|
||||
.byte 0
|
||||
|
@ -239,6 +239,9 @@ Constant inlined print_person::i#0 = (byte) 0
|
||||
Constant inlined $2 = (const byte[]) DIGIT#0
|
||||
Constant inlined print_person::person#1 = (const struct Person[]) persons#0+(byte) 1*(const byte) SIZEOF_STRUCT_PERSON
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Constant array inlined into struct $0 = (string) "jesper"
|
||||
Constant array inlined into struct $1 = (string) "henriette"
|
||||
Successful SSA optimization Pass2ArrayInStructInlining
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
@ -522,10 +525,6 @@ print_person: {
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
_1: .text "henriette"
|
||||
.byte 0
|
||||
persons: .byte 4
|
||||
.text "jesper"
|
||||
.byte 0
|
||||
@ -715,10 +714,6 @@ print_person: {
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
_1: .text "henriette"
|
||||
.byte 0
|
||||
persons: .byte 4
|
||||
.text "jesper"
|
||||
.byte 0
|
||||
@ -762,8 +757,6 @@ Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(const string) $0 $0 = (string) "jesper"
|
||||
(const string) $1 $1 = (string) "henriette"
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
@ -786,7 +779,7 @@ FINAL SYMBOL TABLE
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(struct Person[]) persons
|
||||
(const struct Person[]) persons#0 persons = { { id: (byte) 4, name: (const string) $0 }, { id: (byte) 7, name: (const string) $1 } }
|
||||
(const struct Person[]) persons#0 persons = { { id: (byte) 4, name: (string) "jesper" }, { id: (byte) 7, name: (string) "henriette" } }
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(byte[$10]) print_person::$1 $1 zp ZP_WORD:4 22.0
|
||||
(byte[$10]) print_person::$2 $2 zp ZP_WORD:6 22.0
|
||||
@ -939,10 +932,6 @@ print_person: {
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
_1: .text "henriette"
|
||||
.byte 0
|
||||
persons: .byte 4
|
||||
.text "jesper"
|
||||
.byte 0
|
||||
|
@ -1,5 +1,3 @@
|
||||
(const string) $0 $0 = (string) "jesper"
|
||||
(const string) $1 $1 = (string) "henriette"
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
@ -22,7 +20,7 @@
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(struct Person[]) persons
|
||||
(const struct Person[]) persons#0 persons = { { id: (byte) 4, name: (const string) $0 }, { id: (byte) 7, name: (const string) $1 } }
|
||||
(const struct Person[]) persons#0 persons = { { id: (byte) 4, name: (string) "jesper" }, { id: (byte) 7, name: (string) "henriette" } }
|
||||
(void()) print_person((struct Person*) print_person::person)
|
||||
(byte[$10]) print_person::$1 $1 zp ZP_WORD:4 22.0
|
||||
(byte[$10]) print_person::$2 $2 zp ZP_WORD:6 22.0
|
||||
|
@ -13,10 +13,6 @@ main: {
|
||||
sta SCREEN+1
|
||||
rts
|
||||
}
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
_1: .text "henry"
|
||||
.byte 0
|
||||
persons: .byte 7
|
||||
.text "jesper"
|
||||
.byte 0
|
||||
|
@ -106,6 +106,9 @@ Constant inlined main::$1 = (byte[$d])(const struct Person*) main::person#1+(con
|
||||
Constant inlined main::person#0 = (const struct Person[2]) persons#0
|
||||
Constant inlined main::$0 = (byte[$d])(const struct Person[2]) persons#0+(const byte) OFFSET_STRUCT_PERSON_NAME
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Constant array inlined into struct $0 = (string) "jesper"
|
||||
Constant array inlined into struct $1 = (string) "henry"
|
||||
Successful SSA optimization Pass2ArrayInStructInlining
|
||||
Consolidated array index constant in *((byte[$d])persons#0+OFFSET_STRUCT_PERSON_NAME+2)
|
||||
Consolidated array index constant in *((byte[$d])main::person#1+OFFSET_STRUCT_PERSON_NAME+2)
|
||||
Consolidated array index constant in *(main::SCREEN#0+1)
|
||||
@ -197,10 +200,6 @@ main: {
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
_1: .text "henry"
|
||||
.byte 0
|
||||
persons: .byte 7
|
||||
.text "jesper"
|
||||
.byte 0
|
||||
@ -266,10 +265,6 @@ main: {
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
_1: .text "henry"
|
||||
.byte 0
|
||||
persons: .byte 7
|
||||
.text "jesper"
|
||||
.byte 0
|
||||
@ -300,8 +295,6 @@ Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(const string) $0 $0 = (string) "jesper"
|
||||
(const string) $1 $1 = (string) "henry"
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
@ -317,7 +310,7 @@ FINAL SYMBOL TABLE
|
||||
(struct Person*) main::person
|
||||
(const struct Person*) main::person#1 person = (const struct Person[2]) persons#0+(const byte) SIZEOF_STRUCT_PERSON
|
||||
(struct Person[2]) persons
|
||||
(const struct Person[2]) persons#0 persons = { { id: (byte) 7, name: (const string) $0, age: (word) $141 }, { id: (byte) 9, name: (const string) $1, age: (word) $7b } }
|
||||
(const struct Person[2]) persons#0 persons = { { id: (byte) 7, name: (string) "jesper", age: (word) $141 }, { id: (byte) 9, name: (string) "henry", age: (word) $7b } }
|
||||
|
||||
|
||||
|
||||
@ -357,10 +350,6 @@ main: {
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
_0: .text "jesper"
|
||||
.byte 0
|
||||
_1: .text "henry"
|
||||
.byte 0
|
||||
persons: .byte 7
|
||||
.text "jesper"
|
||||
.byte 0
|
||||
|
@ -1,5 +1,3 @@
|
||||
(const string) $0 $0 = (string) "jesper"
|
||||
(const string) $1 $1 = (string) "henry"
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
@ -15,5 +13,5 @@
|
||||
(struct Person*) main::person
|
||||
(const struct Person*) main::person#1 person = (const struct Person[2]) persons#0+(const byte) SIZEOF_STRUCT_PERSON
|
||||
(struct Person[2]) persons
|
||||
(const struct Person[2]) persons#0 persons = { { id: (byte) 7, name: (const string) $0, age: (word) $141 }, { id: (byte) 9, name: (const string) $1, age: (word) $7b } }
|
||||
(const struct Person[2]) persons#0 persons = { { id: (byte) 7, name: (string) "jesper", age: (word) $141 }, { id: (byte) 9, name: (string) "henry", age: (word) $7b } }
|
||||
|
||||
|
62
src/test/ref/struct-ptr-34.asm
Normal file
62
src/test/ref/struct-ptr-34.asm
Normal file
@ -0,0 +1,62 @@
|
||||
// Example of a struct containing an array
|
||||
// It works on the surface - but illustrates the problem with structs containing arrays treating them like pointers.
|
||||
// https://gitlab.com/camelot/kickc/issues/312
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
.const jesper_id = 4
|
||||
.const henriette_id = 7
|
||||
lda #<jesper_name
|
||||
sta.z print_person.person_name
|
||||
lda #>jesper_name
|
||||
sta.z print_person.person_name+1
|
||||
ldy #0
|
||||
ldx #jesper_id
|
||||
jsr print_person
|
||||
lda #<henriette_name
|
||||
sta.z print_person.person_name
|
||||
lda #>henriette_name
|
||||
sta.z print_person.person_name+1
|
||||
ldx #henriette_id
|
||||
jsr print_person
|
||||
rts
|
||||
jesper_name: .text "jesper"
|
||||
.byte 0
|
||||
.fill 9, 0
|
||||
henriette_name: .text "henriette"
|
||||
.byte 0
|
||||
.fill 6, 0
|
||||
}
|
||||
// print_person(byte register(X) person_id, byte[$10] zeropage(2) person_name)
|
||||
print_person: {
|
||||
.label person_name = 2
|
||||
lda DIGIT,x
|
||||
sta SCREEN,y
|
||||
tya
|
||||
tax
|
||||
inx
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
inx
|
||||
ldy #0
|
||||
b1:
|
||||
lda (person_name),y
|
||||
cmp #0
|
||||
bne b2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
txa
|
||||
tay
|
||||
iny
|
||||
rts
|
||||
b2:
|
||||
lda (person_name),y
|
||||
sta SCREEN,x
|
||||
inx
|
||||
iny
|
||||
jmp b1
|
||||
}
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
46
src/test/ref/struct-ptr-34.cfg
Normal file
46
src/test/ref/struct-ptr-34.cfg
Normal file
@ -0,0 +1,46 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
[5] call print_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[6] phi()
|
||||
[7] call print_person
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[8] return
|
||||
to:@return
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
[9] (byte[$10]) print_person::person_name#4 ← phi( main/(const byte[$10]) main::jesper_name#0 main::@1/(const byte[$10]) main::henriette_name#0 )
|
||||
[9] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
|
||||
[9] (byte) print_person::person_id#2 ← phi( main/(const byte) main::jesper_id#0 main::@1/(const byte) main::henriette_id#0 )
|
||||
[10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2)
|
||||
[11] (byte) idx#4 ← ++ (byte) idx#13
|
||||
[12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
|
||||
[13] (byte) idx#5 ← ++ (byte) idx#4
|
||||
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[$10]) print_person::person_name#4 + (byte) 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#0 + (byte) idx#14) ← (byte) ' '
|
||||
[17] (byte) idx#16 ← ++ (byte) idx#14
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
[18] return
|
||||
to:@return
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
[19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2)
|
||||
[20] (byte) idx#6 ← ++ (byte) idx#14
|
||||
[21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
|
||||
to:print_person::@1
|
913
src/test/ref/struct-ptr-34.log
Normal file
913
src/test/ref/struct-ptr-34.log
Normal file
@ -0,0 +1,913 @@
|
||||
Fixing struct type size struct Person to 17
|
||||
Fixing struct type size struct Person to 17
|
||||
Fixing struct type size struct Person to 17
|
||||
Created struct value member variable (byte) main::jesper_id
|
||||
Created struct value member variable (byte[$10]) main::jesper_name
|
||||
Converted struct value to member variables (struct Person) main::jesper
|
||||
Created struct value member variable (byte) main::henriette_id
|
||||
Created struct value member variable (byte[$10]) main::henriette_name
|
||||
Converted struct value to member variables (struct Person) main::henriette
|
||||
Created struct value member variable (byte) print_person::person_id
|
||||
Created struct value member variable (byte[$10]) print_person::person_name
|
||||
Converted struct value to member variables (struct Person) print_person::person
|
||||
Converted procedure struct value parameter to member unwinding (void()) print_person((byte) print_person::person_id , (byte[$10]) print_person::person_name)
|
||||
Adding struct value list initializer (byte) main::jesper_id ← (number) 4
|
||||
Adding struct value list initializer (byte[$10]) main::jesper_name ← (string) "jesper"
|
||||
Converted procedure struct value parameter to member unwinding in call (void~) main::$0 ← call print_person (byte) main::jesper_id (byte[$10]) main::jesper_name
|
||||
Adding struct value list initializer (byte) main::henriette_id ← (number) 7
|
||||
Adding struct value list initializer (byte[$10]) main::henriette_name ← (string) "henriette"
|
||||
Converted procedure struct value parameter to member unwinding in call (void~) main::$1 ← call print_person (byte) main::henriette_id (byte[$10]) main::henriette_name
|
||||
Replacing struct member reference (struct Person) print_person::person.id with member unwinding reference (byte) print_person::person_id
|
||||
Replacing struct member reference (struct Person) print_person::person.name with member unwinding reference (byte[$10]) print_person::person_name
|
||||
Replacing struct member reference (struct Person) print_person::person.name with member unwinding reference (byte[$10]) print_person::person_name
|
||||
Warning! Adding boolean cast to non-boolean condition *((byte[$10]) print_person::person_name + (byte) print_person::i)
|
||||
Identified constant variable (byte) main::jesper_id
|
||||
Identified constant variable (byte[$10]) main::jesper_name
|
||||
Identified constant variable (byte) main::henriette_id
|
||||
Identified constant variable (byte[$10]) main::henriette_name
|
||||
Culled Empty Block (label) print_person::@4
|
||||
Culled Empty Block (label) print_person::@5
|
||||
Culled Empty Block (label) print_person::@6
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@1
|
||||
main: scope:[main] from @2
|
||||
(byte) idx#18 ← phi( @2/(byte) idx#20 )
|
||||
(byte) main::jesper_id#0 ← (number) 4
|
||||
(byte[$10]) main::jesper_name#0 ← (const string) main::$2
|
||||
(byte) print_person::person_id#0 ← (byte) main::jesper_id#0
|
||||
(byte[$10]) print_person::person_name#0 ← (byte[$10]) main::jesper_name#0
|
||||
call print_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
(byte) idx#10 ← phi( main/(byte) idx#8 )
|
||||
(byte) idx#0 ← (byte) idx#10
|
||||
(byte) main::henriette_id#0 ← (number) 7
|
||||
(byte[$10]) main::henriette_name#0 ← (const string) main::$3
|
||||
(byte) print_person::person_id#1 ← (byte) main::henriette_id#0
|
||||
(byte[$10]) print_person::person_name#1 ← (byte[$10]) main::henriette_name#0
|
||||
call print_person
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
(byte) idx#11 ← phi( main::@1/(byte) idx#8 )
|
||||
(byte) idx#1 ← (byte) idx#11
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
(byte) idx#12 ← phi( main::@2/(byte) idx#1 )
|
||||
(byte) idx#2 ← (byte) idx#12
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
(byte*) SCREEN#0 ← ((byte*)) (number) $400
|
||||
(byte) idx#3 ← (number) 0
|
||||
(byte[]) DIGIT#0 ← (const string) $0
|
||||
to:@2
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
(byte[$10]) print_person::person_name#4 ← phi( main/(byte[$10]) print_person::person_name#0 main::@1/(byte[$10]) print_person::person_name#1 )
|
||||
(byte) idx#13 ← phi( main/(byte) idx#18 main::@1/(byte) idx#0 )
|
||||
(byte) print_person::person_id#2 ← phi( main/(byte) print_person::person_id#0 main::@1/(byte) print_person::person_id#1 )
|
||||
*((byte*) SCREEN#0 + (byte) idx#13) ← *((byte[]) DIGIT#0 + (byte) print_person::person_id#2)
|
||||
(byte) idx#4 ← ++ (byte) idx#13
|
||||
*((byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
|
||||
(byte) idx#5 ← ++ (byte) idx#4
|
||||
(byte) print_person::i#0 ← (number) 0
|
||||
to:print_person::@1
|
||||
print_person::@1: scope:[print_person] from print_person print_person::@2
|
||||
(byte) idx#19 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
|
||||
(byte) print_person::i#2 ← phi( print_person/(byte) print_person::i#0 print_person::@2/(byte) print_person::i#1 )
|
||||
(byte[$10]) print_person::person_name#2 ← phi( print_person/(byte[$10]) print_person::person_name#4 print_person::@2/(byte[$10]) print_person::person_name#3 )
|
||||
(bool~) print_person::$0 ← (number) 0 != *((byte[$10]) print_person::person_name#2 + (byte) print_person::i#2)
|
||||
if((bool~) print_person::$0) goto print_person::@2
|
||||
to:print_person::@3
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
(byte) idx#14 ← phi( print_person::@1/(byte) idx#19 )
|
||||
(byte) print_person::i#3 ← phi( print_person::@1/(byte) print_person::i#2 )
|
||||
(byte[$10]) print_person::person_name#3 ← phi( print_person::@1/(byte[$10]) print_person::person_name#2 )
|
||||
*((byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$10]) print_person::person_name#3 + (byte) print_person::i#3)
|
||||
(byte) idx#6 ← ++ (byte) idx#14
|
||||
(byte) print_person::i#1 ← ++ (byte) print_person::i#3
|
||||
to:print_person::@1
|
||||
print_person::@3: scope:[print_person] from print_person::@1
|
||||
(byte) idx#15 ← phi( print_person::@1/(byte) idx#19 )
|
||||
*((byte*) SCREEN#0 + (byte) idx#15) ← (byte) ' '
|
||||
(byte) idx#7 ← ++ (byte) idx#15
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
(byte) idx#16 ← phi( print_person::@3/(byte) idx#7 )
|
||||
(byte) idx#8 ← (byte) idx#16
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @1
|
||||
(byte) idx#20 ← phi( @1/(byte) idx#3 )
|
||||
call main
|
||||
to:@3
|
||||
@3: scope:[] from @2
|
||||
(byte) idx#17 ← phi( @2/(byte) idx#2 )
|
||||
(byte) idx#9 ← (byte) idx#17
|
||||
to:@end
|
||||
@end: scope:[] from @3
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(const string) $0 = (string) "0123456789"
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) DIGIT
|
||||
(byte[]) DIGIT#0
|
||||
(byte) Person::id
|
||||
(byte[$10]) Person::name
|
||||
(byte*) SCREEN
|
||||
(byte*) SCREEN#0
|
||||
(byte) idx
|
||||
(byte) idx#0
|
||||
(byte) idx#1
|
||||
(byte) idx#10
|
||||
(byte) idx#11
|
||||
(byte) idx#12
|
||||
(byte) idx#13
|
||||
(byte) idx#14
|
||||
(byte) idx#15
|
||||
(byte) idx#16
|
||||
(byte) idx#17
|
||||
(byte) idx#18
|
||||
(byte) idx#19
|
||||
(byte) idx#2
|
||||
(byte) idx#20
|
||||
(byte) idx#3
|
||||
(byte) idx#4
|
||||
(byte) idx#5
|
||||
(byte) idx#6
|
||||
(byte) idx#7
|
||||
(byte) idx#8
|
||||
(byte) idx#9
|
||||
(void()) main()
|
||||
(const string) main::$2 = (string) "jesper"
|
||||
(const string) main::$3 = (string) "henriette"
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(byte) main::henriette_id
|
||||
(byte) main::henriette_id#0
|
||||
(byte[$10]) main::henriette_name
|
||||
(byte[$10]) main::henriette_name#0
|
||||
(byte) main::jesper_id
|
||||
(byte) main::jesper_id#0
|
||||
(byte[$10]) main::jesper_name
|
||||
(byte[$10]) main::jesper_name#0
|
||||
(void()) print_person((byte) print_person::person_id , (byte[$10]) print_person::person_name)
|
||||
(bool~) print_person::$0
|
||||
(label) print_person::@1
|
||||
(label) print_person::@2
|
||||
(label) print_person::@3
|
||||
(label) print_person::@return
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#0
|
||||
(byte) print_person::i#1
|
||||
(byte) print_person::i#2
|
||||
(byte) print_person::i#3
|
||||
(struct Person) print_person::person
|
||||
(byte) print_person::person_id
|
||||
(byte) print_person::person_id#0
|
||||
(byte) print_person::person_id#1
|
||||
(byte) print_person::person_id#2
|
||||
(byte[$10]) print_person::person_name
|
||||
(byte[$10]) print_person::person_name#0
|
||||
(byte[$10]) print_person::person_name#1
|
||||
(byte[$10]) print_person::person_name#2
|
||||
(byte[$10]) print_person::person_name#3
|
||||
(byte[$10]) print_person::person_name#4
|
||||
|
||||
Adding number conversion cast (unumber) 4 in (byte) main::jesper_id#0 ← (number) 4
|
||||
Adding number conversion cast (unumber) 7 in (byte) main::henriette_id#0 ← (number) 7
|
||||
Adding number conversion cast (unumber) 0 in (byte) idx#3 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (byte) print_person::i#0 ← (number) 0
|
||||
Adding number conversion cast (unumber) 0 in (bool~) print_person::$0 ← (number) 0 != *((byte[$10]) print_person::person_name#2 + (byte) print_person::i#2)
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte) main::jesper_id#0 ← (unumber)(number) 4
|
||||
Inlining cast (byte) main::henriette_id#0 ← (unumber)(number) 7
|
||||
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
|
||||
Inlining cast (byte) idx#3 ← (unumber)(number) 0
|
||||
Inlining cast (byte) print_person::i#0 ← (unumber)(number) 0
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 7
|
||||
Simplifying constant pointer cast (byte*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 4
|
||||
Finalized unsigned number type (byte) 7
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Alias (byte) idx#0 = (byte) idx#10
|
||||
Alias (byte) idx#1 = (byte) idx#11 (byte) idx#12 (byte) idx#2
|
||||
Alias (byte[$10]) print_person::person_name#2 = (byte[$10]) print_person::person_name#3
|
||||
Alias (byte) print_person::i#2 = (byte) print_person::i#3
|
||||
Alias (byte) idx#14 = (byte) idx#19 (byte) idx#15
|
||||
Alias (byte) idx#16 = (byte) idx#7 (byte) idx#8
|
||||
Alias (byte) idx#20 = (byte) idx#3
|
||||
Alias (byte) idx#17 = (byte) idx#9
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values (byte) idx#18 (byte) idx#20
|
||||
Identical Phi Values (byte) idx#0 (byte) idx#16
|
||||
Identical Phi Values (byte) idx#1 (byte) idx#16
|
||||
Identical Phi Values (byte[$10]) print_person::person_name#2 (byte[$10]) print_person::person_name#4
|
||||
Identical Phi Values (byte) idx#17 (byte) idx#1
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition (bool~) print_person::$0 [29] if((byte) 0!=*((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant (const byte) main::jesper_id#0 = 4
|
||||
Constant (const byte[$10]) main::jesper_name#0 = main::$2
|
||||
Constant (const byte) main::henriette_id#0 = 7
|
||||
Constant (const byte[$10]) main::henriette_name#0 = main::$3
|
||||
Constant (const byte*) SCREEN#0 = (byte*) 1024
|
||||
Constant (const byte) idx#20 = 0
|
||||
Constant (const byte[]) DIGIT#0 = $0
|
||||
Constant (const byte) print_person::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const byte) print_person::person_id#0 = main::jesper_id#0
|
||||
Constant (const byte[$10]) print_person::person_name#0 = main::jesper_name#0
|
||||
Constant (const byte) print_person::person_id#1 = main::henriette_id#0
|
||||
Constant (const byte[$10]) print_person::person_name#1 = main::henriette_name#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Inlining constant with var siblings (const byte) print_person::i#0
|
||||
Inlining constant with var siblings (const byte) print_person::person_id#0
|
||||
Inlining constant with var siblings (const byte[$10]) print_person::person_name#0
|
||||
Inlining constant with var siblings (const byte) print_person::person_id#1
|
||||
Inlining constant with var siblings (const byte[$10]) print_person::person_name#1
|
||||
Inlining constant with var siblings (const byte) idx#20
|
||||
Constant inlined idx#20 = (byte) 0
|
||||
Constant inlined print_person::person_id#1 = (const byte) main::henriette_id#0
|
||||
Constant inlined print_person::person_id#0 = (const byte) main::jesper_id#0
|
||||
Constant inlined main::$2 = (const byte[$10]) main::jesper_name#0
|
||||
Constant inlined print_person::i#0 = (byte) 0
|
||||
Constant inlined print_person::person_name#1 = (const byte[$10]) main::henriette_name#0
|
||||
Constant inlined main::$3 = (const byte[$10]) main::henriette_name#0
|
||||
Constant inlined $0 = (const byte[]) DIGIT#0
|
||||
Constant inlined print_person::person_name#0 = (const byte[$10]) main::jesper_name#0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
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::@2
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
Calls in [main] to print_person:7 print_person:9
|
||||
|
||||
Created 5 initial phi equivalence classes
|
||||
Coalesced [8] idx#21 ← idx#16
|
||||
Coalesced [17] idx#22 ← idx#5
|
||||
Coalesced [26] print_person::i#4 ← print_person::i#1
|
||||
Coalesced [27] idx#23 ← idx#6
|
||||
Coalesced down to 5 phi equivalence classes
|
||||
Culled Empty Block (label) @1
|
||||
Culled Empty Block (label) @3
|
||||
Culled Empty Block (label) main::@2
|
||||
Renumbering block @2 to @1
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@1
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
[5] call print_person
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[6] phi()
|
||||
[7] call print_person
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[8] return
|
||||
to:@return
|
||||
print_person: scope:[print_person] from main main::@1
|
||||
[9] (byte[$10]) print_person::person_name#4 ← phi( main/(const byte[$10]) main::jesper_name#0 main::@1/(const byte[$10]) main::henriette_name#0 )
|
||||
[9] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
|
||||
[9] (byte) print_person::person_id#2 ← phi( main/(const byte) main::jesper_id#0 main::@1/(const byte) main::henriette_id#0 )
|
||||
[10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2)
|
||||
[11] (byte) idx#4 ← ++ (byte) idx#13
|
||||
[12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
|
||||
[13] (byte) idx#5 ← ++ (byte) idx#4
|
||||
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[$10]) print_person::person_name#4 + (byte) 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#0 + (byte) idx#14) ← (byte) ' '
|
||||
[17] (byte) idx#16 ← ++ (byte) idx#14
|
||||
to:print_person::@return
|
||||
print_person::@return: scope:[print_person] from print_person::@3
|
||||
[18] return
|
||||
to:@return
|
||||
print_person::@2: scope:[print_person] from print_person::@1
|
||||
[19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2)
|
||||
[20] (byte) idx#6 ← ++ (byte) idx#14
|
||||
[21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
|
||||
to:print_person::@1
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte[]) DIGIT
|
||||
(byte) Person::id
|
||||
(byte[$10]) Person::name
|
||||
(byte*) SCREEN
|
||||
(byte) idx
|
||||
(byte) idx#13 3.0
|
||||
(byte) idx#14 9.75
|
||||
(byte) idx#16 1.0
|
||||
(byte) idx#4 3.0
|
||||
(byte) idx#5 4.0
|
||||
(byte) idx#6 11.0
|
||||
(void()) main()
|
||||
(byte) main::henriette_id
|
||||
(byte[$10]) main::henriette_name
|
||||
(byte) main::jesper_id
|
||||
(byte[$10]) main::jesper_name
|
||||
(void()) print_person((byte) print_person::person_id , (byte[$10]) print_person::person_name)
|
||||
(byte) print_person::i
|
||||
(byte) print_person::i#1 22.0
|
||||
(byte) print_person::i#2 11.0
|
||||
(struct Person) print_person::person
|
||||
(byte) print_person::person_id
|
||||
(byte) print_person::person_id#2 2.0
|
||||
(byte[$10]) print_person::person_name
|
||||
(byte[$10]) print_person::person_name#4 2.2
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ print_person::person_id#2 ]
|
||||
[ idx#13 idx#16 ]
|
||||
[ print_person::person_name#4 ]
|
||||
[ print_person::i#2 print_person::i#1 ]
|
||||
[ idx#14 idx#5 idx#6 ]
|
||||
Added variable idx#4 to zero page equivalence class [ idx#4 ]
|
||||
Complete equivalence classes
|
||||
[ print_person::person_id#2 ]
|
||||
[ idx#13 idx#16 ]
|
||||
[ print_person::person_name#4 ]
|
||||
[ print_person::i#2 print_person::i#1 ]
|
||||
[ idx#14 idx#5 idx#6 ]
|
||||
[ idx#4 ]
|
||||
Allocated zp ZP_BYTE:2 [ print_person::person_id#2 ]
|
||||
Allocated zp ZP_BYTE:3 [ idx#13 idx#16 ]
|
||||
Allocated zp ZP_WORD:4 [ print_person::person_name#4 ]
|
||||
Allocated zp ZP_BYTE:6 [ print_person::i#2 print_person::i#1 ]
|
||||
Allocated zp ZP_BYTE:7 [ idx#14 idx#5 idx#6 ]
|
||||
Allocated zp ZP_BYTE:8 [ idx#4 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is c64basic / MOS6502X
|
||||
// File Comments
|
||||
// Example of a struct containing an array
|
||||
// It works on the surface - but illustrates the problem with structs containing arrays treating them like pointers.
|
||||
// https://gitlab.com/camelot/kickc/issues/312
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label idx = 8
|
||||
.label idx_5 = 7
|
||||
.label idx_6 = 7
|
||||
.label idx_13 = 3
|
||||
.label idx_14 = 7
|
||||
.label idx_16 = 3
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
.const jesper_id = 4
|
||||
.const henriette_id = 7
|
||||
// [5] call print_person
|
||||
// [9] phi from main to print_person [phi:main->print_person]
|
||||
print_person_from_main:
|
||||
// [9] phi (byte[$10]) print_person::person_name#4 = (const byte[$10]) main::jesper_name#0 [phi:main->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<jesper_name
|
||||
sta.z print_person.person_name
|
||||
lda #>jesper_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z idx_13
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::jesper_id#0 [phi:main->print_person#2] -- vbuz1=vbuc1
|
||||
lda #jesper_id
|
||||
sta.z print_person.person_id
|
||||
jsr print_person
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [7] call print_person
|
||||
// [9] phi from main::@1 to print_person [phi:main::@1->print_person]
|
||||
print_person_from_b1:
|
||||
// [9] phi (byte[$10]) print_person::person_name#4 = (const byte[$10]) main::henriette_name#0 [phi:main::@1->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<henriette_name
|
||||
sta.z print_person.person_name
|
||||
lda #>henriette_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#1] -- register_copy
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::henriette_id#0 [phi:main::@1->print_person#2] -- vbuz1=vbuc1
|
||||
lda #henriette_id
|
||||
sta.z print_person.person_id
|
||||
jsr print_person
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [8] return
|
||||
rts
|
||||
jesper_name: .text "jesper"
|
||||
.byte 0
|
||||
.fill 9, 0
|
||||
henriette_name: .text "henriette"
|
||||
.byte 0
|
||||
.fill 6, 0
|
||||
}
|
||||
// print_person
|
||||
// print_person(byte zeropage(2) person_id, byte[$10] zeropage(4) person_name)
|
||||
print_person: {
|
||||
.label i = 6
|
||||
.label person_id = 2
|
||||
.label person_name = 4
|
||||
// [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2
|
||||
ldy.z person_id
|
||||
lda DIGIT,y
|
||||
ldy.z idx_13
|
||||
sta SCREEN,y
|
||||
// [11] (byte) idx#4 ← ++ (byte) idx#13 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx_13
|
||||
iny
|
||||
sty.z idx
|
||||
// [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
|
||||
lda #' '
|
||||
ldy.z idx
|
||||
sta SCREEN,y
|
||||
// [13] (byte) idx#5 ← ++ (byte) idx#4 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx
|
||||
iny
|
||||
sty.z idx_5
|
||||
// [14] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
|
||||
b1_from_print_person:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp b1
|
||||
// print_person::@1
|
||||
b1:
|
||||
// [15] if((byte) 0!=*((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_pbuz1_derefidx_vbuz2_then_la1
|
||||
ldy.z i
|
||||
lda (person_name),y
|
||||
cmp #0
|
||||
bne b2
|
||||
jmp b3
|
||||
// print_person::@3
|
||||
b3:
|
||||
// [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
|
||||
lda #' '
|
||||
ldy.z idx_14
|
||||
sta SCREEN,y
|
||||
// [17] (byte) idx#16 ← ++ (byte) idx#14 -- vbuz1=_inc_vbuz2
|
||||
ldy.z idx_14
|
||||
iny
|
||||
sty.z idx_16
|
||||
jmp breturn
|
||||
// print_person::@return
|
||||
breturn:
|
||||
// [18] return
|
||||
rts
|
||||
// print_person::@2
|
||||
b2:
|
||||
// [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2) -- pbuc1_derefidx_vbuz1=pbuz2_derefidx_vbuz3
|
||||
ldx.z idx_14
|
||||
ldy.z i
|
||||
lda (person_name),y
|
||||
sta SCREEN,x
|
||||
// [20] (byte) idx#6 ← ++ (byte) idx#14 -- vbuz1=_inc_vbuz1
|
||||
inc.z idx_6
|
||||
// [21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [14] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
|
||||
b1_from_b2:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2) [ idx#13 print_person::person_name#4 ] ( main:2::print_person:5 [ idx#13 print_person::person_name#4 ] main:2::print_person:7 [ idx#13 print_person::person_name#4 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ idx#13 idx#16 ]
|
||||
Statement [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' [ print_person::person_name#4 idx#4 ] ( main:2::print_person:5 [ print_person::person_name#4 idx#4 ] main:2::print_person:7 [ print_person::person_name#4 idx#4 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:8 [ idx#4 ]
|
||||
Statement [15] if((byte) 0!=*((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2 [ print_person::person_name#4 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person_name#4 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person_name#4 print_person::i#2 idx#14 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ print_person::i#2 print_person::i#1 ]
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:7 [ idx#14 idx#5 idx#6 ]
|
||||
Statement [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' [ idx#14 ] ( main:2::print_person:5 [ idx#14 ] main:2::print_person:7 [ idx#14 ] ) always clobbers reg byte a
|
||||
Statement [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2) [ print_person::person_name#4 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person_name#4 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person_name#4 print_person::i#2 idx#14 ] ) always clobbers reg byte a
|
||||
Statement [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2) [ idx#13 print_person::person_name#4 ] ( main:2::print_person:5 [ idx#13 print_person::person_name#4 ] main:2::print_person:7 [ idx#13 print_person::person_name#4 ] ) always clobbers reg byte a
|
||||
Statement [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' [ print_person::person_name#4 idx#4 ] ( main:2::print_person:5 [ print_person::person_name#4 idx#4 ] main:2::print_person:7 [ print_person::person_name#4 idx#4 ] ) always clobbers reg byte a
|
||||
Statement [15] if((byte) 0!=*((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2 [ print_person::person_name#4 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person_name#4 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person_name#4 print_person::i#2 idx#14 ] ) always clobbers reg byte a
|
||||
Statement [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' [ idx#14 ] ( main:2::print_person:5 [ idx#14 ] main:2::print_person:7 [ idx#14 ] ) always clobbers reg byte a
|
||||
Statement [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2) [ print_person::person_name#4 print_person::i#2 idx#14 ] ( main:2::print_person:5 [ print_person::person_name#4 print_person::i#2 idx#14 ] main:2::print_person:7 [ print_person::person_name#4 print_person::i#2 idx#14 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ print_person::person_id#2 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:3 [ idx#13 idx#16 ] : zp ZP_BYTE:3 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_WORD:4 [ print_person::person_name#4 ] : zp ZP_WORD:4 ,
|
||||
Potential registers zp ZP_BYTE:6 [ print_person::i#2 print_person::i#1 ] : zp ZP_BYTE:6 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:7 [ idx#14 idx#5 idx#6 ] : zp ZP_BYTE:7 , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:8 [ idx#4 ] : zp ZP_BYTE:8 , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [print_person] 33: zp ZP_BYTE:6 [ print_person::i#2 print_person::i#1 ] 2.2: zp ZP_WORD:4 [ print_person::person_name#4 ] 2: zp ZP_BYTE:2 [ print_person::person_id#2 ]
|
||||
Uplift Scope [] 24.75: zp ZP_BYTE:7 [ idx#14 idx#5 idx#6 ] 4: zp ZP_BYTE:3 [ idx#13 idx#16 ] 3: zp ZP_BYTE:8 [ idx#4 ]
|
||||
Uplift Scope [Person]
|
||||
Uplift Scope [main]
|
||||
|
||||
Uplifting [print_person] best 545 combination reg byte y [ print_person::i#2 print_person::i#1 ] zp ZP_WORD:4 [ print_person::person_name#4 ] reg byte x [ print_person::person_id#2 ]
|
||||
Uplifting [] best 463 combination reg byte x [ idx#14 idx#5 idx#6 ] reg byte y [ idx#13 idx#16 ] reg byte x [ idx#4 ]
|
||||
Uplifting [Person] best 463 combination
|
||||
Uplifting [main] best 463 combination
|
||||
Allocated (was zp ZP_WORD:4) zp ZP_WORD:2 [ print_person::person_name#4 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Example of a struct containing an array
|
||||
// It works on the surface - but illustrates the problem with structs containing arrays treating them like pointers.
|
||||
// https://gitlab.com/camelot/kickc/issues/312
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
b1_from_bbegin:
|
||||
jmp b1
|
||||
// @1
|
||||
b1:
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
main_from_b1:
|
||||
jsr main
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
bend_from_b1:
|
||||
jmp bend
|
||||
// @end
|
||||
bend:
|
||||
// main
|
||||
main: {
|
||||
.const jesper_id = 4
|
||||
.const henriette_id = 7
|
||||
// [5] call print_person
|
||||
// [9] phi from main to print_person [phi:main->print_person]
|
||||
print_person_from_main:
|
||||
// [9] phi (byte[$10]) print_person::person_name#4 = (const byte[$10]) main::jesper_name#0 [phi:main->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<jesper_name
|
||||
sta.z print_person.person_name
|
||||
lda #>jesper_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::jesper_id#0 [phi:main->print_person#2] -- vbuxx=vbuc1
|
||||
ldx #jesper_id
|
||||
jsr print_person
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [7] call print_person
|
||||
// [9] phi from main::@1 to print_person [phi:main::@1->print_person]
|
||||
print_person_from_b1:
|
||||
// [9] phi (byte[$10]) print_person::person_name#4 = (const byte[$10]) main::henriette_name#0 [phi:main::@1->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<henriette_name
|
||||
sta.z print_person.person_name
|
||||
lda #>henriette_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#1] -- register_copy
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::henriette_id#0 [phi:main::@1->print_person#2] -- vbuxx=vbuc1
|
||||
ldx #henriette_id
|
||||
jsr print_person
|
||||
jmp breturn
|
||||
// main::@return
|
||||
breturn:
|
||||
// [8] return
|
||||
rts
|
||||
jesper_name: .text "jesper"
|
||||
.byte 0
|
||||
.fill 9, 0
|
||||
henriette_name: .text "henriette"
|
||||
.byte 0
|
||||
.fill 6, 0
|
||||
}
|
||||
// print_person
|
||||
// print_person(byte register(X) person_id, byte[$10] zeropage(2) person_name)
|
||||
print_person: {
|
||||
.label person_name = 2
|
||||
// [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2) -- pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuxx
|
||||
lda DIGIT,x
|
||||
sta SCREEN,y
|
||||
// [11] (byte) idx#4 ← ++ (byte) idx#13 -- vbuxx=_inc_vbuyy
|
||||
tya
|
||||
tax
|
||||
inx
|
||||
// [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// [13] (byte) idx#5 ← ++ (byte) idx#4 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [14] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
|
||||
b1_from_print_person:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
jmp b1
|
||||
// print_person::@1
|
||||
b1:
|
||||
// [15] if((byte) 0!=*((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_pbuz1_derefidx_vbuyy_then_la1
|
||||
lda (person_name),y
|
||||
cmp #0
|
||||
bne b2
|
||||
jmp b3
|
||||
// print_person::@3
|
||||
b3:
|
||||
// [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// [17] (byte) idx#16 ← ++ (byte) idx#14 -- vbuyy=_inc_vbuxx
|
||||
txa
|
||||
tay
|
||||
iny
|
||||
jmp breturn
|
||||
// print_person::@return
|
||||
breturn:
|
||||
// [18] return
|
||||
rts
|
||||
// print_person::@2
|
||||
b2:
|
||||
// [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2) -- pbuc1_derefidx_vbuxx=pbuz1_derefidx_vbuyy
|
||||
lda (person_name),y
|
||||
sta SCREEN,x
|
||||
// [20] (byte) idx#6 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [14] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
|
||||
b1_from_b2:
|
||||
// [14] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b3
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction main_from_b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction print_person_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bend:
|
||||
Removing instruction print_person_from_main:
|
||||
Removing instruction b1:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_print_person:
|
||||
Removing instruction b3:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_b2:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Updating BasicUpstart to call main directly
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Removing instruction bbegin:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) DIGIT
|
||||
(const byte[]) DIGIT#0 DIGIT = (string) "0123456789"
|
||||
(byte) Person::id
|
||||
(byte[$10]) Person::name
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#13 reg byte y 3.0
|
||||
(byte) idx#14 reg byte x 9.75
|
||||
(byte) idx#16 reg byte y 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
|
||||
(byte) main::henriette_id
|
||||
(const byte) main::henriette_id#0 henriette_id = (byte) 7
|
||||
(byte[$10]) main::henriette_name
|
||||
(const byte[$10]) main::henriette_name#0 henriette_name = (string) "henriette"
|
||||
(byte) main::jesper_id
|
||||
(const byte) main::jesper_id#0 jesper_id = (byte) 4
|
||||
(byte[$10]) main::jesper_name
|
||||
(const byte[$10]) main::jesper_name#0 jesper_name = (string) "jesper"
|
||||
(void()) print_person((byte) print_person::person_id , (byte[$10]) print_person::person_name)
|
||||
(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 reg byte y 22.0
|
||||
(byte) print_person::i#2 reg byte y 11.0
|
||||
(struct Person) print_person::person
|
||||
(byte) print_person::person_id
|
||||
(byte) print_person::person_id#2 reg byte x 2.0
|
||||
(byte[$10]) print_person::person_name
|
||||
(byte[$10]) print_person::person_name#4 person_name zp ZP_WORD:2 2.2
|
||||
|
||||
reg byte x [ print_person::person_id#2 ]
|
||||
reg byte y [ idx#13 idx#16 ]
|
||||
zp ZP_WORD:2 [ print_person::person_name#4 ]
|
||||
reg byte y [ print_person::i#2 print_person::i#1 ]
|
||||
reg byte x [ idx#14 idx#5 idx#6 ]
|
||||
reg byte x [ idx#4 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 382
|
||||
|
||||
// File Comments
|
||||
// Example of a struct containing an array
|
||||
// It works on the surface - but illustrates the problem with structs containing arrays treating them like pointers.
|
||||
// https://gitlab.com/camelot/kickc/issues/312
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
// [2] call main
|
||||
// [4] phi from @1 to main [phi:@1->main]
|
||||
// [3] phi from @1 to @end [phi:@1->@end]
|
||||
// @end
|
||||
// main
|
||||
main: {
|
||||
.const jesper_id = 4
|
||||
.const henriette_id = 7
|
||||
// print_person(jesper)
|
||||
// [5] call print_person
|
||||
// [9] phi from main to print_person [phi:main->print_person]
|
||||
// [9] phi (byte[$10]) print_person::person_name#4 = (const byte[$10]) main::jesper_name#0 [phi:main->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<jesper_name
|
||||
sta.z print_person.person_name
|
||||
lda #>jesper_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::jesper_id#0 [phi:main->print_person#2] -- vbuxx=vbuc1
|
||||
ldx #jesper_id
|
||||
jsr print_person
|
||||
// [6] phi from main to main::@1 [phi:main->main::@1]
|
||||
// main::@1
|
||||
// print_person(henriette)
|
||||
// [7] call print_person
|
||||
// [9] phi from main::@1 to print_person [phi:main::@1->print_person]
|
||||
// [9] phi (byte[$10]) print_person::person_name#4 = (const byte[$10]) main::henriette_name#0 [phi:main::@1->print_person#0] -- pbuz1=pbuc1
|
||||
lda #<henriette_name
|
||||
sta.z print_person.person_name
|
||||
lda #>henriette_name
|
||||
sta.z print_person.person_name+1
|
||||
// [9] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#1] -- register_copy
|
||||
// [9] phi (byte) print_person::person_id#2 = (const byte) main::henriette_id#0 [phi:main::@1->print_person#2] -- vbuxx=vbuc1
|
||||
ldx #henriette_id
|
||||
jsr print_person
|
||||
// main::@return
|
||||
// }
|
||||
// [8] return
|
||||
rts
|
||||
jesper_name: .text "jesper"
|
||||
.byte 0
|
||||
.fill 9, 0
|
||||
henriette_name: .text "henriette"
|
||||
.byte 0
|
||||
.fill 6, 0
|
||||
}
|
||||
// print_person
|
||||
// print_person(byte register(X) person_id, byte[$10] zeropage(2) person_name)
|
||||
print_person: {
|
||||
.label person_name = 2
|
||||
// SCREEN[idx++] = DIGIT[person.id]
|
||||
// [10] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + (byte) print_person::person_id#2) -- pbuc1_derefidx_vbuyy=pbuc2_derefidx_vbuxx
|
||||
lda DIGIT,x
|
||||
sta SCREEN,y
|
||||
// SCREEN[idx++] = DIGIT[person.id];
|
||||
// [11] (byte) idx#4 ← ++ (byte) idx#13 -- vbuxx=_inc_vbuyy
|
||||
tya
|
||||
tax
|
||||
inx
|
||||
// SCREEN[idx++] = ' '
|
||||
// [12] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = ' ';
|
||||
// [13] (byte) idx#5 ← ++ (byte) idx#4 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [14] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
|
||||
// [14] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
// print_person::@1
|
||||
b1:
|
||||
// for(byte i=0; person.name[i]; i++)
|
||||
// [15] if((byte) 0!=*((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_pbuz1_derefidx_vbuyy_then_la1
|
||||
lda (person_name),y
|
||||
cmp #0
|
||||
bne b2
|
||||
// print_person::@3
|
||||
// SCREEN[idx++] = ' '
|
||||
// [16] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
|
||||
lda #' '
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = ' ';
|
||||
// [17] (byte) idx#16 ← ++ (byte) idx#14 -- vbuyy=_inc_vbuxx
|
||||
txa
|
||||
tay
|
||||
iny
|
||||
// print_person::@return
|
||||
// }
|
||||
// [18] return
|
||||
rts
|
||||
// print_person::@2
|
||||
b2:
|
||||
// SCREEN[idx++] = person.name[i]
|
||||
// [19] *((const byte*) SCREEN#0 + (byte) idx#14) ← *((byte[$10]) print_person::person_name#4 + (byte) print_person::i#2) -- pbuc1_derefidx_vbuxx=pbuz1_derefidx_vbuyy
|
||||
lda (person_name),y
|
||||
sta SCREEN,x
|
||||
// SCREEN[idx++] = person.name[i];
|
||||
// [20] (byte) idx#6 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// for(byte i=0; person.name[i]; i++)
|
||||
// [21] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
// [14] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
|
||||
// [14] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
|
||||
// [14] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
|
||||
jmp b1
|
||||
}
|
||||
// File Data
|
||||
DIGIT: .text "0123456789"
|
||||
.byte 0
|
||||
|
47
src/test/ref/struct-ptr-34.sym
Normal file
47
src/test/ref/struct-ptr-34.sym
Normal file
@ -0,0 +1,47 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte[]) DIGIT
|
||||
(const byte[]) DIGIT#0 DIGIT = (string) "0123456789"
|
||||
(byte) Person::id
|
||||
(byte[$10]) Person::name
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
|
||||
(byte) idx
|
||||
(byte) idx#13 reg byte y 3.0
|
||||
(byte) idx#14 reg byte x 9.75
|
||||
(byte) idx#16 reg byte y 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
|
||||
(byte) main::henriette_id
|
||||
(const byte) main::henriette_id#0 henriette_id = (byte) 7
|
||||
(byte[$10]) main::henriette_name
|
||||
(const byte[$10]) main::henriette_name#0 henriette_name = (string) "henriette"
|
||||
(byte) main::jesper_id
|
||||
(const byte) main::jesper_id#0 jesper_id = (byte) 4
|
||||
(byte[$10]) main::jesper_name
|
||||
(const byte[$10]) main::jesper_name#0 jesper_name = (string) "jesper"
|
||||
(void()) print_person((byte) print_person::person_id , (byte[$10]) print_person::person_name)
|
||||
(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 reg byte y 22.0
|
||||
(byte) print_person::i#2 reg byte y 11.0
|
||||
(struct Person) print_person::person
|
||||
(byte) print_person::person_id
|
||||
(byte) print_person::person_id#2 reg byte x 2.0
|
||||
(byte[$10]) print_person::person_name
|
||||
(byte[$10]) print_person::person_name#4 person_name zp ZP_WORD:2 2.2
|
||||
|
||||
reg byte x [ print_person::person_id#2 ]
|
||||
reg byte y [ idx#13 idx#16 ]
|
||||
zp ZP_WORD:2 [ print_person::person_name#4 ]
|
||||
reg byte y [ print_person::i#2 print_person::i#1 ]
|
||||
reg byte x [ idx#14 idx#5 idx#6 ]
|
||||
reg byte x [ idx#4 ]
|
Loading…
x
Reference in New Issue
Block a user