mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-21 14:30:21 +00:00
Merge branch 'master' into 372-varcall-progress
This commit is contained in:
commit
271163a25f
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
27
src/test/kc/union-10.c
Normal 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
27
src/test/kc/union-11.c
Normal 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
29
src/test/kc/union-12.c
Normal 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
20
src/test/kc/union-13.c
Normal 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
14
src/test/kc/union-9.c
Normal 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
20
src/test/ref/union-10.asm
Normal 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
|
8
src/test/ref/union-10.cfg
Normal file
8
src/test/ref/union-10.cfg
Normal 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
166
src/test/ref/union-10.log
Normal 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
|
||||
|
5
src/test/ref/union-10.sym
Normal file
5
src/test/ref/union-10.sym
Normal 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
21
src/test/ref/union-11.asm
Normal 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
|
8
src/test/ref/union-11.cfg
Normal file
8
src/test/ref/union-11.cfg
Normal 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
168
src/test/ref/union-11.log
Normal 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
|
||||
|
5
src/test/ref/union-11.sym
Normal file
5
src/test/ref/union-11.sym
Normal 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
21
src/test/ref/union-12.asm
Normal 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
|
8
src/test/ref/union-12.cfg
Normal file
8
src/test/ref/union-12.cfg
Normal 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
170
src/test/ref/union-12.log
Normal 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
|
||||
|
6
src/test/ref/union-12.sym
Normal file
6
src/test/ref/union-12.sym
Normal 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
22
src/test/ref/union-13.asm
Normal 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
|
8
src/test/ref/union-13.cfg
Normal file
8
src/test/ref/union-13.cfg
Normal 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
176
src/test/ref/union-13.log
Normal 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
|
||||
|
5
src/test/ref/union-13.sym
Normal file
5
src/test/ref/union-13.sym
Normal 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
20
src/test/ref/union-9.asm
Normal 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
8
src/test/ref/union-9.cfg
Normal 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
159
src/test/ref/union-9.log
Normal 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
5
src/test/ref/union-9.sym
Normal file
@ -0,0 +1,5 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
__loadstore union Data data = { w: $4d2 } // mem[2]
|
||||
void main()
|
||||
|
||||
mem[2] [ data ]
|
Loading…
Reference in New Issue
Block a user