mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-14 09:30:57 +00:00
Merge branch 'add-union-initializer-c99-syntax' into 'master'
Implemented C99 compatible union initializer method, using .member= syntax... See merge request camelot/kickc!40
This commit is contained in:
commit
f864f61be2
@ -243,9 +243,10 @@ expr
|
|||||||
| expr ( '&&' ) expr #exprBinary
|
| expr ( '&&' ) expr #exprBinary
|
||||||
| expr ( '||' ) expr #exprBinary
|
| expr ( '||' ) expr #exprBinary
|
||||||
| expr '?' expr COLON expr #exprTernary
|
| expr '?' expr COLON expr #exprTernary
|
||||||
| <assoc=right> expr '=' expr #exprAssignment
|
| <assoc=right> expr ASSIGN expr #exprAssignment
|
||||||
| <assoc=right> expr ASSIGN_COMPOUND expr #exprAssignmentCompound
|
| <assoc=right> expr ASSIGN_COMPOUND expr #exprAssignmentCompound
|
||||||
| CURLY_BEGIN expr (COMMA expr )* COMMA? CURLY_END #initList
|
| CURLY_BEGIN expr (COMMA expr )* COMMA? CURLY_END #initList
|
||||||
|
| CURLY_BEGIN DOT NAME ASSIGN expr CURLY_END #initUnion
|
||||||
| NAME #exprId
|
| NAME #exprId
|
||||||
| NUMBER #exprNumber
|
| NUMBER #exprNumber
|
||||||
| STRING+ #exprString
|
| STRING+ #exprString
|
||||||
|
@ -89,6 +89,8 @@ public class Initializers {
|
|||||||
return new ConstantCastValue(toType, (ConstantValue) constantSub);
|
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) {
|
} else if(initValue instanceof ValueList) {
|
||||||
ValueList initList = (ValueList) initValue;
|
ValueList initList = (ValueList) initValue;
|
||||||
if(typeSpec.getType() instanceof SymbolTypePointer && ((SymbolTypePointer) typeSpec.getType()).getArraySpec() != null) {
|
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);
|
initValue = constantifyArray(initList, (SymbolTypePointer) typeSpec.getType(), program, source);
|
||||||
} else if(typeSpec.getType() instanceof SymbolTypeStruct) {
|
} else if(typeSpec.getType() instanceof SymbolTypeStruct) {
|
||||||
// Type is a struct
|
// Type is a struct
|
||||||
initValue = constantifyStruct(initList, (SymbolTypeStruct) typeSpec.getType(), program, source);
|
initValue = constantifyStructOrUnion(initList, (SymbolTypeStruct) typeSpec.getType(), program, source);
|
||||||
} else {
|
} else {
|
||||||
throw new CompileError("Value list cannot initialize type " + typeSpec.getType(), source);
|
throw new CompileError("Value list cannot initialize type " + typeSpec.getType(), source);
|
||||||
}
|
}
|
||||||
@ -127,6 +129,41 @@ public class Initializers {
|
|||||||
return initValue;
|
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.
|
* Convert as much as possible of a struct to constants.
|
||||||
*
|
*
|
||||||
@ -136,7 +173,7 @@ public class Initializers {
|
|||||||
* @param source The source line
|
* @param source The source line
|
||||||
* @return The constantified value
|
* @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
|
// Recursively cast all sub-elements
|
||||||
StructDefinition structDefinition = structType.getStructDefinition(program.getScope());
|
StructDefinition structDefinition = structType.getStructDefinition(program.getScope());
|
||||||
Collection<Variable> memberDefinitions = structDefinition.getAllVars(false);
|
Collection<Variable> memberDefinitions = structDefinition.getAllVars(false);
|
||||||
@ -144,7 +181,7 @@ public class Initializers {
|
|||||||
if(structInitNeedSize != valueList.getList().size()) {
|
if(structInitNeedSize != valueList.getList().size()) {
|
||||||
if(structDefinition.isUnion()) {
|
if(structDefinition.isUnion()) {
|
||||||
throw new CompileError(
|
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),
|
" Union initializer: " + valueList.toString(program),
|
||||||
source);
|
source);
|
||||||
} else {
|
} 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;
|
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
|
@Override
|
||||||
public RValue visitInitList(KickCParser.InitListContext ctx) {
|
public RValue visitInitList(KickCParser.InitListContext ctx) {
|
||||||
List<RValue> initValues = new ArrayList<>();
|
List<RValue> initValues = new ArrayList<>();
|
||||||
for(KickCParser.ExprContext initializer : ctx.expr()) {
|
for(KickCParser.ExprContext initializer : ctx.expr()) {
|
||||||
RValue rValue = (RValue) visit(initializer);
|
RValue rValue = (RValue) visit(initializer);
|
||||||
initValues.add(rValue);
|
initValues.add(rValue);
|
||||||
}
|
}
|
||||||
return new ValueList(initValues);
|
return new ValueList(initValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2541,6 +2541,31 @@ public class TestProgramsFast extends TestPrograms {
|
|||||||
compileAndCompare("weeip-bbslist.c");
|
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
|
@Test
|
||||||
public void testUnion8() throws IOException {
|
public void testUnion8() throws IOException {
|
||||||
compileAndCompare("union-8.c");
|
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…
x
Reference in New Issue
Block a user