diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 680394611..421299423 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -569,17 +569,16 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor(), new LinkedHashSet<>()); + final LinkedHashSet defined = new LinkedHashSet<>(); + // Add all variables with an init-value + for(Variable var : getScope().getAllVars(true)) { + if(var.getInitValue()!=null) { + defined.add(var.getRef()); + } + } + assertUsedVars(beginBlock, null, referenceInfos, defined, new LinkedHashSet<>()); getProgram().clearVariableReferenceInfos(); getProgram().clearStatementIndices(); return false; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java b/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java index b616d1d5d..440de7af7 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java @@ -267,10 +267,9 @@ public class Pass1UnwindStructValues extends Pass1Base { if(lValueUnwinding.isBulkCopyable() && rValueUnwinding.isBulkCopyable()) { // Use bulk unwinding for a struct member that is an array stmtIt.previous(); - //RValue lValueMemberVarPointer = lValueUnwinding.getBulkLValue(getScope()); - //LValue lValueMemberVarRef = new PointerDereferenceSimple(lValueMemberVarPointer); - //if(rValueUnwinding.getArraySpec()==null || !lValueUnwinding.getArraySpec().equals(rValueUnwinding.getArraySpec())) - // throw new RuntimeException("ArraySpec mismatch!"); + if(lValueUnwinding.getArraySpec()!=null) + if(rValueUnwinding.getArraySpec()==null || !lValueUnwinding.getArraySpec().equals(rValueUnwinding.getArraySpec())) + throw new RuntimeException("ArraySpec mismatch!"); LValue lValueMemberVarRef = lValueUnwinding.getBulkLValue(getScope()); RValue rValueBulkUnwinding = rValueUnwinding.getBulkRValue(getScope()); if(lValueUnwoundList != null) diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertArrayLengths.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertArrayLengths.java index 98e9b19f9..60769ee0b 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertArrayLengths.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertArrayLengths.java @@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.symbols.StructDefinition; import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.values.*; @@ -21,6 +22,8 @@ public class Pass3AssertArrayLengths extends Pass2SsaAssertion { public void check() throws AssertionFailed { Collection allConstants = getScope().getAllConstants(true); for(Variable constantVar : allConstants) { + if(constantVar.getScope() instanceof StructDefinition) + continue; SymbolType constantType = constantVar.getType(); if(constantVar.isArray() && constantVar.getArraySize() != null) { ConstantValue declaredSize = constantVar.getArraySize(); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 3b8b85947..c042a3afc 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -539,10 +539,23 @@ public class Pass4CodeGeneration { String alignment = AsmFormat.getAsmNumber(declaredAlignment); asm.addDataAlignment(alignment); } - AsmDataChunk asmDataChunk = new AsmDataChunk(); - ConstantValue zeroValue = Initializers.createZeroValue(new Initializers.ValueTypeSpec(variable.getType(), variable.getArraySpec()), null); - addChunkData(asmDataChunk, zeroValue, variable.getType(), variable.getArraySpec(), scopeRef); - asmDataChunk.addToAsm(AsmFormat.asmFix(variable.getAsmName()), asm); + if(variable.getInitValue()!=null) { + // Variable has a constant init Value + ConstantValue constantValue = variable.getInitValue(); + if(constantValue instanceof ConstantArray || constantValue instanceof ConstantString || constantValue instanceof ConstantStructValue || constantValue instanceof StructZero) { + AsmDataChunk asmDataChunk = new AsmDataChunk(); + addChunkData(asmDataChunk, constantValue, variable.getType(), variable.getArraySpec(), scopeRef); + asmDataChunk.addToAsm(AsmFormat.asmFix(variable.getAsmName()), asm); + } else { + throw new InternalError("Constant Variable not handled " + variable.toString(program)); + } + } else { + // Zero-fill variable + AsmDataChunk asmDataChunk = new AsmDataChunk(); + ConstantValue zeroValue = Initializers.createZeroValue(new Initializers.ValueTypeSpec(variable.getType(), variable.getArraySpec()), null); + addChunkData(asmDataChunk, zeroValue, variable.getType(), variable.getArraySpec(), scopeRef); + asmDataChunk.addToAsm(AsmFormat.asmFix(variable.getAsmName()), asm); + } added.add(variable.getAsmName()); } } else { diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index a5b0ed2fa..d837e0b0a 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -1127,9 +1127,14 @@ public class TestPrograms { assertError("struct-err-0", "Unknown struct type"); } + @Test + public void testStruct33() throws IOException, URISyntaxException { + compileAndCompare("struct-33", log()); + } + @Test public void testStruct32() throws IOException, URISyntaxException { - compileAndCompare("struct-32", log()); + compileAndCompare("struct-32"); } @Test @@ -1139,7 +1144,7 @@ public class TestPrograms { @Test public void testStruct30() throws IOException, URISyntaxException { - compileAndCompare("struct-30", log()); + compileAndCompare("struct-30"); } @Test @@ -1229,17 +1234,17 @@ public class TestPrograms { @Test public void testStruct12() throws IOException, URISyntaxException { - compileAndCompare("struct-12", log()); + compileAndCompare("struct-12"); } @Test public void testStruct11b() throws IOException, URISyntaxException { - compileAndCompare("struct-11b", log()); + compileAndCompare("struct-11b"); } @Test public void testStruct11() throws IOException, URISyntaxException { - compileAndCompare("struct-11", log()); + compileAndCompare("struct-11"); } @Test diff --git a/src/test/kc/struct-33.kc b/src/test/kc/struct-33.kc new file mode 100644 index 000000000..0ac0f91b5 --- /dev/null +++ b/src/test/kc/struct-33.kc @@ -0,0 +1,17 @@ +// Minimal struct with C-Standard behavior - declaration, instantiation and usage + +struct Point { + char x; + char y; +}; + +__mem __ma struct Point point; + +const char* SCREEN = 0x0400; + +void main() { + point.x = 2; + point.y = 3; + SCREEN[0] = point.x; + SCREEN[1] = point.y; +} \ No newline at end of file diff --git a/src/test/ref/declared-memory-var-3.asm b/src/test/ref/declared-memory-var-3.asm index 5900a4430..f94e32f31 100644 --- a/src/test/ref/declared-memory-var-3.asm +++ b/src/test/ref/declared-memory-var-3.asm @@ -1,19 +1,9 @@ // Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store) // Test a memory variable struct value .pc = $801 "Basic" -:BasicUpstart(__bbegin) +:BasicUpstart(main) .pc = $80d "Program" - .const SIZEOF_STRUCT_FOO = 2 .const OFFSET_STRUCT_FOO_THING2 = 1 -__bbegin: - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- - jsr main - rts main: { .label SCREEN = $400 .label barp = bar @@ -23,5 +13,4 @@ main: { sta SCREEN+1 rts } - __0: .byte 'a', 'b' - bar: .fill SIZEOF_STRUCT_FOO, 0 + bar: .byte 'a', 'b' diff --git a/src/test/ref/declared-memory-var-3.cfg b/src/test/ref/declared-memory-var-3.cfg index 6baf15371..4cd0031b8 100644 --- a/src/test/ref/declared-memory-var-3.cfg +++ b/src/test/ref/declared-memory-var-3.cfg @@ -1,5 +1,5 @@ @begin: scope:[] from - [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) + [0] phi() to:@1 @1: scope:[] from @begin [1] phi() diff --git a/src/test/ref/declared-memory-var-3.log b/src/test/ref/declared-memory-var-3.log index aabc3c959..9a21ca18a 100644 --- a/src/test/ref/declared-memory-var-3.log +++ b/src/test/ref/declared-memory-var-3.log @@ -1,12 +1,10 @@ Setting inferred volatile on symbol affected by address-of (struct foo*) main::barp ← &(struct foo) bar -Adding struct value member variable copy *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) Rewriting struct pointer member access *((struct foo*) main::barp).thing1 Rewriting struct pointer member access *((struct foo*) main::barp).thing2 Identified constant variable (struct foo*) main::barp CONTROL FLOW GRAPH SSA @begin: scope:[] from - *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) to:@1 (void()) main() @@ -30,15 +28,13 @@ main::@return: scope:[main] from main @end: scope:[] from @2 SYMBOL TABLE SSA -(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' } (label) @1 (label) @2 (label) @begin (label) @end (const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 -(const byte) SIZEOF_STRUCT_FOO = (byte) 2 -(struct foo) bar loadstore +(struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b' } (byte) foo::thing1 (byte) foo::thing2 (void()) main() @@ -54,20 +50,20 @@ SYMBOL TABLE SSA Simplifying constant pointer cast (byte*) 1024 Successful SSA optimization PassNCastSimplification -Constant right-side identified [2] (byte*~) main::$0 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1 -Constant right-side identified [5] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2 +Constant right-side identified [1] (byte*~) main::$0 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1 +Constant right-side identified [4] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2 Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::i#0 = 0 Constant (const byte*) main::$0 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING1 Constant (const byte*) main::$1 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING2 Successful SSA optimization Pass2ConstantIdentification Simplifying expression containing zero (byte*)main::barp in -Simplifying expression containing zero main::SCREEN in [3] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$0) +Simplifying expression containing zero main::SCREEN in [2] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$0) Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (byte) main::i#2 and assignment [4] (byte) main::i#2 ← ++ (byte) main::i#1 +Eliminating unused variable (byte) main::i#2 and assignment [3] (byte) main::i#2 ← ++ (byte) main::i#1 Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1 Successful SSA optimization PassNEliminateUnusedVars -Constant right-side identified [2] (byte) main::i#1 ← ++ (const byte) main::i#0 +Constant right-side identified [1] (byte) main::i#1 ← ++ (const byte) main::i#0 Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::i#1 = ++main::i#0 Successful SSA optimization Pass2ConstantIdentification @@ -82,6 +78,7 @@ Consolidated array index constant in *(main::SCREEN+++0) Successful SSA optimization Pass2ConstantAdditionElimination Simplifying constant integer increment ++0 Successful SSA optimization Pass2ConstantSimplification +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 @end @@ -91,12 +88,13 @@ Calls in [] to main:2 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin Adding NOP phi() at start of @1 Adding NOP phi() at start of @end FINAL CONTROL FLOW GRAPH @begin: scope:[] from - [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) + [0] phi() to:@1 @1: scope:[] from @begin [1] phi() @@ -116,7 +114,7 @@ main::@return: scope:[main] from main VARIABLE REGISTER WEIGHTS -(struct foo) bar loadstore +(struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b' } (byte) foo::thing1 (byte) foo::thing2 (void()) main() @@ -138,17 +136,9 @@ Target platform is c64basic / MOS6502X :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels - .const SIZEOF_STRUCT_FOO = 2 .const OFFSET_STRUCT_FOO_THING2 = 1 // @begin __bbegin: - // [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 @@ -178,11 +168,9 @@ main: { rts } // File Data - __0: .byte 'a', 'b' - bar: .fill SIZEOF_STRUCT_FOO, 0 + bar: .byte 'a', 'b' REGISTER UPLIFT POTENTIAL REGISTERS -Statement [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [ ] ( [ ] ) always clobbers reg byte a reg byte y Statement [4] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a Potential registers mem[2] [ bar ] : mem[2] , @@ -192,9 +180,9 @@ Uplift Scope [foo] Uplift Scope [main] Uplift Scope [] 0: mem[2] [ bar ] -Uplifting [foo] best 53 combination -Uplifting [main] best 53 combination -Uplifting [] best 53 combination mem[2] [ bar ] +Uplifting [foo] best 37 combination +Uplifting [main] best 37 combination +Uplifting [] best 37 combination mem[2] [ bar ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -205,17 +193,9 @@ ASSEMBLER BEFORE OPTIMIZATION :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels - .const SIZEOF_STRUCT_FOO = 2 .const OFFSET_STRUCT_FOO_THING2 = 1 // @begin __bbegin: - // [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 @@ -245,32 +225,33 @@ main: { rts } // File Data - __0: .byte 'a', 'b' - bar: .fill SIZEOF_STRUCT_FOO, 0 + bar: .byte 'a', 'b' ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __bend Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination +Replacing label __bbegin with __b1 +Removing instruction __bbegin: Removing instruction __b1_from___bbegin: Removing instruction __bend_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination -Removing instruction __b1: Removing instruction __bend: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination -Adding RTS to root block -Succesful ASM optimization Pass5AddMainRts +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE -(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' } (label) @1 (label) @begin (label) @end (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 -(const byte) SIZEOF_STRUCT_FOO = (byte) 2 -(struct foo) bar loadstore mem[2] +(struct foo) bar loadstore mem[2] = { thing1: (byte) 'a', thing2: (byte) 'b' } (byte) foo::thing1 (byte) foo::thing2 (void()) main() @@ -283,33 +264,21 @@ mem[2] [ bar ] FINAL ASSEMBLER -Score: 50 +Score: 22 // File Comments // Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store) // Test a memory variable struct value // Upstart .pc = $801 "Basic" -:BasicUpstart(__bbegin) +:BasicUpstart(main) .pc = $80d "Program" // Global Constants & labels - .const SIZEOF_STRUCT_FOO = 2 .const OFFSET_STRUCT_FOO_THING2 = 1 // @begin -__bbegin: - // bar = { 'a', 'b' } - // [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- // [1] phi from @begin to @1 [phi:@begin->@1] // @1 // [2] call main - jsr main - rts // [3] phi from @1 to @end [phi:@1->@end] // @end // main @@ -330,6 +299,5 @@ main: { rts } // File Data - __0: .byte 'a', 'b' - bar: .fill SIZEOF_STRUCT_FOO, 0 + bar: .byte 'a', 'b' diff --git a/src/test/ref/declared-memory-var-3.sym b/src/test/ref/declared-memory-var-3.sym index 383755f95..8684311f1 100644 --- a/src/test/ref/declared-memory-var-3.sym +++ b/src/test/ref/declared-memory-var-3.sym @@ -1,10 +1,8 @@ -(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' } (label) @1 (label) @begin (label) @end (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 -(const byte) SIZEOF_STRUCT_FOO = (byte) 2 -(struct foo) bar loadstore mem[2] +(struct foo) bar loadstore mem[2] = { thing1: (byte) 'a', thing2: (byte) 'b' } (byte) foo::thing1 (byte) foo::thing2 (void()) main() diff --git a/src/test/ref/declared-memory-var-4.asm b/src/test/ref/declared-memory-var-4.asm index aca5c3c3b..f54a3b4d5 100644 --- a/src/test/ref/declared-memory-var-4.asm +++ b/src/test/ref/declared-memory-var-4.asm @@ -1,20 +1,10 @@ // Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store) // Test a memory variable struct value - containing a fixed size array .pc = $801 "Basic" -:BasicUpstart(__bbegin) +:BasicUpstart(main) .pc = $80d "Program" - .const SIZEOF_STRUCT_FOO = $e .const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING3 = 2 -__bbegin: - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- - jsr main - rts main: { .label SCREEN = $400 .label barp = bar @@ -33,8 +23,7 @@ main: { bne __b1 rts } - __0: .byte 'a', 'b' + bar: .byte 'a', 'b' .text "qwe" .byte 0 .fill 8, 0 - bar: .fill SIZEOF_STRUCT_FOO, 0 diff --git a/src/test/ref/declared-memory-var-4.cfg b/src/test/ref/declared-memory-var-4.cfg index 214a0b4a0..876e4c003 100644 --- a/src/test/ref/declared-memory-var-4.cfg +++ b/src/test/ref/declared-memory-var-4.cfg @@ -1,5 +1,5 @@ @begin: scope:[] from - [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) + [0] phi() to:@1 @1: scope:[] from @begin [1] phi() diff --git a/src/test/ref/declared-memory-var-4.log b/src/test/ref/declared-memory-var-4.log index e82b0fafb..26a40f1e6 100644 --- a/src/test/ref/declared-memory-var-4.log +++ b/src/test/ref/declared-memory-var-4.log @@ -3,7 +3,6 @@ Fixing struct type size struct foo to 14 Fixing struct type SIZE_OF struct foo to 14 Fixing struct type SIZE_OF struct foo to 14 Setting inferred volatile on symbol affected by address-of (struct foo*) main::barp ← &(struct foo) bar -Adding struct value member variable copy *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) Rewriting struct pointer member access *((struct foo*) main::barp).thing1 Rewriting struct pointer member access *((struct foo*) main::barp).thing2 Rewriting struct pointer member access *((struct foo*) main::barp).thing3 @@ -12,7 +11,6 @@ Culled Empty Block (label) main::@2 CONTROL FLOW GRAPH SSA @begin: scope:[] from - *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) to:@1 (void()) main() @@ -47,7 +45,6 @@ main::@return: scope:[main] from main::@1 @end: scope:[] from @2 SYMBOL TABLE SSA -(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" } (label) @1 (label) @2 (label) @begin @@ -55,8 +52,7 @@ SYMBOL TABLE SSA (const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2 -(const byte) SIZEOF_STRUCT_FOO = (byte) $e -(struct foo) bar loadstore +(struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" } (byte) foo::thing1 (byte) foo::thing2 (const byte*) foo::thing3[(number) $c] = { fill( $c, 0) } @@ -82,11 +78,11 @@ SYMBOL TABLE SSA Simplifying constant pointer cast (byte*) 1024 Successful SSA optimization PassNCastSimplification -Simple Condition (bool~) main::$0 [15] if((byte) main::j#1!=rangelast(0,$b)) goto main::@1 +Simple Condition (bool~) main::$0 [14] if((byte) main::j#1!=rangelast(0,$b)) goto main::@1 Successful SSA optimization Pass2ConditionalJumpSimplification -Constant right-side identified [2] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1 -Constant right-side identified [5] (byte*~) main::$2 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2 -Constant right-side identified [10] (byte*~) main::$3 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING3 +Constant right-side identified [1] (byte*~) main::$1 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING1 +Constant right-side identified [4] (byte*~) main::$2 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING2 +Constant right-side identified [9] (byte*~) main::$3 ← (byte*)(const struct foo*) main::barp + (const byte) OFFSET_STRUCT_FOO_THING3 Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::i#0 = 0 Constant (const byte*) main::$1 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING1 @@ -94,10 +90,10 @@ Constant (const byte*) main::$2 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING2 Constant (const byte) main::j#0 = 0 Constant (const byte*) main::$3 = (byte*)main::barp+OFFSET_STRUCT_FOO_THING3 Successful SSA optimization Pass2ConstantIdentification -Resolved ranged next value [13] main::j#1 ← ++ main::j#2 to ++ -Resolved ranged comparison value [15] if(main::j#1!=rangelast(0,$b)) goto main::@1 to (number) $c +Resolved ranged next value [12] main::j#1 ← ++ main::j#2 to ++ +Resolved ranged comparison value [14] if(main::j#1!=rangelast(0,$b)) goto main::@1 to (number) $c Simplifying expression containing zero (byte*)main::barp in -Simplifying expression containing zero main::SCREEN in [3] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$1) +Simplifying expression containing zero main::SCREEN in [2] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((const byte*) main::$1) Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1 Successful SSA optimization PassNEliminateUnusedVars @@ -107,11 +103,11 @@ Simplifying constant integer cast $c Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) $c Successful SSA optimization PassNFinalizeNumberTypeConversions -Constant right-side identified [2] (byte) main::i#1 ← ++ (const byte) main::i#0 +Constant right-side identified [1] (byte) main::i#1 ← ++ (const byte) main::i#0 Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::i#1 = ++main::i#0 Successful SSA optimization Pass2ConstantIdentification -Constant right-side identified [3] (byte) main::i#2 ← ++ (const byte) main::i#1 +Constant right-side identified [2] (byte) main::i#2 ← ++ (const byte) main::i#1 Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::i#2 = ++main::i#1 Successful SSA optimization Pass2ConstantIdentification @@ -135,6 +131,7 @@ Successful SSA optimization Pass2ConstantSimplification Simplifying constant integer increment ++1 Successful SSA optimization Pass2ConstantSimplification Added new block during phi lifting main::@3(between main::@1 and main::@1) +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 @end @@ -147,12 +144,13 @@ Coalesced [14] main::i#5 ← main::i#3 Coalesced down to 2 phi equivalence classes Culled Empty Block (label) @2 Culled Empty Block (label) main::@3 +Adding NOP phi() at start of @begin Adding NOP phi() at start of @1 Adding NOP phi() at start of @end FINAL CONTROL FLOW GRAPH @begin: scope:[] from - [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) + [0] phi() to:@1 @1: scope:[] from @begin [1] phi() @@ -180,7 +178,7 @@ main::@return: scope:[main] from main::@1 VARIABLE REGISTER WEIGHTS -(struct foo) bar loadstore +(struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" } (byte) foo::thing1 (byte) foo::thing2 (void()) main() @@ -213,18 +211,10 @@ Target platform is c64basic / MOS6502X :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels - .const SIZEOF_STRUCT_FOO = $e .const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING3 = 2 // @begin __bbegin: - // [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 @@ -285,20 +275,17 @@ main: { rts } // File Data - __0: .byte 'a', 'b' + bar: .byte 'a', 'b' .text "qwe" .byte 0 .fill 8, 0 - bar: .fill SIZEOF_STRUCT_FOO, 0 REGISTER UPLIFT POTENTIAL REGISTERS -Statement [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [ ] ( [ ] ) always clobbers reg byte a reg byte y Statement [4] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [7] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) [ main::j#2 main::i#4 ] ( main:2 [ main::j#2 main::i#4 ] ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::j#2 main::j#1 ] Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::i#4 main::i#3 ] -Statement [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [ ] ( [ ] ) always clobbers reg byte a reg byte y Statement [4] *((const byte*) main::SCREEN) ← *((byte*)(const struct foo*) main::barp) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [7] *((const byte*) main::SCREEN + (byte) main::i#4) ← *((byte*)(const struct foo*) main::barp+(const byte) OFFSET_STRUCT_FOO_THING3 + (byte) main::j#2) [ main::j#2 main::i#4 ] ( main:2 [ main::j#2 main::i#4 ] ) always clobbers reg byte a @@ -311,9 +298,9 @@ Uplift Scope [main] 27.5: zp[1]:2 [ main::j#2 main::j#1 ] 23.83: zp[1]:3 [ main: Uplift Scope [foo] Uplift Scope [] 0: mem[14] [ bar ] -Uplifting [main] best 360 combination reg byte y [ main::j#2 main::j#1 ] reg byte x [ main::i#4 main::i#3 ] -Uplifting [foo] best 360 combination -Uplifting [] best 360 combination mem[14] [ bar ] +Uplifting [main] best 344 combination reg byte y [ main::j#2 main::j#1 ] reg byte x [ main::i#4 main::i#3 ] +Uplifting [foo] best 344 combination +Uplifting [] best 344 combination mem[14] [ bar ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -324,18 +311,10 @@ ASSEMBLER BEFORE OPTIMIZATION :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels - .const SIZEOF_STRUCT_FOO = $e .const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING3 = 2 // @begin __bbegin: - // [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 @@ -389,11 +368,10 @@ main: { rts } // File Data - __0: .byte 'a', 'b' + bar: .byte 'a', 'b' .text "qwe" .byte 0 .fill 8, 0 - bar: .fill SIZEOF_STRUCT_FOO, 0 ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 @@ -401,30 +379,32 @@ Removing instruction jmp __bend Removing instruction jmp __b1 Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination +Replacing label __bbegin with __b1 Replacing label __b1_from___b1 with __b1 +Removing instruction __bbegin: Removing instruction __b1_from___bbegin: Removing instruction __bend_from___b1: Removing instruction __b1_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination -Removing instruction __b1: Removing instruction __bend: Removing instruction __b1_from_main: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination -Adding RTS to root block -Succesful ASM optimization Pass5AddMainRts +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin Removing instruction jmp __b1 Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE -(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" } (label) @1 (label) @begin (label) @end (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2 -(const byte) SIZEOF_STRUCT_FOO = (byte) $e -(struct foo) bar loadstore mem[14] +(struct foo) bar loadstore mem[14] = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" } (byte) foo::thing1 (byte) foo::thing2 (const byte*) foo::thing3[(number) $c] = { fill( $c, 0) } @@ -446,34 +426,22 @@ mem[14] [ bar ] FINAL ASSEMBLER -Score: 270 +Score: 242 // File Comments // Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store) // Test a memory variable struct value - containing a fixed size array // Upstart .pc = $801 "Basic" -:BasicUpstart(__bbegin) +:BasicUpstart(main) .pc = $80d "Program" // Global Constants & labels - .const SIZEOF_STRUCT_FOO = $e .const OFFSET_STRUCT_FOO_THING2 = 1 .const OFFSET_STRUCT_FOO_THING3 = 2 // @begin -__bbegin: - // bar = { 'a', 'b', "qwe" } - // [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- // [1] phi from @begin to @1 [phi:@begin->@1] // @1 // [2] call main - jsr main - rts // [3] phi from @1 to @end [phi:@1->@end] // @end // main @@ -517,9 +485,8 @@ main: { rts } // File Data - __0: .byte 'a', 'b' + bar: .byte 'a', 'b' .text "qwe" .byte 0 .fill 8, 0 - bar: .fill SIZEOF_STRUCT_FOO, 0 diff --git a/src/test/ref/declared-memory-var-4.sym b/src/test/ref/declared-memory-var-4.sym index b5896b640..f94b9f8ce 100644 --- a/src/test/ref/declared-memory-var-4.sym +++ b/src/test/ref/declared-memory-var-4.sym @@ -1,11 +1,9 @@ -(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" } (label) @1 (label) @begin (label) @end (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 (const byte) OFFSET_STRUCT_FOO_THING3 = (byte) 2 -(const byte) SIZEOF_STRUCT_FOO = (byte) $e -(struct foo) bar loadstore mem[14] +(struct foo) bar loadstore mem[14] = { thing1: (byte) 'a', thing2: (byte) 'b', thing3: (string) "qwe" } (byte) foo::thing1 (byte) foo::thing2 (const byte*) foo::thing3[(number) $c] = { fill( $c, 0) } diff --git a/src/test/ref/declared-memory-var-5.asm b/src/test/ref/declared-memory-var-5.asm index af256a2a2..f4e3888f2 100644 --- a/src/test/ref/declared-memory-var-5.asm +++ b/src/test/ref/declared-memory-var-5.asm @@ -1,19 +1,9 @@ // Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store) // Test a memory variable struct value .pc = $801 "Basic" -:BasicUpstart(__bbegin) +:BasicUpstart(main) .pc = $80d "Program" - .const SIZEOF_STRUCT_FOO = 2 .const OFFSET_STRUCT_FOO_THING2 = 1 -__bbegin: - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- - jsr main - rts main: { .label SCREEN = $400 lda bar @@ -22,5 +12,4 @@ main: { sta SCREEN+1 rts } - __0: .byte 'a', 'b' - bar: .fill SIZEOF_STRUCT_FOO, 0 + bar: .byte 'a', 'b' diff --git a/src/test/ref/declared-memory-var-5.cfg b/src/test/ref/declared-memory-var-5.cfg index 834f78a0a..f4e42c791 100644 --- a/src/test/ref/declared-memory-var-5.cfg +++ b/src/test/ref/declared-memory-var-5.cfg @@ -1,5 +1,5 @@ @begin: scope:[] from - [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) + [0] phi() to:@1 @1: scope:[] from @begin [1] phi() diff --git a/src/test/ref/declared-memory-var-5.log b/src/test/ref/declared-memory-var-5.log index b44d3e519..541494122 100644 --- a/src/test/ref/declared-memory-var-5.log +++ b/src/test/ref/declared-memory-var-5.log @@ -1,10 +1,8 @@ -Adding struct value member variable copy *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) Replacing struct member reference (struct foo) bar.thing1 with member unwinding reference *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING1) Replacing struct member reference (struct foo) bar.thing2 with member unwinding reference *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) CONTROL FLOW GRAPH SSA @begin: scope:[] from - *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) to:@1 (void()) main() @@ -26,15 +24,13 @@ main::@return: scope:[main] from main @end: scope:[] from @2 SYMBOL TABLE SSA -(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' } (label) @1 (label) @2 (label) @begin (label) @end (const byte) OFFSET_STRUCT_FOO_THING1 = (byte) 0 (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 -(const byte) SIZEOF_STRUCT_FOO = (byte) 2 -(struct foo) bar loadstore +(struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b' } (byte) foo::thing1 (byte) foo::thing2 (void()) main() @@ -49,13 +45,13 @@ Simplifying constant pointer cast (byte*) 1024 Successful SSA optimization PassNCastSimplification Constant (const byte) main::i#0 = 0 Successful SSA optimization Pass2ConstantIdentification -Simplifying expression containing zero (byte*)&bar in [2] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING1) -Simplifying expression containing zero main::SCREEN in [2] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)&(struct foo) bar) +Simplifying expression containing zero (byte*)&bar in [1] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING1) +Simplifying expression containing zero main::SCREEN in [1] *((const byte*) main::SCREEN + (const byte) main::i#0) ← *((byte*)&(struct foo) bar) Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (byte) main::i#2 and assignment [4] (byte) main::i#2 ← ++ (byte) main::i#1 +Eliminating unused variable (byte) main::i#2 and assignment [3] (byte) main::i#2 ← ++ (byte) main::i#1 Eliminating unused constant (const byte) OFFSET_STRUCT_FOO_THING1 Successful SSA optimization PassNEliminateUnusedVars -Constant right-side identified [2] (byte) main::i#1 ← ++ (const byte) main::i#0 +Constant right-side identified [1] (byte) main::i#1 ← ++ (const byte) main::i#0 Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::i#1 = ++main::i#0 Successful SSA optimization Pass2ConstantIdentification @@ -68,6 +64,7 @@ Consolidated array index constant in *(main::SCREEN+++0) Successful SSA optimization Pass2ConstantAdditionElimination Simplifying constant integer increment ++0 Successful SSA optimization Pass2ConstantSimplification +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 @end @@ -77,12 +74,13 @@ Calls in [] to main:2 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin Adding NOP phi() at start of @1 Adding NOP phi() at start of @end FINAL CONTROL FLOW GRAPH @begin: scope:[] from - [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) + [0] phi() to:@1 @1: scope:[] from @begin [1] phi() @@ -102,7 +100,7 @@ main::@return: scope:[main] from main VARIABLE REGISTER WEIGHTS -(struct foo) bar loadstore +(struct foo) bar loadstore = { thing1: (byte) 'a', thing2: (byte) 'b' } (byte) foo::thing1 (byte) foo::thing2 (void()) main() @@ -124,17 +122,9 @@ Target platform is c64basic / MOS6502X :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels - .const SIZEOF_STRUCT_FOO = 2 .const OFFSET_STRUCT_FOO_THING2 = 1 // @begin __bbegin: - // [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 @@ -163,11 +153,9 @@ main: { rts } // File Data - __0: .byte 'a', 'b' - bar: .fill SIZEOF_STRUCT_FOO, 0 + bar: .byte 'a', 'b' REGISTER UPLIFT POTENTIAL REGISTERS -Statement [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) [ bar ] ( [ bar ] ) always clobbers reg byte a reg byte y Statement [4] *((const byte*) main::SCREEN) ← *((byte*)&(struct foo) bar) [ bar ] ( main:2 [ bar ] ) always clobbers reg byte a Statement [5] *((const byte*) main::SCREEN+(byte) 1) ← *((byte*)&(struct foo) bar+(const byte) OFFSET_STRUCT_FOO_THING2) [ ] ( main:2 [ ] ) always clobbers reg byte a Potential registers mem[2] [ bar ] : mem[2] , @@ -177,9 +165,9 @@ Uplift Scope [foo] Uplift Scope [main] Uplift Scope [] 0: mem[2] [ bar ] -Uplifting [foo] best 53 combination -Uplifting [main] best 53 combination -Uplifting [] best 53 combination mem[2] [ bar ] +Uplifting [foo] best 37 combination +Uplifting [main] best 37 combination +Uplifting [] best 37 combination mem[2] [ bar ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -190,17 +178,9 @@ ASSEMBLER BEFORE OPTIMIZATION :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels - .const SIZEOF_STRUCT_FOO = 2 .const OFFSET_STRUCT_FOO_THING2 = 1 // @begin __bbegin: - // [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- // [1] phi from @begin to @1 [phi:@begin->@1] __b1_from___bbegin: jmp __b1 @@ -229,32 +209,33 @@ main: { rts } // File Data - __0: .byte 'a', 'b' - bar: .fill SIZEOF_STRUCT_FOO, 0 + bar: .byte 'a', 'b' ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __bend Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination +Replacing label __bbegin with __b1 +Removing instruction __bbegin: Removing instruction __b1_from___bbegin: Removing instruction __bend_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination -Removing instruction __b1: Removing instruction __bend: Removing instruction __breturn: Succesful ASM optimization Pass5UnusedLabelElimination -Adding RTS to root block -Succesful ASM optimization Pass5AddMainRts +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE -(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' } (label) @1 (label) @begin (label) @end (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 -(const byte) SIZEOF_STRUCT_FOO = (byte) 2 -(struct foo) bar loadstore mem[2] +(struct foo) bar loadstore mem[2] = { thing1: (byte) 'a', thing2: (byte) 'b' } (byte) foo::thing1 (byte) foo::thing2 (void()) main() @@ -266,33 +247,21 @@ mem[2] [ bar ] FINAL ASSEMBLER -Score: 50 +Score: 22 // File Comments // Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store) // Test a memory variable struct value // Upstart .pc = $801 "Basic" -:BasicUpstart(__bbegin) +:BasicUpstart(main) .pc = $80d "Program" // Global Constants & labels - .const SIZEOF_STRUCT_FOO = 2 .const OFFSET_STRUCT_FOO_THING2 = 1 // @begin -__bbegin: - // bar = { 'a', 'b' } - // [0] *(&(struct foo) bar) ← memcpy(*(&(const struct foo) $0), struct foo, (const byte) SIZEOF_STRUCT_FOO) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 - ldy #SIZEOF_STRUCT_FOO -!: - lda __0-1,y - sta bar-1,y - dey - bne !- // [1] phi from @begin to @1 [phi:@begin->@1] // @1 // [2] call main - jsr main - rts // [3] phi from @1 to @end [phi:@1->@end] // @end // main @@ -312,6 +281,5 @@ main: { rts } // File Data - __0: .byte 'a', 'b' - bar: .fill SIZEOF_STRUCT_FOO, 0 + bar: .byte 'a', 'b' diff --git a/src/test/ref/declared-memory-var-5.sym b/src/test/ref/declared-memory-var-5.sym index 7f8d48c4c..dd276379c 100644 --- a/src/test/ref/declared-memory-var-5.sym +++ b/src/test/ref/declared-memory-var-5.sym @@ -1,10 +1,8 @@ -(const struct foo) $0 = { thing1: (byte) 'a', thing2: (byte) 'b' } (label) @1 (label) @begin (label) @end (const byte) OFFSET_STRUCT_FOO_THING2 = (byte) 1 -(const byte) SIZEOF_STRUCT_FOO = (byte) 2 -(struct foo) bar loadstore mem[2] +(struct foo) bar loadstore mem[2] = { thing1: (byte) 'a', thing2: (byte) 'b' } (byte) foo::thing1 (byte) foo::thing2 (void()) main()