Merge branch 'master' into 372-varcall-progress

This commit is contained in:
jespergravgaard 2023-04-05 17:17:16 +02:00
commit 271163a25f
30 changed files with 1242 additions and 6 deletions

View File

@ -243,9 +243,10 @@ expr
| expr ( '&&' ) expr #exprBinary
| expr ( '||' ) expr #exprBinary
| expr '?' expr COLON expr #exprTernary
| <assoc=right> expr '=' expr #exprAssignment
| <assoc=right> expr ASSIGN expr #exprAssignment
| <assoc=right> expr ASSIGN_COMPOUND expr #exprAssignmentCompound
| CURLY_BEGIN expr (COMMA expr )* COMMA? CURLY_END #initList
| CURLY_BEGIN DOT NAME ASSIGN expr CURLY_END #initUnion
| NAME #exprId
| NUMBER #exprNumber
| STRING+ #exprString

View File

@ -89,6 +89,8 @@ public class Initializers {
return new ConstantCastValue(toType, (ConstantValue) constantSub);
}
}
} else if(initValue instanceof UnionDesignator) {
initValue = constantifyUnion((UnionDesignator) initValue, (SymbolTypeStruct) typeSpec.getType(), program, source);
} else if(initValue instanceof ValueList) {
ValueList initList = (ValueList) initValue;
if(typeSpec.getType() instanceof SymbolTypePointer && ((SymbolTypePointer) typeSpec.getType()).getArraySpec() != null) {
@ -96,7 +98,7 @@ public class Initializers {
initValue = constantifyArray(initList, (SymbolTypePointer) typeSpec.getType(), program, source);
} else if(typeSpec.getType() instanceof SymbolTypeStruct) {
// Type is a struct
initValue = constantifyStruct(initList, (SymbolTypeStruct) typeSpec.getType(), program, source);
initValue = constantifyStructOrUnion(initList, (SymbolTypeStruct) typeSpec.getType(), program, source);
} else {
throw new CompileError("Value list cannot initialize type " + typeSpec.getType(), source);
}
@ -127,6 +129,41 @@ public class Initializers {
return initValue;
}
/**
* Convert a union designator initializer to a constant.
*
* @param unionInit The union initializer
* @param structType The union type
* @param program The program
* @param source The source line
* @return The constantified value
*/
private static RValue constantifyUnion(UnionDesignator unionInit, SymbolTypeStruct structType, Program program, StatementSource source) {
StructDefinition structDefinition = structType.getStructDefinition(program.getScope());
Collection<Variable> memberDefinitions = structDefinition.getAllVars(false);
final String memberName = unionInit.getMemberName();
final RValue initValue = unionInit.getMemberValue();
Variable memberDef = null;
for(Variable definition : memberDefinitions) {
if(definition.getLocalName().equals(memberName)) {
memberDef = definition;
}
}
if(memberDef==null)
throw new CompileError( "Union member not found", source);
RValue constantifiedMemberValue = constantify(initValue, new ValueTypeSpec(memberDef.getType()), program, source);
if(constantifiedMemberValue instanceof ConstantValue) {
LinkedHashMap<SymbolVariableRef, ConstantValue> constMemberMap = new LinkedHashMap<>();
constMemberMap.put(memberDef.getRef(), (ConstantValue) constantifiedMemberValue);
return new ConstantStructValue(structType, constMemberMap);
} else {
throw new CompileError( "Union initializer is not constant", source);
}
}
/**
* Convert as much as possible of a struct to constants.
*
@ -136,7 +173,7 @@ public class Initializers {
* @param source The source line
* @return The constantified value
*/
private static RValue constantifyStruct(ValueList valueList, SymbolTypeStruct structType, Program program, StatementSource source) {
private static RValue constantifyStructOrUnion(ValueList valueList, SymbolTypeStruct structType, Program program, StatementSource source) {
// Recursively cast all sub-elements
StructDefinition structDefinition = structType.getStructDefinition(program.getScope());
Collection<Variable> memberDefinitions = structDefinition.getAllVars(false);
@ -144,7 +181,7 @@ public class Initializers {
if(structInitNeedSize != valueList.getList().size()) {
if(structDefinition.isUnion()) {
throw new CompileError(
"Union initializer has too many values, since only one is allowed.\n" +
"Union initializer has wrong size. One value is required.\n" +
" Union initializer: " + valueList.toString(program),
source);
} else {

View File

@ -0,0 +1,40 @@
package dk.camelot64.kickc.model.values;
import dk.camelot64.kickc.model.Program;
/**
* A union designator initializer.
*/
public class UnionDesignator implements RValue {
private final String memberName;
private final RValue rValue;
public UnionDesignator(String memberName, RValue rValue) {
this.memberName = memberName;
this.rValue = rValue;
}
public String getMemberName() { return memberName; }
public RValue getMemberValue() {
return rValue;
}
@Override
public String toString(Program program) {
StringBuilder out = new StringBuilder();
out.append("{ ");
out.append(memberName);
out.append("=");
out.append(rValue.toString(program));
out.append(" }");
return out.toString();
}
@Override
public String toString() {
return toString(null);
}
}

View File

@ -1913,13 +1913,20 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
return null;
}
@Override
public RValue visitInitUnion(KickCParser.InitUnionContext ctx) {
final String memberName = ctx.NAME().getText();
final RValue rValue = (RValue) visit(ctx.expr());
return new UnionDesignator(memberName, rValue);
}
@Override
public RValue visitInitList(KickCParser.InitListContext ctx) {
List<RValue> initValues = new ArrayList<>();
for(KickCParser.ExprContext initializer : ctx.expr()) {
RValue rValue = (RValue) visit(initializer);
initValues.add(rValue);
}
initValues.add(rValue);
}
return new ValueList(initValues);
}

View File

@ -2557,6 +2557,31 @@ public class TestProgramsFast extends TestPrograms {
compileAndCompare("weeip-bbslist.c");
}
@Test
public void testUnion13() throws IOException {
compileAndCompare("union-13.c");
}
@Test
public void testUnion12() throws IOException {
compileAndCompare("union-12.c");
}
@Test
public void testUnion11() throws IOException {
compileAndCompare("union-11.c");
}
@Test
public void testUnion10() throws IOException {
compileAndCompare("union-10.c");
}
@Test
public void testUnion9() throws IOException {
compileAndCompare("union-9.c");
}
@Test
public void testUnion8() throws IOException {
compileAndCompare("union-8.c");

27
src/test/kc/union-10.c Normal file
View File

@ -0,0 +1,27 @@
// More extensive union with C99 style designator initialization behaviour of the second element.
struct Move {
char f;
char t;
char s;
};
struct Turn {
char t;
char s;
char r;
char d;
};
union Data {
struct Move m;
struct Turn t;
};
union Data data = { .t={1,2,3,4} };
char* const SCREEN = (char*)0x0400;
void main() {
SCREEN[0] = data.m.f;
}

27
src/test/kc/union-11.c Normal file
View File

@ -0,0 +1,27 @@
// More extensive union with C99 style designator initialization behaviour of the first element.
struct Move {
char f;
char t;
char s;
};
struct Turn {
char t;
char s;
char r;
char d;
};
union Data {
struct Move m;
struct Turn t;
};
union Data data = { .m={1,2,3} };
char* const SCREEN = (char*)0x0400;
void main() {
SCREEN[0] = data.m.f;
}

29
src/test/kc/union-12.c Normal file
View File

@ -0,0 +1,29 @@
// More extensive union with C99 style designator initialization behaviour using const expressions.
struct Move {
char f;
char t;
char s;
};
struct Turn {
char t;
char s;
char r;
char d;
};
union Data {
struct Move m;
struct Turn t;
};
const struct Move move = {1,2,3};
union Data data = { .m=move };
char* const SCREEN = (char*)0x0400;
void main() {
SCREEN[0] = data.m.f;
}

20
src/test/kc/union-13.c Normal file
View File

@ -0,0 +1,20 @@
// More extensive union with C99 style designator initialization behaviour using const expressions.
union A {
unsigned char b;
unsigned int w;
};
union B {
union A a;
char b[4];
};
union B b1 = { .a={ .b=1 } };
char* const SCREEN = (char*)0x0400;
void main() {
SCREEN[0] = b1.b[0];
}

14
src/test/kc/union-9.c Normal file
View File

@ -0,0 +1,14 @@
// Minimal union with C99 style designator initialization behaviour.
union Data {
char b;
unsigned w;
};
union Data data = { .w=1234 };
char* const SCREEN = (char*)0x0400;
void main() {
SCREEN[0] = data.b;
}

20
src/test/ref/union-10.asm Normal file
View File

@ -0,0 +1,20 @@
// More extensive union with C99 style designator initialization behaviour of the second element.
// Commodore 64 PRG executable file
.file [name="union-10.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.label SCREEN = $400
.segment Code
main: {
// SCREEN[0] = data.m.f
lda data
sta SCREEN
// }
rts
}
.segment Data
data: .byte 1, 2, 3, 4

View File

@ -0,0 +1,8 @@
void main()
main: scope:[main] from
[0] *SCREEN = *((char *)(struct Move *)&data)
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return

166
src/test/ref/union-10.log Normal file
View File

@ -0,0 +1,166 @@
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M+OFFSET_STRUCT_MOVE_F)
to:main::@return
main::@return: scope:[main] from main
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
__constant char OFFSET_STRUCT_MOVE_F = 0
__constant char OFFSET_UNION_DATA_M = 0
__constant char * const SCREEN = (char *)$400
void __start()
__loadstore union Data data = { t: { t: 1, s: 2, r: 3, d: 4 } }
void main()
Adding number conversion cast (unumber) 0 in SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M+OFFSET_STRUCT_MOVE_F)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (char *) 1024
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simplifying expression containing zero (char *)(struct Move *)&data+OFFSET_UNION_DATA_M in [0] SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M+OFFSET_STRUCT_MOVE_F)
Simplifying expression containing zero (struct Move *)&data in [0] SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M)
Simplifying expression containing zero SCREEN in [0] SCREEN[0] = *((char *)(struct Move *)&data)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant OFFSET_UNION_DATA_M
Eliminating unused constant OFFSET_STRUCT_MOVE_F
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] *SCREEN = *((char *)(struct Move *)&data)
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return
VARIABLE REGISTER WEIGHTS
__loadstore union Data data = { t: { t: 1, s: 2, r: 3, d: 4 } }
void main()
Initial phi equivalence classes
Added variable data to live range equivalence class [ data ]
Complete equivalence classes
[ data ]
Allocated mem[4] [ data ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *SCREEN = *((char *)(struct Move *)&data) [ ] ( [ ] { } ) always clobbers reg byte a
Potential registers mem[4] [ data ] : mem[4] ,
REGISTER UPLIFT SCOPES
Uplift Scope [Move]
Uplift Scope [Turn]
Uplift Scope [Data]
Uplift Scope [main]
Uplift Scope [] 0: mem[4] [ data ]
Uplifting [Move] best 17 combination
Uplifting [Turn] best 17 combination
Uplifting [Data] best 17 combination
Uplifting [main] best 17 combination
Uplifting [] best 17 combination mem[4] [ data ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// More extensive union with C99 style designator initialization behaviour of the second element.
// Upstart
// Commodore 64 PRG executable file
.file [name="union-10.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// [0] *SCREEN = *((char *)(struct Move *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
.segment Data
data: .byte 1, 2, 3, 4
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
__constant char * const SCREEN = (char *) 1024
__loadstore union Data data = { t: { t: 1, s: 2, r: 3, d: 4 } } // mem[4]
void main()
mem[4] [ data ]
FINAL ASSEMBLER
Score: 14
// File Comments
// More extensive union with C99 style designator initialization behaviour of the second element.
// Upstart
// Commodore 64 PRG executable file
.file [name="union-10.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// SCREEN[0] = data.m.f
// [0] *SCREEN = *((char *)(struct Move *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
// main::@return
// }
// [1] return
rts
}
// File Data
.segment Data
data: .byte 1, 2, 3, 4

View File

@ -0,0 +1,5 @@
__constant char * const SCREEN = (char *) 1024
__loadstore union Data data = { t: { t: 1, s: 2, r: 3, d: 4 } } // mem[4]
void main()
mem[4] [ data ]

21
src/test/ref/union-11.asm Normal file
View File

@ -0,0 +1,21 @@
// More extensive union with C99 style designator initialization behaviour of the first element.
// Commodore 64 PRG executable file
.file [name="union-11.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.label SCREEN = $400
.segment Code
main: {
// SCREEN[0] = data.m.f
lda data
sta SCREEN
// }
rts
}
.segment Data
data: .byte 1, 2, 3
.fill 1, 0

View File

@ -0,0 +1,8 @@
void main()
main: scope:[main] from
[0] *SCREEN = *((char *)(struct Move *)&data)
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return

168
src/test/ref/union-11.log Normal file
View File

@ -0,0 +1,168 @@
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M+OFFSET_STRUCT_MOVE_F)
to:main::@return
main::@return: scope:[main] from main
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
__constant char OFFSET_STRUCT_MOVE_F = 0
__constant char OFFSET_UNION_DATA_M = 0
__constant char * const SCREEN = (char *)$400
void __start()
__loadstore union Data data = { m: { f: 1, t: 2, s: 3 } }
void main()
Adding number conversion cast (unumber) 0 in SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M+OFFSET_STRUCT_MOVE_F)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (char *) 1024
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simplifying expression containing zero (char *)(struct Move *)&data+OFFSET_UNION_DATA_M in [0] SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M+OFFSET_STRUCT_MOVE_F)
Simplifying expression containing zero (struct Move *)&data in [0] SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M)
Simplifying expression containing zero SCREEN in [0] SCREEN[0] = *((char *)(struct Move *)&data)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant OFFSET_UNION_DATA_M
Eliminating unused constant OFFSET_STRUCT_MOVE_F
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] *SCREEN = *((char *)(struct Move *)&data)
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return
VARIABLE REGISTER WEIGHTS
__loadstore union Data data = { m: { f: 1, t: 2, s: 3 } }
void main()
Initial phi equivalence classes
Added variable data to live range equivalence class [ data ]
Complete equivalence classes
[ data ]
Allocated mem[4] [ data ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *SCREEN = *((char *)(struct Move *)&data) [ ] ( [ ] { } ) always clobbers reg byte a
Potential registers mem[4] [ data ] : mem[4] ,
REGISTER UPLIFT SCOPES
Uplift Scope [Move]
Uplift Scope [Turn]
Uplift Scope [Data]
Uplift Scope [main]
Uplift Scope [] 0: mem[4] [ data ]
Uplifting [Move] best 17 combination
Uplifting [Turn] best 17 combination
Uplifting [Data] best 17 combination
Uplifting [main] best 17 combination
Uplifting [] best 17 combination mem[4] [ data ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// More extensive union with C99 style designator initialization behaviour of the first element.
// Upstart
// Commodore 64 PRG executable file
.file [name="union-11.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// [0] *SCREEN = *((char *)(struct Move *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
.segment Data
data: .byte 1, 2, 3
.fill 1, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
__constant char * const SCREEN = (char *) 1024
__loadstore union Data data = { m: { f: 1, t: 2, s: 3 } } // mem[4]
void main()
mem[4] [ data ]
FINAL ASSEMBLER
Score: 14
// File Comments
// More extensive union with C99 style designator initialization behaviour of the first element.
// Upstart
// Commodore 64 PRG executable file
.file [name="union-11.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// SCREEN[0] = data.m.f
// [0] *SCREEN = *((char *)(struct Move *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
// main::@return
// }
// [1] return
rts
}
// File Data
.segment Data
data: .byte 1, 2, 3
.fill 1, 0

View File

@ -0,0 +1,5 @@
__constant char * const SCREEN = (char *) 1024
__loadstore union Data data = { m: { f: 1, t: 2, s: 3 } } // mem[4]
void main()
mem[4] [ data ]

21
src/test/ref/union-12.asm Normal file
View File

@ -0,0 +1,21 @@
// More extensive union with C99 style designator initialization behaviour using const expressions.
// Commodore 64 PRG executable file
.file [name="union-12.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.label SCREEN = $400
.segment Code
main: {
// SCREEN[0] = data.m.f
lda data
sta SCREEN
// }
rts
}
.segment Data
move: .byte 1, 2, 3
data: .fill 1, 0

View File

@ -0,0 +1,8 @@
void main()
main: scope:[main] from
[0] *SCREEN = *((char *)(struct Move *)&data)
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return

170
src/test/ref/union-12.log Normal file
View File

@ -0,0 +1,170 @@
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M+OFFSET_STRUCT_MOVE_F)
to:main::@return
main::@return: scope:[main] from main
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
__constant char OFFSET_STRUCT_MOVE_F = 0
__constant char OFFSET_UNION_DATA_M = 0
__constant char * const SCREEN = (char *)$400
void __start()
__loadstore union Data data = { m: move }
void main()
__constant const struct Move move = { f: 1, t: 2, s: 3 }
Adding number conversion cast (unumber) 0 in SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M+OFFSET_STRUCT_MOVE_F)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (char *) 1024
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simplifying expression containing zero (char *)(struct Move *)&data+OFFSET_UNION_DATA_M in [0] SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M+OFFSET_STRUCT_MOVE_F)
Simplifying expression containing zero (struct Move *)&data in [0] SCREEN[0] = *((char *)(struct Move *)&data+OFFSET_UNION_DATA_M)
Simplifying expression containing zero SCREEN in [0] SCREEN[0] = *((char *)(struct Move *)&data)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant OFFSET_UNION_DATA_M
Eliminating unused constant OFFSET_STRUCT_MOVE_F
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] *SCREEN = *((char *)(struct Move *)&data)
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return
VARIABLE REGISTER WEIGHTS
__loadstore union Data data = { m: move }
void main()
Initial phi equivalence classes
Added variable data to live range equivalence class [ data ]
Complete equivalence classes
[ data ]
Allocated mem[4] [ data ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *SCREEN = *((char *)(struct Move *)&data) [ ] ( [ ] { } ) always clobbers reg byte a
Potential registers mem[4] [ data ] : mem[4] ,
REGISTER UPLIFT SCOPES
Uplift Scope [Move]
Uplift Scope [Turn]
Uplift Scope [Data]
Uplift Scope [main]
Uplift Scope [] 0: mem[4] [ data ]
Uplifting [Move] best 17 combination
Uplifting [Turn] best 17 combination
Uplifting [Data] best 17 combination
Uplifting [main] best 17 combination
Uplifting [] best 17 combination mem[4] [ data ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// More extensive union with C99 style designator initialization behaviour using const expressions.
// Upstart
// Commodore 64 PRG executable file
.file [name="union-12.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// [0] *SCREEN = *((char *)(struct Move *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
.segment Data
move: .byte 1, 2, 3
data: .fill 1, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
__constant char * const SCREEN = (char *) 1024
__loadstore union Data data = { m: move } // mem[4]
void main()
__constant const struct Move move = { f: 1, t: 2, s: 3 }
mem[4] [ data ]
FINAL ASSEMBLER
Score: 14
// File Comments
// More extensive union with C99 style designator initialization behaviour using const expressions.
// Upstart
// Commodore 64 PRG executable file
.file [name="union-12.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// SCREEN[0] = data.m.f
// [0] *SCREEN = *((char *)(struct Move *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
// main::@return
// }
// [1] return
rts
}
// File Data
.segment Data
move: .byte 1, 2, 3
data: .fill 1, 0

View File

@ -0,0 +1,6 @@
__constant char * const SCREEN = (char *) 1024
__loadstore union Data data = { m: move } // mem[4]
void main()
__constant const struct Move move = { f: 1, t: 2, s: 3 }
mem[4] [ data ]

22
src/test/ref/union-13.asm Normal file
View File

@ -0,0 +1,22 @@
// More extensive union with C99 style designator initialization behaviour using const expressions.
// Commodore 64 PRG executable file
.file [name="union-13.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.label SCREEN = $400
.segment Code
main: {
// SCREEN[0] = b1.b[0]
lda b1
sta SCREEN
// }
rts
}
.segment Data
b1: .byte 1
.fill 1, 0
.fill 2, 0

View File

@ -0,0 +1,8 @@
void main()
main: scope:[main] from
[0] *SCREEN = *((char *)&b1)
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return

176
src/test/ref/union-13.log Normal file
View File

@ -0,0 +1,176 @@
Fixing struct type size union B to 4
Fixing struct type size union B to 4
Fixing struct type SIZE_OF union B to 4
Fixing struct type SIZE_OF union B to 4
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
SCREEN[0] = ((char *)&b1+OFFSET_UNION_B_B)[0]
to:main::@return
main::@return: scope:[main] from main
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
__constant char OFFSET_UNION_B_B = 0
__constant char * const SCREEN = (char *)$400
void __start()
__loadstore union B b1 = { a: { b: 1 } }
void main()
Adding number conversion cast (unumber) 0 in SCREEN[0] = ((char *)&b1+OFFSET_UNION_B_B)[0]
Adding number conversion cast (unumber) 0 in SCREEN[0] = ((char *)&b1+OFFSET_UNION_B_B)[(unumber)0]
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (char *) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) 0
Finalized unsigned number type (char) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simplifying expression containing zero (char *)&b1+OFFSET_UNION_B_B in [0] SCREEN[0] = ((char *)&b1+OFFSET_UNION_B_B)[0]
Simplifying expression containing zero (char *)&b1 in [0] SCREEN[0] = *((char *)&b1+OFFSET_UNION_B_B)
Simplifying expression containing zero SCREEN in [0] SCREEN[0] = *((char *)&b1)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant OFFSET_UNION_B_B
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
Finalized unsigned number type (char) 4
Finalized unsigned number type (char) 4
Successful SSA optimization PassNFinalizeNumberTypeConversions
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] *SCREEN = *((char *)&b1)
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return
VARIABLE REGISTER WEIGHTS
__loadstore union B b1 = { a: { b: 1 } }
void main()
Initial phi equivalence classes
Added variable b1 to live range equivalence class [ b1 ]
Complete equivalence classes
[ b1 ]
Allocated mem[4] [ b1 ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *SCREEN = *((char *)&b1) [ ] ( [ ] { } ) always clobbers reg byte a
Potential registers mem[4] [ b1 ] : mem[4] ,
REGISTER UPLIFT SCOPES
Uplift Scope [A]
Uplift Scope [B]
Uplift Scope [main]
Uplift Scope [] 0: mem[4] [ b1 ]
Uplifting [A] best 17 combination
Uplifting [B] best 17 combination
Uplifting [main] best 17 combination
Uplifting [] best 17 combination mem[4] [ b1 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// More extensive union with C99 style designator initialization behaviour using const expressions.
// Upstart
// Commodore 64 PRG executable file
.file [name="union-13.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// [0] *SCREEN = *((char *)&b1) -- _deref_pbuc1=_deref_pbuc2
lda b1
sta SCREEN
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
.segment Data
b1: .byte 1
.fill 1, 0
.fill 2, 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
__constant char * const SCREEN = (char *) 1024
__loadstore union B b1 = { a: { b: 1 } } // mem[4]
void main()
mem[4] [ b1 ]
FINAL ASSEMBLER
Score: 14
// File Comments
// More extensive union with C99 style designator initialization behaviour using const expressions.
// Upstart
// Commodore 64 PRG executable file
.file [name="union-13.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// SCREEN[0] = b1.b[0]
// [0] *SCREEN = *((char *)&b1) -- _deref_pbuc1=_deref_pbuc2
lda b1
sta SCREEN
// main::@return
// }
// [1] return
rts
}
// File Data
.segment Data
b1: .byte 1
.fill 1, 0
.fill 2, 0

View File

@ -0,0 +1,5 @@
__constant char * const SCREEN = (char *) 1024
__loadstore union B b1 = { a: { b: 1 } } // mem[4]
void main()
mem[4] [ b1 ]

20
src/test/ref/union-9.asm Normal file
View File

@ -0,0 +1,20 @@
// Minimal union with C99 style designator initialization behaviour.
// Commodore 64 PRG executable file
.file [name="union-9.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
.label SCREEN = $400
.segment Code
main: {
// SCREEN[0] = data.b
lda data
sta SCREEN
// }
rts
}
.segment Data
data: .word $4d2

8
src/test/ref/union-9.cfg Normal file
View File

@ -0,0 +1,8 @@
void main()
main: scope:[main] from
[0] *SCREEN = *((char *)&data)
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return

159
src/test/ref/union-9.log Normal file
View File

@ -0,0 +1,159 @@
CONTROL FLOW GRAPH SSA
void main()
main: scope:[main] from __start
SCREEN[0] = *((char *)&data+OFFSET_UNION_DATA_B)
to:main::@return
main::@return: scope:[main] from main
return
to:@return
void __start()
__start: scope:[__start] from
call main
to:__start::@1
__start::@1: scope:[__start] from __start
to:__start::@return
__start::@return: scope:[__start] from __start::@1
return
to:@return
SYMBOL TABLE SSA
__constant char OFFSET_UNION_DATA_B = 0
__constant char * const SCREEN = (char *)$400
void __start()
__loadstore union Data data = { w: $4d2 }
void main()
Adding number conversion cast (unumber) 0 in SCREEN[0] = *((char *)&data+OFFSET_UNION_DATA_B)
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant pointer cast (char *) 1024
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Simplifying expression containing zero (char *)&data in [0] SCREEN[0] = *((char *)&data+OFFSET_UNION_DATA_B)
Simplifying expression containing zero SCREEN in [0] SCREEN[0] = *((char *)&data)
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant OFFSET_UNION_DATA_B
Successful SSA optimization PassNEliminateUnusedVars
Removing unused procedure __start
Removing unused procedure block __start
Removing unused procedure block __start::@1
Removing unused procedure block __start::@return
Successful SSA optimization PassNEliminateEmptyStart
CALL GRAPH
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
FINAL CONTROL FLOW GRAPH
void main()
main: scope:[main] from
[0] *SCREEN = *((char *)&data)
to:main::@return
main::@return: scope:[main] from main
[1] return
to:@return
VARIABLE REGISTER WEIGHTS
__loadstore union Data data = { w: $4d2 }
void main()
Initial phi equivalence classes
Added variable data to live range equivalence class [ data ]
Complete equivalence classes
[ data ]
Allocated mem[2] [ data ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [0] *SCREEN = *((char *)&data) [ ] ( [ ] { } ) always clobbers reg byte a
Potential registers mem[2] [ data ] : mem[2] ,
REGISTER UPLIFT SCOPES
Uplift Scope [Data]
Uplift Scope [main]
Uplift Scope [] 0: mem[2] [ data ]
Uplifting [Data] best 17 combination
Uplifting [main] best 17 combination
Uplifting [] best 17 combination mem[2] [ data ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Minimal union with C99 style designator initialization behaviour.
// Upstart
// Commodore 64 PRG executable file
.file [name="union-9.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// [0] *SCREEN = *((char *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
jmp __breturn
// main::@return
__breturn:
// [1] return
rts
}
// File Data
.segment Data
data: .word $4d2
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
__constant char * const SCREEN = (char *) 1024
__loadstore union Data data = { w: $4d2 } // mem[2]
void main()
mem[2] [ data ]
FINAL ASSEMBLER
Score: 14
// File Comments
// Minimal union with C99 style designator initialization behaviour.
// Upstart
// Commodore 64 PRG executable file
.file [name="union-9.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
// Global Constants & labels
.label SCREEN = $400
.segment Code
// main
main: {
// SCREEN[0] = data.b
// [0] *SCREEN = *((char *)&data) -- _deref_pbuc1=_deref_pbuc2
lda data
sta SCREEN
// main::@return
// }
// [1] return
rts
}
// File Data
.segment Data
data: .word $4d2

5
src/test/ref/union-9.sym Normal file
View File

@ -0,0 +1,5 @@
__constant char * const SCREEN = (char *) 1024
__loadstore union Data data = { w: $4d2 } // mem[2]
void main()
mem[2] [ data ]