mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-26 12:49:21 +00:00
Merge branch 'master' into 814-upgrade-java
This commit is contained in:
commit
7b1b3d3708
@ -0,0 +1,3 @@
|
|||||||
|
lda ({z1}),y
|
||||||
|
cmp ({z2}),y
|
||||||
|
bcc {la1}
|
@ -62,9 +62,7 @@ public class Pass1CallVar extends Pass2SsaOptimization {
|
|||||||
final LValue lValue = call.getlValue();
|
final LValue lValue = call.getlValue();
|
||||||
if(lValue!=null) {
|
if(lValue!=null) {
|
||||||
Variable returnVar = procedure.getLocalVariable("return");
|
Variable returnVar = procedure.getLocalVariable("return");
|
||||||
stmtIt.previous();
|
|
||||||
generateCallFinalize(lValue, returnVar, source, comments, stmtIt, statement);
|
generateCallFinalize(lValue, returnVar, source, comments, stmtIt, statement);
|
||||||
stmtIt.next();
|
|
||||||
}
|
}
|
||||||
stmtIt.remove();
|
stmtIt.remove();
|
||||||
}
|
}
|
||||||
@ -105,7 +103,9 @@ public class Pass1CallVar extends Pass2SsaOptimization {
|
|||||||
if(!(lValue instanceof ValueList) || !(returnType instanceof SymbolTypeStruct)) {
|
if(!(lValue instanceof ValueList) || !(returnType instanceof SymbolTypeStruct)) {
|
||||||
// A simple value - add simple assignment
|
// A simple value - add simple assignment
|
||||||
final StatementAssignment stackPull = new StatementAssignment(lValue, returnVar.getRef(), false, source, comments);
|
final StatementAssignment stackPull = new StatementAssignment(lValue, returnVar.getRef(), false, source, comments);
|
||||||
|
stmtIt.previous();
|
||||||
stmtIt.add(stackPull);
|
stmtIt.add(stackPull);
|
||||||
|
stmtIt.next();
|
||||||
getLog().append("Calling convention " + Procedure.CallingConvention.VAR_CALL + " adding return value assignment " + stackPull);
|
getLog().append("Calling convention " + Procedure.CallingConvention.VAR_CALL + " adding return value assignment " + stackPull);
|
||||||
} else {
|
} else {
|
||||||
final CastValue structLValue = new CastValue(returnType, lValue);
|
final CastValue structLValue = new CastValue(returnType, lValue);
|
||||||
@ -113,21 +113,6 @@ public class Pass1CallVar extends Pass2SsaOptimization {
|
|||||||
final ValueSource lValueSource = ValueSourceFactory.getValueSource(structLValue, getProgram(), getScope(), currentStmt, stmtIt, null);
|
final ValueSource lValueSource = ValueSourceFactory.getValueSource(structLValue, getProgram(), getScope(), currentStmt, stmtIt, null);
|
||||||
final ValueSource rValueSource = ValueSourceFactory.getValueSource(returnVar.getRef(), getProgram(), getScope(), currentStmt, stmtIt, null);
|
final ValueSource rValueSource = ValueSourceFactory.getValueSource(returnVar.getRef(), getProgram(), getScope(), currentStmt, stmtIt, null);
|
||||||
Pass1UnwindStructValues.copyValues(lValueSource, rValueSource, null, false, currentStmt, null, stmtIt, getProgram());
|
Pass1UnwindStructValues.copyValues(lValueSource, rValueSource, null, false, currentStmt, null, stmtIt, getProgram());
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
final List<RValue> memberLValues = ((ValueList) lValue).getList();
|
|
||||||
final StructVariableMemberUnwinding structVariableMemberUnwinding = getProgram().getStructVariableMemberUnwinding();
|
|
||||||
final StructVariableMemberUnwinding.VariableUnwinding returnVarUnwinding = structVariableMemberUnwinding.getVariableUnwinding(returnVar.getRef());
|
|
||||||
for(RValue memberLValue : memberLValues) {
|
|
||||||
|
|
||||||
}
|
|
||||||
for(int i = 0; i < structMemberVars.size(); i++) {
|
|
||||||
final Variable memberVar = structMemberVars.get(i);
|
|
||||||
final RValue memberValue = memberLValues.get(i);
|
|
||||||
generateCallFinalize(memberValue, memberVar.getType(), source, comments, stmtIt);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,7 @@ package dk.camelot64.kickc.passes;
|
|||||||
import dk.camelot64.kickc.model.Program;
|
import dk.camelot64.kickc.model.Program;
|
||||||
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
import dk.camelot64.kickc.model.iterator.ProgramValue;
|
||||||
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
|
||||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
import dk.camelot64.kickc.model.symbols.*;
|
||||||
import dk.camelot64.kickc.model.symbols.Symbol;
|
|
||||||
import dk.camelot64.kickc.model.symbols.Variable;
|
|
||||||
import dk.camelot64.kickc.model.values.*;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
import dk.camelot64.kickc.passes.utils.AliasReplacer;
|
import dk.camelot64.kickc.passes.utils.AliasReplacer;
|
||||||
|
|
||||||
@ -55,10 +53,14 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
|
|||||||
replaceInValues(inline);
|
replaceInValues(inline);
|
||||||
// Replace all usages of the constants in the control flow graph or symbol table
|
// Replace all usages of the constants in the control flow graph or symbol table
|
||||||
replaceVariables(inline);
|
replaceVariables(inline);
|
||||||
|
// Remove parameters
|
||||||
|
final Set<ConstantRef> inlineRefs = inline.keySet();
|
||||||
|
removeParameters(inlineRefs);
|
||||||
// Remove from symbol table
|
// Remove from symbol table
|
||||||
deleteSymbols(getScope(), inline.keySet());
|
deleteSymbols(getScope(), inlineRefs);
|
||||||
|
|
||||||
for(ConstantRef constantRef : inline.keySet()) {
|
|
||||||
|
for(ConstantRef constantRef : inlineRefs) {
|
||||||
getLog().append("Constant inlined " + constantRef.toString() + " = " + inline.get(constantRef).toString(getProgram()));
|
getLog().append("Constant inlined " + constantRef.toString() + " = " + inline.get(constantRef).toString(getProgram()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +68,30 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeParameters(Set<ConstantRef> inlineRefs) {
|
||||||
|
for(ConstantRef inlineRef : inlineRefs) {
|
||||||
|
final Scope scope = getScope().getConstant(inlineRef).getScope();
|
||||||
|
final Procedure procedure = getProcedure(scope);
|
||||||
|
if(procedure!=null) {
|
||||||
|
final List<Variable> parameters = procedure.getParameters();
|
||||||
|
final boolean modified = parameters.removeIf(param -> param.getRef().equals(inlineRef));
|
||||||
|
if(modified) {
|
||||||
|
procedure.setParameters(parameters);
|
||||||
|
getLog().append("Parameter inlined " + inlineRef.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Procedure getProcedure(Scope scope) {
|
||||||
|
if(scope instanceof Procedure)
|
||||||
|
return (Procedure) scope;
|
||||||
|
else if(scope instanceof ProgramScope)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return getProcedure(scope.getScope());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace any aliases within the constant values themselves
|
* Replace any aliases within the constant values themselves
|
||||||
*
|
*
|
||||||
|
@ -374,17 +374,33 @@ public class TestProgramsFast extends TestPrograms {
|
|||||||
public void testStructUnwinding2() throws IOException {
|
public void testStructUnwinding2() throws IOException {
|
||||||
compileAndCompare("struct-unwinding-2.c");
|
compileAndCompare("struct-unwinding-2.c");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStructUnwinding1() throws IOException {
|
public void testStructUnwinding1() throws IOException {
|
||||||
compileAndCompare("struct-unwinding-1.c");
|
compileAndCompare("struct-unwinding-1.c");
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test
|
@Test
|
||||||
//public void testVarCall5() throws IOException {
|
public void testVarCall9() throws IOException {
|
||||||
// compileAndCompare("varcall-5.c", log().verboseCreateSsa().verboseStructUnwind());
|
compileAndCompare("varcall-9.c");
|
||||||
//}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVarCall8() throws IOException {
|
||||||
|
compileAndCompare("varcall-8.c");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVarCall7() throws IOException {
|
||||||
|
compileAndCompare("varcall-7.c");
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testVarCall6() throws IOException {
|
||||||
|
compileAndCompare("varcall-6.c");
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testVarCall5() throws IOException {
|
||||||
|
compileAndCompare("varcall-5.c");
|
||||||
|
}
|
||||||
@Test
|
@Test
|
||||||
public void testVarCall4() throws IOException {
|
public void testVarCall4() throws IOException {
|
||||||
compileAndCompare("varcall-4.c");
|
compileAndCompare("varcall-4.c");
|
||||||
|
@ -6,10 +6,17 @@ struct Cols {
|
|||||||
char bg;
|
char bg;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Cols * const COLS = (struct Cols *)0xd020;
|
struct Cols * const COLS = (struct Cols * const)0xd020;
|
||||||
|
|
||||||
struct Cols a;
|
struct Cols a;
|
||||||
|
|
||||||
|
__varcall struct Cols make(char v) {
|
||||||
|
struct Cols c;
|
||||||
|
c.border = v;
|
||||||
|
c.bg = v+v;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
a = make(1);
|
a = make(1);
|
||||||
*COLS = a;
|
*COLS = a;
|
||||||
@ -17,6 +24,3 @@ void main() {
|
|||||||
*COLS = a;
|
*COLS = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
__varcall struct Cols make(char v) {
|
|
||||||
return { v, v+v };
|
|
||||||
}
|
|
||||||
|
@ -8,15 +8,15 @@ struct Cols {
|
|||||||
|
|
||||||
struct Cols * const COLS = (struct Cols *)0xd020;
|
struct Cols * const COLS = (struct Cols *)0xd020;
|
||||||
|
|
||||||
void main() {
|
|
||||||
struct Cols a = { 1, 2 };
|
|
||||||
//*COLS = a;
|
|
||||||
a = plus(a, { 2, 3 } );
|
|
||||||
*COLS = a;
|
|
||||||
//a = plus(a, a);
|
|
||||||
//*COLS = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
__varcall struct Cols plus(struct Cols a, struct Cols b) {
|
__varcall struct Cols plus(struct Cols a, struct Cols b) {
|
||||||
return { a.border+b.border, a.bg+b.bg };
|
return { a.border+b.border, a.bg+b.bg };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
struct Cols a = { 1, 2 };
|
||||||
|
struct Cols c = plus(a, { 2, 3 });
|
||||||
|
*COLS = c;
|
||||||
|
c = plus(c, a);
|
||||||
|
*COLS = c;
|
||||||
|
}
|
||||||
|
21
src/test/kc/varcall-7.c
Normal file
21
src/test/kc/varcall-7.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct parameter & return value - only a single call
|
||||||
|
|
||||||
|
struct Cols {
|
||||||
|
char border;
|
||||||
|
char bg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cols * const COLS = (struct Cols *)0xd020;
|
||||||
|
|
||||||
|
__varcall struct Cols plus(struct Cols a, struct Cols b) {
|
||||||
|
return { a.border+b.border, a.bg+b.bg };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
struct Cols a = { 1, 2 };
|
||||||
|
struct Cols b = { 2, 3 };
|
||||||
|
struct Cols c = plus(a, b);
|
||||||
|
*COLS = c;
|
||||||
|
}
|
28
src/test/kc/varcall-8.c
Normal file
28
src/test/kc/varcall-8.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Test __varcall calling convention
|
||||||
|
// Pointer to Struct parameter & return value
|
||||||
|
|
||||||
|
struct Cols {
|
||||||
|
char border;
|
||||||
|
char bg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cols * const COLS = (struct Cols *)0xd020;
|
||||||
|
|
||||||
|
__varcall struct Cols * min(struct Cols * a, struct Cols * b) {
|
||||||
|
if(a->bg < b->bg)
|
||||||
|
return a;
|
||||||
|
else
|
||||||
|
return b;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
struct Cols a = { 1, 7 };
|
||||||
|
struct Cols b = { 2, 6 };
|
||||||
|
struct Cols c = { 3, 5 };
|
||||||
|
struct Cols *m = min(&a,&b);
|
||||||
|
*COLS = *m;
|
||||||
|
m = min(m,&c);
|
||||||
|
*COLS = *m;
|
||||||
|
}
|
26
src/test/kc/varcall-9.c
Normal file
26
src/test/kc/varcall-9.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct of struct parameter value
|
||||||
|
|
||||||
|
struct Col {
|
||||||
|
char border;
|
||||||
|
char bg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cols {
|
||||||
|
struct Col normal;
|
||||||
|
struct Col error;
|
||||||
|
};
|
||||||
|
|
||||||
|
char * const COLS = (char*)0xd020;
|
||||||
|
|
||||||
|
__varcall char plus(struct Cols a, struct Cols b) {
|
||||||
|
return a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border + b.error.border + a.error.bg + b.error.bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
struct Cols a = { { 1, 2 }, { 3, 4 }};
|
||||||
|
struct Cols b = { { 5, 6 }, { 7, 8 }};
|
||||||
|
struct Cols c = { { 9, 10 }, { 11, 12 }};
|
||||||
|
*COLS = plus(a, b);
|
||||||
|
*COLS = plus(b, c);
|
||||||
|
}
|
69
src/test/ref/varcall-5.asm
Normal file
69
src/test/ref/varcall-5.asm
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct return value
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-5.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)
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.const SIZEOF_STRUCT_COLS = 2
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
main: {
|
||||||
|
// make(1)
|
||||||
|
lda #1
|
||||||
|
sta.z make.v
|
||||||
|
jsr make
|
||||||
|
ldx.z make.return_border
|
||||||
|
lda.z make.return_bg
|
||||||
|
// a = make(1)
|
||||||
|
stx a
|
||||||
|
sta a+OFFSET_STRUCT_COLS_BG
|
||||||
|
// *COLS = a
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda a-1,y
|
||||||
|
sta COLS-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// make(2)
|
||||||
|
lda #2
|
||||||
|
sta.z make.v
|
||||||
|
jsr make
|
||||||
|
ldx.z make.return_border
|
||||||
|
lda.z make.return_bg
|
||||||
|
// a = make(2)
|
||||||
|
stx a
|
||||||
|
sta a+OFFSET_STRUCT_COLS_BG
|
||||||
|
// *COLS = a
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda a-1,y
|
||||||
|
sta COLS-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// struct Cols make(__zp(2) char v)
|
||||||
|
make: {
|
||||||
|
.label v = 2
|
||||||
|
.label return_border = 3
|
||||||
|
.label return_bg = 4
|
||||||
|
// c.border = v
|
||||||
|
ldx.z v
|
||||||
|
// v+v
|
||||||
|
txa
|
||||||
|
asl
|
||||||
|
// c.bg = v+v
|
||||||
|
// return c;
|
||||||
|
stx.z return_border
|
||||||
|
sta.z return_bg
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
.segment Data
|
||||||
|
a: .fill SIZEOF_STRUCT_COLS, 0
|
33
src/test/ref/varcall-5.cfg
Normal file
33
src/test/ref/varcall-5.cfg
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] make::v = 1
|
||||||
|
[1] callexecute make
|
||||||
|
[2] main::$0_border = make::return_border
|
||||||
|
[3] main::$0_bg = make::return_bg
|
||||||
|
[4] *((char *)&a) = main::$0_border
|
||||||
|
[5] *((char *)&a+OFFSET_STRUCT_COLS_BG) = main::$0_bg
|
||||||
|
[6] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
[7] make::v = 2
|
||||||
|
[8] callexecute make
|
||||||
|
[9] main::$1_border = make::return_border
|
||||||
|
[10] main::$1_bg = make::return_bg
|
||||||
|
[11] *((char *)&a) = main::$1_border
|
||||||
|
[12] *((char *)&a+OFFSET_STRUCT_COLS_BG) = main::$1_bg
|
||||||
|
[13] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[14] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
__varcall struct Cols make(char v)
|
||||||
|
make: scope:[make] from
|
||||||
|
[15] make::c_border#1 = make::v
|
||||||
|
[16] make::$0 = make::v + make::v
|
||||||
|
[17] make::c_bg#1 = make::$0
|
||||||
|
[18] make::return_border = make::c_border#1
|
||||||
|
[19] make::return_bg = make::c_bg#1
|
||||||
|
to:make::@return
|
||||||
|
make::@return: scope:[make] from make
|
||||||
|
[20] return
|
||||||
|
to:@return
|
496
src/test/ref/varcall-5.log
Normal file
496
src/test/ref/varcall-5.log
Normal file
@ -0,0 +1,496 @@
|
|||||||
|
Converting parameter in __varcall procedure to load/store make::v
|
||||||
|
Converting return in __varcall procedure to load/store make::return
|
||||||
|
Eliminating unused variable with no statement main::$0
|
||||||
|
Eliminating unused variable with no statement main::$1
|
||||||
|
Calling convention __varcall adding prepare/execute/finalize for { main::$0_border, main::$0_bg } = call make(1)
|
||||||
|
Calling convention __varcall adding prepare/execute/finalize for { main::$1_border, main::$1_bg } = call make(2)
|
||||||
|
Removing C-classic struct-unwound assignment a = struct-unwound {*((char *)&a+OFFSET_STRUCT_COLS_BORDER), *((char *)&a+OFFSET_STRUCT_COLS_BG)}
|
||||||
|
Removing C-classic struct-unwound assignment a = struct-unwound {*((char *)&a+OFFSET_STRUCT_COLS_BORDER), *((char *)&a+OFFSET_STRUCT_COLS_BG)}
|
||||||
|
|
||||||
|
CONTROL FLOW GRAPH SSA
|
||||||
|
|
||||||
|
__varcall struct Cols make(char v)
|
||||||
|
make: scope:[make] from
|
||||||
|
make::c_border#0 = 0
|
||||||
|
make::c_bg#0 = 0
|
||||||
|
make::c_border#1 = make::v
|
||||||
|
make::$0 = make::v + make::v
|
||||||
|
make::c_bg#1 = make::$0
|
||||||
|
make::return_border = make::c_border#1
|
||||||
|
make::return_bg = make::c_bg#1
|
||||||
|
make::return = struct-unwound {make::return_border, make::return_bg}
|
||||||
|
to:make::@return
|
||||||
|
make::@return: scope:[make] from make
|
||||||
|
return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from __start
|
||||||
|
make::v = 1
|
||||||
|
callexecute make
|
||||||
|
main::$0_border = make::return_border
|
||||||
|
main::$0_bg = make::return_bg
|
||||||
|
*((char *)&a+OFFSET_STRUCT_COLS_BORDER) = main::$0_border
|
||||||
|
*((char *)&a+OFFSET_STRUCT_COLS_BG) = main::$0_bg
|
||||||
|
*COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
make::v = 2
|
||||||
|
callexecute make
|
||||||
|
main::$1_border = make::return_border
|
||||||
|
main::$1_bg = make::return_bg
|
||||||
|
*((char *)&a+OFFSET_STRUCT_COLS_BORDER) = main::$1_border
|
||||||
|
*((char *)&a+OFFSET_STRUCT_COLS_BG) = main::$1_bg
|
||||||
|
*COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
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 struct Cols * const COLS = (struct Cols * const )$d020
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BORDER = 0
|
||||||
|
__constant char SIZEOF_STRUCT_COLS = 2
|
||||||
|
void __start()
|
||||||
|
__loadstore struct Cols a = {}
|
||||||
|
void main()
|
||||||
|
char main::$0_bg
|
||||||
|
char main::$0_border
|
||||||
|
char main::$1_bg
|
||||||
|
char main::$1_border
|
||||||
|
__varcall struct Cols make(char v)
|
||||||
|
char make::$0
|
||||||
|
char make::c_bg
|
||||||
|
char make::c_bg#0
|
||||||
|
char make::c_bg#1
|
||||||
|
char make::c_border
|
||||||
|
char make::c_border#0
|
||||||
|
char make::c_border#1
|
||||||
|
__loadstore struct Cols make::return
|
||||||
|
__loadstore char make::return_bg
|
||||||
|
__loadstore char make::return_border
|
||||||
|
__loadstore char make::v
|
||||||
|
|
||||||
|
Adding number conversion cast (unumber) 1 in make::v = 1
|
||||||
|
Adding number conversion cast (unumber) 2 in make::v = 2
|
||||||
|
Successful SSA optimization PassNAddNumberTypeConversions
|
||||||
|
Inlining cast make::v = (unumber)1
|
||||||
|
Inlining cast make::v = (unumber)2
|
||||||
|
Successful SSA optimization Pass2InlineCast
|
||||||
|
Simplifying constant pointer cast (struct Cols *) 53280
|
||||||
|
Simplifying constant integer cast 1
|
||||||
|
Simplifying constant integer cast 2
|
||||||
|
Successful SSA optimization PassNCastSimplification
|
||||||
|
Finalized unsigned number type (char) 1
|
||||||
|
Finalized unsigned number type (char) 2
|
||||||
|
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||||
|
Alias candidate removed (volatile)make::c_bg#1 = make::$0 make::return_bg
|
||||||
|
Alias candidate removed (volatile)make::c_border#1 = make::return_border
|
||||||
|
Constant make::c_border#0 = 0
|
||||||
|
Constant make::c_bg#0 = 0
|
||||||
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
|
Simplifying expression containing zero (char *)&a in [13] *((char *)&a+OFFSET_STRUCT_COLS_BORDER) = main::$0_border
|
||||||
|
Simplifying expression containing zero (char *)&a in [20] *((char *)&a+OFFSET_STRUCT_COLS_BORDER) = main::$1_border
|
||||||
|
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||||
|
Eliminating unused variable make::return and assignment [5] make::return = struct-unwound {make::return_border, make::return_bg}
|
||||||
|
Eliminating unused constant make::c_border#0
|
||||||
|
Eliminating unused constant make::c_bg#0
|
||||||
|
Eliminating unused constant OFFSET_STRUCT_COLS_BORDER
|
||||||
|
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
|
||||||
|
Alias candidate removed (volatile)make::c_bg#1 = make::$0 make::return_bg
|
||||||
|
Alias candidate removed (volatile)make::c_border#1 = make::return_border
|
||||||
|
Alias candidate removed (volatile)make::c_bg#1 = make::$0 make::return_bg
|
||||||
|
Alias candidate removed (volatile)make::c_border#1 = make::return_border
|
||||||
|
Alias candidate removed (volatile)make::c_bg#1 = make::$0 make::return_bg
|
||||||
|
Alias candidate removed (volatile)make::c_border#1 = make::return_border
|
||||||
|
CALL GRAPH
|
||||||
|
Calls in [main] to make:1 make:8
|
||||||
|
|
||||||
|
Created 0 initial phi equivalence classes
|
||||||
|
Coalesced down to 0 phi equivalence classes
|
||||||
|
|
||||||
|
FINAL CONTROL FLOW GRAPH
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] make::v = 1
|
||||||
|
[1] callexecute make
|
||||||
|
[2] main::$0_border = make::return_border
|
||||||
|
[3] main::$0_bg = make::return_bg
|
||||||
|
[4] *((char *)&a) = main::$0_border
|
||||||
|
[5] *((char *)&a+OFFSET_STRUCT_COLS_BG) = main::$0_bg
|
||||||
|
[6] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
[7] make::v = 2
|
||||||
|
[8] callexecute make
|
||||||
|
[9] main::$1_border = make::return_border
|
||||||
|
[10] main::$1_bg = make::return_bg
|
||||||
|
[11] *((char *)&a) = main::$1_border
|
||||||
|
[12] *((char *)&a+OFFSET_STRUCT_COLS_BG) = main::$1_bg
|
||||||
|
[13] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[14] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
__varcall struct Cols make(char v)
|
||||||
|
make: scope:[make] from
|
||||||
|
[15] make::c_border#1 = make::v
|
||||||
|
[16] make::$0 = make::v + make::v
|
||||||
|
[17] make::c_bg#1 = make::$0
|
||||||
|
[18] make::return_border = make::c_border#1
|
||||||
|
[19] make::return_bg = make::c_bg#1
|
||||||
|
to:make::@return
|
||||||
|
make::@return: scope:[make] from make
|
||||||
|
[20] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
|
||||||
|
VARIABLE REGISTER WEIGHTS
|
||||||
|
__loadstore struct Cols a = {}
|
||||||
|
void main()
|
||||||
|
char main::$0_bg // 2.0
|
||||||
|
char main::$0_border // 2.0
|
||||||
|
char main::$1_bg // 2.0
|
||||||
|
char main::$1_border // 2.0
|
||||||
|
__varcall struct Cols make(char v)
|
||||||
|
char make::$0 // 22.0
|
||||||
|
char make::c_bg
|
||||||
|
char make::c_bg#1 // 11.0
|
||||||
|
char make::c_border
|
||||||
|
char make::c_border#1 // 7.333333333333333
|
||||||
|
__loadstore char make::return_bg // 2.5
|
||||||
|
__loadstore char make::return_border // 3.0
|
||||||
|
__loadstore char make::v // 12.333333333333332
|
||||||
|
|
||||||
|
Initial phi equivalence classes
|
||||||
|
Added variable make::v to live range equivalence class [ make::v ]
|
||||||
|
Added variable main::$0_border to live range equivalence class [ main::$0_border ]
|
||||||
|
Added variable main::$0_bg to live range equivalence class [ main::$0_bg ]
|
||||||
|
Added variable main::$1_border to live range equivalence class [ main::$1_border ]
|
||||||
|
Added variable main::$1_bg to live range equivalence class [ main::$1_bg ]
|
||||||
|
Added variable make::c_border#1 to live range equivalence class [ make::c_border#1 ]
|
||||||
|
Added variable make::$0 to live range equivalence class [ make::$0 ]
|
||||||
|
Added variable make::c_bg#1 to live range equivalence class [ make::c_bg#1 ]
|
||||||
|
Added variable make::return_border to live range equivalence class [ make::return_border ]
|
||||||
|
Added variable make::return_bg to live range equivalence class [ make::return_bg ]
|
||||||
|
Added variable a to live range equivalence class [ a ]
|
||||||
|
Complete equivalence classes
|
||||||
|
[ make::v ]
|
||||||
|
[ main::$0_border ]
|
||||||
|
[ main::$0_bg ]
|
||||||
|
[ main::$1_border ]
|
||||||
|
[ main::$1_bg ]
|
||||||
|
[ make::c_border#1 ]
|
||||||
|
[ make::$0 ]
|
||||||
|
[ make::c_bg#1 ]
|
||||||
|
[ make::return_border ]
|
||||||
|
[ make::return_bg ]
|
||||||
|
[ a ]
|
||||||
|
Allocated zp[1]:2 [ make::$0 ]
|
||||||
|
Allocated zp[1]:3 [ make::v ]
|
||||||
|
Allocated zp[1]:4 [ make::c_bg#1 ]
|
||||||
|
Allocated zp[1]:5 [ make::c_border#1 ]
|
||||||
|
Allocated zp[1]:6 [ make::return_border ]
|
||||||
|
Allocated zp[1]:7 [ make::return_bg ]
|
||||||
|
Allocated zp[1]:8 [ main::$0_border ]
|
||||||
|
Allocated zp[1]:9 [ main::$0_bg ]
|
||||||
|
Allocated zp[1]:10 [ main::$1_border ]
|
||||||
|
Allocated zp[1]:11 [ main::$1_bg ]
|
||||||
|
Allocated mem[2] [ a ]
|
||||||
|
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||||
|
Statement [0] make::v = 1 [ make::v a ] ( [ make::v a ] { } ) always clobbers reg byte a
|
||||||
|
Statement [6] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) [ a ] ( [ a ] { } ) always clobbers reg byte a reg byte y
|
||||||
|
Statement [7] make::v = 2 [ make::v a ] ( [ make::v a ] { } ) always clobbers reg byte a
|
||||||
|
Statement [13] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) [ ] ( [ ] { } ) always clobbers reg byte a reg byte y
|
||||||
|
Statement [16] make::$0 = make::v + make::v [ make::c_border#1 make::$0 ] ( make:1 [ a make::c_border#1 make::$0 ] { } make:8 [ a make::c_border#1 make::$0 ] { } ) always clobbers reg byte a
|
||||||
|
Removing always clobbered register reg byte a as potential for zp[1]:5 [ make::c_border#1 ]
|
||||||
|
Statement [0] make::v = 1 [ make::v a ] ( [ make::v a ] { } ) always clobbers reg byte a
|
||||||
|
Statement [6] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) [ a ] ( [ a ] { } ) always clobbers reg byte a reg byte y
|
||||||
|
Statement [7] make::v = 2 [ make::v a ] ( [ make::v a ] { } ) always clobbers reg byte a
|
||||||
|
Statement [13] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) [ ] ( [ ] { } ) always clobbers reg byte a reg byte y
|
||||||
|
Statement [16] make::$0 = make::v + make::v [ make::c_border#1 make::$0 ] ( make:1 [ a make::c_border#1 make::$0 ] { } make:8 [ a make::c_border#1 make::$0 ] { } ) always clobbers reg byte a
|
||||||
|
Potential registers zp[1]:3 [ make::v ] : zp[1]:3 ,
|
||||||
|
Potential registers zp[1]:8 [ main::$0_border ] : zp[1]:8 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:9 [ main::$0_bg ] : zp[1]:9 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:10 [ main::$1_border ] : zp[1]:10 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:11 [ main::$1_bg ] : zp[1]:11 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:5 [ make::c_border#1 ] : zp[1]:5 , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:2 [ make::$0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:4 [ make::c_bg#1 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:6 [ make::return_border ] : zp[1]:6 ,
|
||||||
|
Potential registers zp[1]:7 [ make::return_bg ] : zp[1]:7 ,
|
||||||
|
Potential registers mem[2] [ a ] : mem[2] ,
|
||||||
|
|
||||||
|
REGISTER UPLIFT SCOPES
|
||||||
|
Uplift Scope [make] 22: zp[1]:2 [ make::$0 ] 12.33: zp[1]:3 [ make::v ] 11: zp[1]:4 [ make::c_bg#1 ] 7.33: zp[1]:5 [ make::c_border#1 ] 3: zp[1]:6 [ make::return_border ] 2.5: zp[1]:7 [ make::return_bg ]
|
||||||
|
Uplift Scope [main] 2: zp[1]:8 [ main::$0_border ] 2: zp[1]:9 [ main::$0_bg ] 2: zp[1]:10 [ main::$1_border ] 2: zp[1]:11 [ main::$1_bg ]
|
||||||
|
Uplift Scope [Cols]
|
||||||
|
Uplift Scope [] 0: mem[2] [ a ]
|
||||||
|
|
||||||
|
Uplifting [make] best 138 combination reg byte a [ make::$0 ] zp[1]:3 [ make::v ] reg byte a [ make::c_bg#1 ] reg byte x [ make::c_border#1 ] zp[1]:6 [ make::return_border ] zp[1]:7 [ make::return_bg ]
|
||||||
|
Uplifting [main] best 120 combination reg byte x [ main::$0_border ] reg byte a [ main::$0_bg ] reg byte x [ main::$1_border ] zp[1]:11 [ main::$1_bg ]
|
||||||
|
Limited combination testing to 100 combinations of 256 possible.
|
||||||
|
Uplifting [Cols] best 120 combination
|
||||||
|
Uplifting [] best 120 combination mem[2] [ a ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:3 [ make::v ]
|
||||||
|
Uplifting [make] best 120 combination zp[1]:3 [ make::v ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:6 [ make::return_border ]
|
||||||
|
Uplifting [make] best 120 combination zp[1]:6 [ make::return_border ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:7 [ make::return_bg ]
|
||||||
|
Uplifting [make] best 120 combination zp[1]:7 [ make::return_bg ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:11 [ main::$1_bg ]
|
||||||
|
Uplifting [main] best 114 combination reg byte a [ main::$1_bg ]
|
||||||
|
Allocated (was zp[1]:3) zp[1]:2 [ make::v ]
|
||||||
|
Allocated (was zp[1]:6) zp[1]:3 [ make::return_border ]
|
||||||
|
Allocated (was zp[1]:7) zp[1]:4 [ make::return_bg ]
|
||||||
|
|
||||||
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
|
// File Comments
|
||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct return value
|
||||||
|
// Upstart
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-5.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
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.const SIZEOF_STRUCT_COLS = 2
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
// [0] make::v = 1 -- vbuz1=vbuc1
|
||||||
|
lda #1
|
||||||
|
sta.z make.v
|
||||||
|
// [1] callexecute make -- call_vprc1
|
||||||
|
jsr make
|
||||||
|
// [2] main::$0_border = make::return_border -- vbuxx=vbuz1
|
||||||
|
ldx.z make.return_border
|
||||||
|
// [3] main::$0_bg = make::return_bg -- vbuaa=vbuz1
|
||||||
|
lda.z make.return_bg
|
||||||
|
// [4] *((char *)&a) = main::$0_border -- _deref_pbuc1=vbuxx
|
||||||
|
stx a
|
||||||
|
// [5] *((char *)&a+OFFSET_STRUCT_COLS_BG) = main::$0_bg -- _deref_pbuc1=vbuaa
|
||||||
|
sta a+OFFSET_STRUCT_COLS_BG
|
||||||
|
// [6] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda a-1,y
|
||||||
|
sta COLS-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// [7] make::v = 2 -- vbuz1=vbuc1
|
||||||
|
lda #2
|
||||||
|
sta.z make.v
|
||||||
|
// [8] callexecute make -- call_vprc1
|
||||||
|
jsr make
|
||||||
|
// [9] main::$1_border = make::return_border -- vbuxx=vbuz1
|
||||||
|
ldx.z make.return_border
|
||||||
|
// [10] main::$1_bg = make::return_bg -- vbuaa=vbuz1
|
||||||
|
lda.z make.return_bg
|
||||||
|
// [11] *((char *)&a) = main::$1_border -- _deref_pbuc1=vbuxx
|
||||||
|
stx a
|
||||||
|
// [12] *((char *)&a+OFFSET_STRUCT_COLS_BG) = main::$1_bg -- _deref_pbuc1=vbuaa
|
||||||
|
sta a+OFFSET_STRUCT_COLS_BG
|
||||||
|
// [13] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda a-1,y
|
||||||
|
sta COLS-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
jmp __breturn
|
||||||
|
// main::@return
|
||||||
|
__breturn:
|
||||||
|
// [14] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// make
|
||||||
|
// struct Cols make(__zp(2) char v)
|
||||||
|
make: {
|
||||||
|
.label v = 2
|
||||||
|
.label return_border = 3
|
||||||
|
.label return_bg = 4
|
||||||
|
// [15] make::c_border#1 = make::v -- vbuxx=vbuz1
|
||||||
|
ldx.z v
|
||||||
|
// [16] make::$0 = make::v + make::v -- vbuaa=vbuz1_plus_vbuz1
|
||||||
|
lda.z v
|
||||||
|
asl
|
||||||
|
// [17] make::c_bg#1 = make::$0
|
||||||
|
// [18] make::return_border = make::c_border#1 -- vbuz1=vbuxx
|
||||||
|
stx.z return_border
|
||||||
|
// [19] make::return_bg = make::c_bg#1 -- vbuz1=vbuaa
|
||||||
|
sta.z return_bg
|
||||||
|
jmp __breturn
|
||||||
|
// make::@return
|
||||||
|
__breturn:
|
||||||
|
// [20] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
.segment Data
|
||||||
|
a: .fill SIZEOF_STRUCT_COLS, 0
|
||||||
|
|
||||||
|
ASSEMBLER OPTIMIZATIONS
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Succesful ASM optimization Pass5NextJumpElimination
|
||||||
|
Replacing instruction lda.z v with TXA
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||||
|
|
||||||
|
FINAL SYMBOL TABLE
|
||||||
|
__constant struct Cols * const COLS = (struct Cols *) 53280
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
__constant char SIZEOF_STRUCT_COLS = 2
|
||||||
|
__loadstore struct Cols a = {} // mem[2]
|
||||||
|
void main()
|
||||||
|
char main::$0_bg // reg byte a 2.0
|
||||||
|
char main::$0_border // reg byte x 2.0
|
||||||
|
char main::$1_bg // reg byte a 2.0
|
||||||
|
char main::$1_border // reg byte x 2.0
|
||||||
|
__varcall struct Cols make(char v)
|
||||||
|
char make::$0 // reg byte a 22.0
|
||||||
|
char make::c_bg
|
||||||
|
char make::c_bg#1 // reg byte a 11.0
|
||||||
|
char make::c_border
|
||||||
|
char make::c_border#1 // reg byte x 7.333333333333333
|
||||||
|
__loadstore char make::return_bg // zp[1]:4 2.5
|
||||||
|
__loadstore char make::return_border // zp[1]:3 3.0
|
||||||
|
__loadstore char make::v // zp[1]:2 12.333333333333332
|
||||||
|
|
||||||
|
zp[1]:2 [ make::v ]
|
||||||
|
reg byte x [ main::$0_border ]
|
||||||
|
reg byte a [ main::$0_bg ]
|
||||||
|
reg byte x [ main::$1_border ]
|
||||||
|
reg byte a [ main::$1_bg ]
|
||||||
|
reg byte x [ make::c_border#1 ]
|
||||||
|
reg byte a [ make::$0 ]
|
||||||
|
reg byte a [ make::c_bg#1 ]
|
||||||
|
zp[1]:3 [ make::return_border ]
|
||||||
|
zp[1]:4 [ make::return_bg ]
|
||||||
|
mem[2] [ a ]
|
||||||
|
|
||||||
|
|
||||||
|
FINAL ASSEMBLER
|
||||||
|
Score: 107
|
||||||
|
|
||||||
|
// File Comments
|
||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct return value
|
||||||
|
// Upstart
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-5.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
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.const SIZEOF_STRUCT_COLS = 2
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
// make(1)
|
||||||
|
// [0] make::v = 1 -- vbuz1=vbuc1
|
||||||
|
lda #1
|
||||||
|
sta.z make.v
|
||||||
|
// [1] callexecute make -- call_vprc1
|
||||||
|
jsr make
|
||||||
|
// [2] main::$0_border = make::return_border -- vbuxx=vbuz1
|
||||||
|
ldx.z make.return_border
|
||||||
|
// [3] main::$0_bg = make::return_bg -- vbuaa=vbuz1
|
||||||
|
lda.z make.return_bg
|
||||||
|
// a = make(1)
|
||||||
|
// [4] *((char *)&a) = main::$0_border -- _deref_pbuc1=vbuxx
|
||||||
|
stx a
|
||||||
|
// [5] *((char *)&a+OFFSET_STRUCT_COLS_BG) = main::$0_bg -- _deref_pbuc1=vbuaa
|
||||||
|
sta a+OFFSET_STRUCT_COLS_BG
|
||||||
|
// *COLS = a
|
||||||
|
// [6] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda a-1,y
|
||||||
|
sta COLS-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// make(2)
|
||||||
|
// [7] make::v = 2 -- vbuz1=vbuc1
|
||||||
|
lda #2
|
||||||
|
sta.z make.v
|
||||||
|
// [8] callexecute make -- call_vprc1
|
||||||
|
jsr make
|
||||||
|
// [9] main::$1_border = make::return_border -- vbuxx=vbuz1
|
||||||
|
ldx.z make.return_border
|
||||||
|
// [10] main::$1_bg = make::return_bg -- vbuaa=vbuz1
|
||||||
|
lda.z make.return_bg
|
||||||
|
// a = make(2)
|
||||||
|
// [11] *((char *)&a) = main::$1_border -- _deref_pbuc1=vbuxx
|
||||||
|
stx a
|
||||||
|
// [12] *((char *)&a+OFFSET_STRUCT_COLS_BG) = main::$1_bg -- _deref_pbuc1=vbuaa
|
||||||
|
sta a+OFFSET_STRUCT_COLS_BG
|
||||||
|
// *COLS = a
|
||||||
|
// [13] *COLS = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda a-1,y
|
||||||
|
sta COLS-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// main::@return
|
||||||
|
// }
|
||||||
|
// [14] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// make
|
||||||
|
// struct Cols make(__zp(2) char v)
|
||||||
|
make: {
|
||||||
|
.label v = 2
|
||||||
|
.label return_border = 3
|
||||||
|
.label return_bg = 4
|
||||||
|
// c.border = v
|
||||||
|
// [15] make::c_border#1 = make::v -- vbuxx=vbuz1
|
||||||
|
ldx.z v
|
||||||
|
// v+v
|
||||||
|
// [16] make::$0 = make::v + make::v -- vbuaa=vbuz1_plus_vbuz1
|
||||||
|
txa
|
||||||
|
asl
|
||||||
|
// c.bg = v+v
|
||||||
|
// [17] make::c_bg#1 = make::$0
|
||||||
|
// return c;
|
||||||
|
// [18] make::return_border = make::c_border#1 -- vbuz1=vbuxx
|
||||||
|
stx.z return_border
|
||||||
|
// [19] make::return_bg = make::c_bg#1 -- vbuz1=vbuaa
|
||||||
|
sta.z return_bg
|
||||||
|
// make::@return
|
||||||
|
// }
|
||||||
|
// [20] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
.segment Data
|
||||||
|
a: .fill SIZEOF_STRUCT_COLS, 0
|
||||||
|
|
30
src/test/ref/varcall-5.sym
Normal file
30
src/test/ref/varcall-5.sym
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
__constant struct Cols * const COLS = (struct Cols *) 53280
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
__constant char SIZEOF_STRUCT_COLS = 2
|
||||||
|
__loadstore struct Cols a = {} // mem[2]
|
||||||
|
void main()
|
||||||
|
char main::$0_bg // reg byte a 2.0
|
||||||
|
char main::$0_border // reg byte x 2.0
|
||||||
|
char main::$1_bg // reg byte a 2.0
|
||||||
|
char main::$1_border // reg byte x 2.0
|
||||||
|
__varcall struct Cols make(char v)
|
||||||
|
char make::$0 // reg byte a 22.0
|
||||||
|
char make::c_bg
|
||||||
|
char make::c_bg#1 // reg byte a 11.0
|
||||||
|
char make::c_border
|
||||||
|
char make::c_border#1 // reg byte x 7.333333333333333
|
||||||
|
__loadstore char make::return_bg // zp[1]:4 2.5
|
||||||
|
__loadstore char make::return_border // zp[1]:3 3.0
|
||||||
|
__loadstore char make::v // zp[1]:2 12.333333333333332
|
||||||
|
|
||||||
|
zp[1]:2 [ make::v ]
|
||||||
|
reg byte x [ main::$0_border ]
|
||||||
|
reg byte a [ main::$0_bg ]
|
||||||
|
reg byte x [ main::$1_border ]
|
||||||
|
reg byte a [ main::$1_bg ]
|
||||||
|
reg byte x [ make::c_border#1 ]
|
||||||
|
reg byte a [ make::$0 ]
|
||||||
|
reg byte a [ make::c_bg#1 ]
|
||||||
|
zp[1]:3 [ make::return_border ]
|
||||||
|
zp[1]:4 [ make::return_bg ]
|
||||||
|
mem[2] [ a ]
|
71
src/test/ref/varcall-6.asm
Normal file
71
src/test/ref/varcall-6.asm
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct parameter & return value
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-6.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)
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
main: {
|
||||||
|
.const a_border = 1
|
||||||
|
.const a_bg = 2
|
||||||
|
// struct Cols c = plus(a, { 2, 3 })
|
||||||
|
lda #a_border
|
||||||
|
sta.z plus.a_border
|
||||||
|
lda #a_bg
|
||||||
|
sta.z plus.a_bg
|
||||||
|
lda #2
|
||||||
|
sta.z plus.b_border
|
||||||
|
lda #3
|
||||||
|
sta.z plus.b_bg
|
||||||
|
jsr plus
|
||||||
|
ldx.z plus.return_border
|
||||||
|
lda.z plus.return_bg
|
||||||
|
// *COLS = c
|
||||||
|
stx COLS
|
||||||
|
sta COLS+OFFSET_STRUCT_COLS_BG
|
||||||
|
// plus(c, a)
|
||||||
|
stx.z plus.a_border
|
||||||
|
sta.z plus.a_bg
|
||||||
|
lda #a_border
|
||||||
|
sta.z plus.b_border
|
||||||
|
lda #a_bg
|
||||||
|
sta.z plus.b_bg
|
||||||
|
jsr plus
|
||||||
|
// c = plus(c, a)
|
||||||
|
ldx.z plus.return_border
|
||||||
|
lda.z plus.return_bg
|
||||||
|
// *COLS = c
|
||||||
|
stx COLS
|
||||||
|
sta COLS+OFFSET_STRUCT_COLS_BG
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// struct Cols plus(__zp(7) char a_border, __zp(6) char a_bg, __zp(3) char b_border, __zp(2) char b_bg)
|
||||||
|
plus: {
|
||||||
|
.label a_border = 7
|
||||||
|
.label a_bg = 6
|
||||||
|
.label b_border = 3
|
||||||
|
.label b_bg = 2
|
||||||
|
.label return_border = 4
|
||||||
|
.label return_bg = 5
|
||||||
|
// a.border+b.border
|
||||||
|
lda.z a_border
|
||||||
|
clc
|
||||||
|
adc.z b_border
|
||||||
|
tax
|
||||||
|
// a.bg+b.bg
|
||||||
|
lda.z a_bg
|
||||||
|
clc
|
||||||
|
adc.z b_bg
|
||||||
|
// return { a.border+b.border, a.bg+b.bg };
|
||||||
|
stx.z return_border
|
||||||
|
sta.z return_bg
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
36
src/test/ref/varcall-6.cfg
Normal file
36
src/test/ref/varcall-6.cfg
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] plus::a_border = main::a_border
|
||||||
|
[1] plus::a_bg = main::a_bg
|
||||||
|
[2] plus::b_border = 2
|
||||||
|
[3] plus::b_bg = 3
|
||||||
|
[4] callexecute plus
|
||||||
|
[5] main::c_border#0 = plus::return_border
|
||||||
|
[6] main::c_bg#0 = plus::return_bg
|
||||||
|
[7] *((char *)COLS) = main::c_border#0
|
||||||
|
[8] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#0
|
||||||
|
[9] plus::a_border = main::c_border#0
|
||||||
|
[10] plus::a_bg = main::c_bg#0
|
||||||
|
[11] plus::b_border = main::a_border
|
||||||
|
[12] plus::b_bg = main::a_bg
|
||||||
|
[13] callexecute plus
|
||||||
|
[14] main::c_border#1 = plus::return_border
|
||||||
|
[15] main::c_bg#1 = plus::return_bg
|
||||||
|
[16] *((char *)COLS) = main::c_border#1
|
||||||
|
[17] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#1
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[18] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
__varcall struct Cols plus(char a_border , char a_bg , char b_border , char b_bg)
|
||||||
|
plus: scope:[plus] from
|
||||||
|
[19] plus::$0 = plus::a_border + plus::b_border
|
||||||
|
[20] plus::$1 = plus::a_bg + plus::b_bg
|
||||||
|
[21] plus::return_border = plus::$0
|
||||||
|
[22] plus::return_bg = plus::$1
|
||||||
|
to:plus::@return
|
||||||
|
plus::@return: scope:[plus] from plus
|
||||||
|
[23] return
|
||||||
|
to:@return
|
541
src/test/ref/varcall-6.log
Normal file
541
src/test/ref/varcall-6.log
Normal file
@ -0,0 +1,541 @@
|
|||||||
|
Converting parameter in __varcall procedure to load/store plus::a
|
||||||
|
Converting parameter in __varcall procedure to load/store plus::b
|
||||||
|
Converting return in __varcall procedure to load/store plus::return
|
||||||
|
Constantified RValue plus::return = (struct Cols){ plus::$0, plus::$1 }
|
||||||
|
Added struct type cast to parameter value list main::c = call plus(main::a, (struct Cols){ 2, 3 })
|
||||||
|
Eliminating unused variable with no statement plus::a
|
||||||
|
Eliminating unused variable with no statement plus::b
|
||||||
|
Eliminating unused variable with no statement main::$0
|
||||||
|
Eliminating unused variable with no statement main::$1
|
||||||
|
Calling convention __varcall adding prepare/execute/finalize for { main::c_border, main::c_bg } = call plus(main::a_border, main::a_bg, 2, 3)
|
||||||
|
Calling convention __varcall adding prepare/execute/finalize for { main::$1_border, main::$1_bg } = call plus(main::c_border, main::c_bg, main::a_border, main::a_bg)
|
||||||
|
|
||||||
|
CONTROL FLOW GRAPH SSA
|
||||||
|
|
||||||
|
__varcall struct Cols plus(char a_border , char a_bg , char b_border , char b_bg)
|
||||||
|
plus: scope:[plus] from
|
||||||
|
plus::$0 = plus::a_border + plus::b_border
|
||||||
|
plus::$1 = plus::a_bg + plus::b_bg
|
||||||
|
plus::return_border = plus::$0
|
||||||
|
plus::return_bg = plus::$1
|
||||||
|
plus::return = struct-unwound {plus::return_border, plus::return_bg}
|
||||||
|
to:plus::@return
|
||||||
|
plus::@return: scope:[plus] from plus
|
||||||
|
return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from __start
|
||||||
|
plus::a_border = main::a_border
|
||||||
|
plus::a_bg = main::a_bg
|
||||||
|
plus::b_border = 2
|
||||||
|
plus::b_bg = 3
|
||||||
|
callexecute plus
|
||||||
|
main::c_border#0 = plus::return_border
|
||||||
|
main::c_bg#0 = plus::return_bg
|
||||||
|
*((char *)COLS+OFFSET_STRUCT_COLS_BORDER) = main::c_border#0
|
||||||
|
*((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#0
|
||||||
|
plus::a_border = main::c_border#0
|
||||||
|
plus::a_bg = main::c_bg#0
|
||||||
|
plus::b_border = main::a_border
|
||||||
|
plus::b_bg = main::a_bg
|
||||||
|
callexecute plus
|
||||||
|
main::$1_border = plus::return_border
|
||||||
|
main::$1_bg = plus::return_bg
|
||||||
|
main::c_border#1 = main::$1_border
|
||||||
|
main::c_bg#1 = main::$1_bg
|
||||||
|
*((char *)COLS+OFFSET_STRUCT_COLS_BORDER) = main::c_border#1
|
||||||
|
*((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#1
|
||||||
|
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 struct Cols * const COLS = (struct Cols *)$d020
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BORDER = 0
|
||||||
|
void __start()
|
||||||
|
void main()
|
||||||
|
char main::$1_bg
|
||||||
|
char main::$1_border
|
||||||
|
__constant char main::a_bg = 2
|
||||||
|
__constant char main::a_border = 1
|
||||||
|
char main::c_bg
|
||||||
|
char main::c_bg#0
|
||||||
|
char main::c_bg#1
|
||||||
|
char main::c_border
|
||||||
|
char main::c_border#0
|
||||||
|
char main::c_border#1
|
||||||
|
__varcall struct Cols plus(char a_border , char a_bg , char b_border , char b_bg)
|
||||||
|
char plus::$0
|
||||||
|
char plus::$1
|
||||||
|
__loadstore char plus::a_bg
|
||||||
|
__loadstore char plus::a_border
|
||||||
|
__loadstore char plus::b_bg
|
||||||
|
__loadstore char plus::b_border
|
||||||
|
__loadstore struct Cols plus::return
|
||||||
|
__loadstore char plus::return_bg
|
||||||
|
__loadstore char plus::return_border
|
||||||
|
|
||||||
|
Adding number conversion cast (unumber) 2 in plus::b_border = 2
|
||||||
|
Adding number conversion cast (unumber) 3 in plus::b_bg = 3
|
||||||
|
Successful SSA optimization PassNAddNumberTypeConversions
|
||||||
|
Inlining cast plus::b_border = (unumber)2
|
||||||
|
Inlining cast plus::b_bg = (unumber)3
|
||||||
|
Successful SSA optimization Pass2InlineCast
|
||||||
|
Simplifying constant pointer cast (struct Cols *) 53280
|
||||||
|
Simplifying constant integer cast 2
|
||||||
|
Simplifying constant integer cast 3
|
||||||
|
Successful SSA optimization PassNCastSimplification
|
||||||
|
Finalized unsigned number type (char) 2
|
||||||
|
Finalized unsigned number type (char) 3
|
||||||
|
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||||
|
Alias candidate removed (volatile)plus::return_border = plus::$0
|
||||||
|
Alias candidate removed (volatile)plus::return_bg = plus::$1
|
||||||
|
Alias main::c_border#1 = main::$1_border
|
||||||
|
Alias main::c_bg#1 = main::$1_bg
|
||||||
|
Successful SSA optimization Pass2AliasElimination
|
||||||
|
Alias candidate removed (volatile)plus::return_border = plus::$0
|
||||||
|
Alias candidate removed (volatile)plus::return_bg = plus::$1
|
||||||
|
Simplifying expression containing zero (char *)COLS in [13] *((char *)COLS+OFFSET_STRUCT_COLS_BORDER) = main::c_border#0
|
||||||
|
Simplifying expression containing zero (char *)COLS in [22] *((char *)COLS+OFFSET_STRUCT_COLS_BORDER) = main::c_border#1
|
||||||
|
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||||
|
Eliminating unused variable plus::return and assignment [4] plus::return = struct-unwound {plus::return_border, plus::return_bg}
|
||||||
|
Eliminating unused constant OFFSET_STRUCT_COLS_BORDER
|
||||||
|
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
|
||||||
|
Alias candidate removed (volatile)plus::return_border = plus::$0
|
||||||
|
Alias candidate removed (volatile)plus::return_bg = plus::$1
|
||||||
|
Alias candidate removed (volatile)plus::return_border = plus::$0
|
||||||
|
Alias candidate removed (volatile)plus::return_bg = plus::$1
|
||||||
|
Alias candidate removed (volatile)plus::return_border = plus::$0
|
||||||
|
Alias candidate removed (volatile)plus::return_bg = plus::$1
|
||||||
|
CALL GRAPH
|
||||||
|
Calls in [main] to plus:4 plus:13
|
||||||
|
|
||||||
|
Created 0 initial phi equivalence classes
|
||||||
|
Coalesced down to 0 phi equivalence classes
|
||||||
|
|
||||||
|
FINAL CONTROL FLOW GRAPH
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] plus::a_border = main::a_border
|
||||||
|
[1] plus::a_bg = main::a_bg
|
||||||
|
[2] plus::b_border = 2
|
||||||
|
[3] plus::b_bg = 3
|
||||||
|
[4] callexecute plus
|
||||||
|
[5] main::c_border#0 = plus::return_border
|
||||||
|
[6] main::c_bg#0 = plus::return_bg
|
||||||
|
[7] *((char *)COLS) = main::c_border#0
|
||||||
|
[8] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#0
|
||||||
|
[9] plus::a_border = main::c_border#0
|
||||||
|
[10] plus::a_bg = main::c_bg#0
|
||||||
|
[11] plus::b_border = main::a_border
|
||||||
|
[12] plus::b_bg = main::a_bg
|
||||||
|
[13] callexecute plus
|
||||||
|
[14] main::c_border#1 = plus::return_border
|
||||||
|
[15] main::c_bg#1 = plus::return_bg
|
||||||
|
[16] *((char *)COLS) = main::c_border#1
|
||||||
|
[17] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#1
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[18] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
__varcall struct Cols plus(char a_border , char a_bg , char b_border , char b_bg)
|
||||||
|
plus: scope:[plus] from
|
||||||
|
[19] plus::$0 = plus::a_border + plus::b_border
|
||||||
|
[20] plus::$1 = plus::a_bg + plus::b_bg
|
||||||
|
[21] plus::return_border = plus::$0
|
||||||
|
[22] plus::return_bg = plus::$1
|
||||||
|
to:plus::@return
|
||||||
|
plus::@return: scope:[plus] from plus
|
||||||
|
[23] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
|
||||||
|
VARIABLE REGISTER WEIGHTS
|
||||||
|
void main()
|
||||||
|
char main::c_bg
|
||||||
|
char main::c_bg#0 // 1.5
|
||||||
|
char main::c_bg#1 // 2.0
|
||||||
|
char main::c_border
|
||||||
|
char main::c_border#0 // 1.5
|
||||||
|
char main::c_border#1 // 2.0
|
||||||
|
__varcall struct Cols plus(char a_border , char a_bg , char b_border , char b_bg)
|
||||||
|
char plus::$0 // 11.0
|
||||||
|
char plus::$1 // 11.0
|
||||||
|
__loadstore char plus::a_bg // 2.142857142857143
|
||||||
|
__loadstore char plus::a_border // 1.875
|
||||||
|
__loadstore char plus::b_bg // 5.0
|
||||||
|
__loadstore char plus::b_border // 3.75
|
||||||
|
__loadstore char plus::return_bg // 2.5
|
||||||
|
__loadstore char plus::return_border // 3.0
|
||||||
|
|
||||||
|
Initial phi equivalence classes
|
||||||
|
Added variable plus::a_border to live range equivalence class [ plus::a_border ]
|
||||||
|
Added variable plus::a_bg to live range equivalence class [ plus::a_bg ]
|
||||||
|
Added variable plus::b_border to live range equivalence class [ plus::b_border ]
|
||||||
|
Added variable plus::b_bg to live range equivalence class [ plus::b_bg ]
|
||||||
|
Added variable main::c_border#0 to live range equivalence class [ main::c_border#0 ]
|
||||||
|
Added variable main::c_bg#0 to live range equivalence class [ main::c_bg#0 ]
|
||||||
|
Added variable main::c_border#1 to live range equivalence class [ main::c_border#1 ]
|
||||||
|
Added variable main::c_bg#1 to live range equivalence class [ main::c_bg#1 ]
|
||||||
|
Added variable plus::$0 to live range equivalence class [ plus::$0 ]
|
||||||
|
Added variable plus::$1 to live range equivalence class [ plus::$1 ]
|
||||||
|
Added variable plus::return_border to live range equivalence class [ plus::return_border ]
|
||||||
|
Added variable plus::return_bg to live range equivalence class [ plus::return_bg ]
|
||||||
|
Complete equivalence classes
|
||||||
|
[ plus::a_border ]
|
||||||
|
[ plus::a_bg ]
|
||||||
|
[ plus::b_border ]
|
||||||
|
[ plus::b_bg ]
|
||||||
|
[ main::c_border#0 ]
|
||||||
|
[ main::c_bg#0 ]
|
||||||
|
[ main::c_border#1 ]
|
||||||
|
[ main::c_bg#1 ]
|
||||||
|
[ plus::$0 ]
|
||||||
|
[ plus::$1 ]
|
||||||
|
[ plus::return_border ]
|
||||||
|
[ plus::return_bg ]
|
||||||
|
Allocated zp[1]:2 [ plus::$0 ]
|
||||||
|
Allocated zp[1]:3 [ plus::$1 ]
|
||||||
|
Allocated zp[1]:4 [ plus::b_bg ]
|
||||||
|
Allocated zp[1]:5 [ plus::b_border ]
|
||||||
|
Allocated zp[1]:6 [ plus::return_border ]
|
||||||
|
Allocated zp[1]:7 [ plus::return_bg ]
|
||||||
|
Allocated zp[1]:8 [ plus::a_bg ]
|
||||||
|
Allocated zp[1]:9 [ main::c_border#1 ]
|
||||||
|
Allocated zp[1]:10 [ main::c_bg#1 ]
|
||||||
|
Allocated zp[1]:11 [ plus::a_border ]
|
||||||
|
Allocated zp[1]:12 [ main::c_border#0 ]
|
||||||
|
Allocated zp[1]:13 [ main::c_bg#0 ]
|
||||||
|
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||||
|
Statement [0] plus::a_border = main::a_border [ plus::a_border ] ( [ plus::a_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [1] plus::a_bg = main::a_bg [ plus::a_border plus::a_bg ] ( [ plus::a_border plus::a_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [2] plus::b_border = 2 [ plus::a_border plus::a_bg plus::b_border ] ( [ plus::a_border plus::a_bg plus::b_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [3] plus::b_bg = 3 [ plus::a_border plus::a_bg plus::b_border plus::b_bg ] ( [ plus::a_border plus::a_bg plus::b_border plus::b_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [11] plus::b_border = main::a_border [ plus::a_border plus::a_bg plus::b_border ] ( [ plus::a_border plus::a_bg plus::b_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [12] plus::b_bg = main::a_bg [ plus::a_border plus::a_bg plus::b_border plus::b_bg ] ( [ plus::a_border plus::a_bg plus::b_border plus::b_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [19] plus::$0 = plus::a_border + plus::b_border [ plus::a_bg plus::b_bg plus::$0 ] ( plus:4 [ plus::a_bg plus::b_bg plus::$0 ] { { main::c_border#0 = plus::a_border } { main::c_bg#0 = plus::a_bg } } plus:13 [ plus::a_bg plus::b_bg plus::$0 ] { { main::c_border#0 = plus::a_border } { main::c_bg#0 = plus::a_bg } } ) always clobbers reg byte a
|
||||||
|
Statement [20] plus::$1 = plus::a_bg + plus::b_bg [ plus::$0 plus::$1 ] ( plus:4 [ plus::$0 plus::$1 ] { { main::c_border#0 = plus::a_border } { main::c_bg#0 = plus::a_bg } } plus:13 [ plus::$0 plus::$1 ] { { main::c_border#0 = plus::a_border } { main::c_bg#0 = plus::a_bg } } ) always clobbers reg byte a
|
||||||
|
Removing always clobbered register reg byte a as potential for zp[1]:2 [ plus::$0 ]
|
||||||
|
Statement [0] plus::a_border = main::a_border [ plus::a_border ] ( [ plus::a_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [1] plus::a_bg = main::a_bg [ plus::a_border plus::a_bg ] ( [ plus::a_border plus::a_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [2] plus::b_border = 2 [ plus::a_border plus::a_bg plus::b_border ] ( [ plus::a_border plus::a_bg plus::b_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [3] plus::b_bg = 3 [ plus::a_border plus::a_bg plus::b_border plus::b_bg ] ( [ plus::a_border plus::a_bg plus::b_border plus::b_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [11] plus::b_border = main::a_border [ plus::a_border plus::a_bg plus::b_border ] ( [ plus::a_border plus::a_bg plus::b_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [12] plus::b_bg = main::a_bg [ plus::a_border plus::a_bg plus::b_border plus::b_bg ] ( [ plus::a_border plus::a_bg plus::b_border plus::b_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [19] plus::$0 = plus::a_border + plus::b_border [ plus::a_bg plus::b_bg plus::$0 ] ( plus:4 [ plus::a_bg plus::b_bg plus::$0 ] { { main::c_border#0 = plus::a_border } { main::c_bg#0 = plus::a_bg } } plus:13 [ plus::a_bg plus::b_bg plus::$0 ] { { main::c_border#0 = plus::a_border } { main::c_bg#0 = plus::a_bg } } ) always clobbers reg byte a
|
||||||
|
Statement [20] plus::$1 = plus::a_bg + plus::b_bg [ plus::$0 plus::$1 ] ( plus:4 [ plus::$0 plus::$1 ] { { main::c_border#0 = plus::a_border } { main::c_bg#0 = plus::a_bg } } plus:13 [ plus::$0 plus::$1 ] { { main::c_border#0 = plus::a_border } { main::c_bg#0 = plus::a_bg } } ) always clobbers reg byte a
|
||||||
|
Potential registers zp[1]:11 [ plus::a_border ] : zp[1]:11 ,
|
||||||
|
Potential registers zp[1]:8 [ plus::a_bg ] : zp[1]:8 ,
|
||||||
|
Potential registers zp[1]:5 [ plus::b_border ] : zp[1]:5 ,
|
||||||
|
Potential registers zp[1]:4 [ plus::b_bg ] : zp[1]:4 ,
|
||||||
|
Potential registers zp[1]:12 [ main::c_border#0 ] : zp[1]:12 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:13 [ main::c_bg#0 ] : zp[1]:13 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:9 [ main::c_border#1 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:10 [ main::c_bg#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:2 [ plus::$0 ] : zp[1]:2 , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:3 [ plus::$1 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:6 [ plus::return_border ] : zp[1]:6 ,
|
||||||
|
Potential registers zp[1]:7 [ plus::return_bg ] : zp[1]:7 ,
|
||||||
|
|
||||||
|
REGISTER UPLIFT SCOPES
|
||||||
|
Uplift Scope [plus] 11: zp[1]:2 [ plus::$0 ] 11: zp[1]:3 [ plus::$1 ] 5: zp[1]:4 [ plus::b_bg ] 3.75: zp[1]:5 [ plus::b_border ] 3: zp[1]:6 [ plus::return_border ] 2.5: zp[1]:7 [ plus::return_bg ] 2.14: zp[1]:8 [ plus::a_bg ] 1.88: zp[1]:11 [ plus::a_border ]
|
||||||
|
Uplift Scope [main] 2: zp[1]:9 [ main::c_border#1 ] 2: zp[1]:10 [ main::c_bg#1 ] 1.5: zp[1]:12 [ main::c_border#0 ] 1.5: zp[1]:13 [ main::c_bg#0 ]
|
||||||
|
Uplift Scope [Cols]
|
||||||
|
Uplift Scope []
|
||||||
|
|
||||||
|
Uplifting [plus] best 148 combination reg byte x [ plus::$0 ] reg byte a [ plus::$1 ] zp[1]:4 [ plus::b_bg ] zp[1]:5 [ plus::b_border ] zp[1]:6 [ plus::return_border ] zp[1]:7 [ plus::return_bg ] zp[1]:8 [ plus::a_bg ] zp[1]:11 [ plus::a_border ]
|
||||||
|
Uplifting [main] best 124 combination reg byte x [ main::c_border#1 ] zp[1]:10 [ main::c_bg#1 ] reg byte x [ main::c_border#0 ] reg byte a [ main::c_bg#0 ]
|
||||||
|
Limited combination testing to 100 combinations of 256 possible.
|
||||||
|
Uplifting [Cols] best 124 combination
|
||||||
|
Uplifting [] best 124 combination
|
||||||
|
Attempting to uplift remaining variables inzp[1]:4 [ plus::b_bg ]
|
||||||
|
Uplifting [plus] best 124 combination zp[1]:4 [ plus::b_bg ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:5 [ plus::b_border ]
|
||||||
|
Uplifting [plus] best 124 combination zp[1]:5 [ plus::b_border ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:6 [ plus::return_border ]
|
||||||
|
Uplifting [plus] best 124 combination zp[1]:6 [ plus::return_border ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:7 [ plus::return_bg ]
|
||||||
|
Uplifting [plus] best 124 combination zp[1]:7 [ plus::return_bg ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:8 [ plus::a_bg ]
|
||||||
|
Uplifting [plus] best 124 combination zp[1]:8 [ plus::a_bg ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:10 [ main::c_bg#1 ]
|
||||||
|
Uplifting [main] best 118 combination reg byte a [ main::c_bg#1 ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:11 [ plus::a_border ]
|
||||||
|
Uplifting [plus] best 118 combination zp[1]:11 [ plus::a_border ]
|
||||||
|
Allocated (was zp[1]:4) zp[1]:2 [ plus::b_bg ]
|
||||||
|
Allocated (was zp[1]:5) zp[1]:3 [ plus::b_border ]
|
||||||
|
Allocated (was zp[1]:6) zp[1]:4 [ plus::return_border ]
|
||||||
|
Allocated (was zp[1]:7) zp[1]:5 [ plus::return_bg ]
|
||||||
|
Allocated (was zp[1]:8) zp[1]:6 [ plus::a_bg ]
|
||||||
|
Allocated (was zp[1]:11) zp[1]:7 [ plus::a_border ]
|
||||||
|
|
||||||
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
|
// File Comments
|
||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct parameter & return value
|
||||||
|
// Upstart
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-6.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
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
.const a_border = 1
|
||||||
|
.const a_bg = 2
|
||||||
|
// [0] plus::a_border = main::a_border -- vbuz1=vbuc1
|
||||||
|
lda #a_border
|
||||||
|
sta.z plus.a_border
|
||||||
|
// [1] plus::a_bg = main::a_bg -- vbuz1=vbuc1
|
||||||
|
lda #a_bg
|
||||||
|
sta.z plus.a_bg
|
||||||
|
// [2] plus::b_border = 2 -- vbuz1=vbuc1
|
||||||
|
lda #2
|
||||||
|
sta.z plus.b_border
|
||||||
|
// [3] plus::b_bg = 3 -- vbuz1=vbuc1
|
||||||
|
lda #3
|
||||||
|
sta.z plus.b_bg
|
||||||
|
// [4] callexecute plus -- call_vprc1
|
||||||
|
jsr plus
|
||||||
|
// [5] main::c_border#0 = plus::return_border -- vbuxx=vbuz1
|
||||||
|
ldx.z plus.return_border
|
||||||
|
// [6] main::c_bg#0 = plus::return_bg -- vbuaa=vbuz1
|
||||||
|
lda.z plus.return_bg
|
||||||
|
// [7] *((char *)COLS) = main::c_border#0 -- _deref_pbuc1=vbuxx
|
||||||
|
stx COLS
|
||||||
|
// [8] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#0 -- _deref_pbuc1=vbuaa
|
||||||
|
sta COLS+OFFSET_STRUCT_COLS_BG
|
||||||
|
// [9] plus::a_border = main::c_border#0 -- vbuz1=vbuxx
|
||||||
|
stx.z plus.a_border
|
||||||
|
// [10] plus::a_bg = main::c_bg#0 -- vbuz1=vbuaa
|
||||||
|
sta.z plus.a_bg
|
||||||
|
// [11] plus::b_border = main::a_border -- vbuz1=vbuc1
|
||||||
|
lda #a_border
|
||||||
|
sta.z plus.b_border
|
||||||
|
// [12] plus::b_bg = main::a_bg -- vbuz1=vbuc1
|
||||||
|
lda #a_bg
|
||||||
|
sta.z plus.b_bg
|
||||||
|
// [13] callexecute plus -- call_vprc1
|
||||||
|
jsr plus
|
||||||
|
// [14] main::c_border#1 = plus::return_border -- vbuxx=vbuz1
|
||||||
|
ldx.z plus.return_border
|
||||||
|
// [15] main::c_bg#1 = plus::return_bg -- vbuaa=vbuz1
|
||||||
|
lda.z plus.return_bg
|
||||||
|
// [16] *((char *)COLS) = main::c_border#1 -- _deref_pbuc1=vbuxx
|
||||||
|
stx COLS
|
||||||
|
// [17] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#1 -- _deref_pbuc1=vbuaa
|
||||||
|
sta COLS+OFFSET_STRUCT_COLS_BG
|
||||||
|
jmp __breturn
|
||||||
|
// main::@return
|
||||||
|
__breturn:
|
||||||
|
// [18] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// plus
|
||||||
|
// struct Cols plus(__zp(7) char a_border, __zp(6) char a_bg, __zp(3) char b_border, __zp(2) char b_bg)
|
||||||
|
plus: {
|
||||||
|
.label a_border = 7
|
||||||
|
.label a_bg = 6
|
||||||
|
.label b_border = 3
|
||||||
|
.label b_bg = 2
|
||||||
|
.label return_border = 4
|
||||||
|
.label return_bg = 5
|
||||||
|
// [19] plus::$0 = plus::a_border + plus::b_border -- vbuxx=vbuz1_plus_vbuz2
|
||||||
|
lda.z a_border
|
||||||
|
clc
|
||||||
|
adc.z b_border
|
||||||
|
tax
|
||||||
|
// [20] plus::$1 = plus::a_bg + plus::b_bg -- vbuaa=vbuz1_plus_vbuz2
|
||||||
|
lda.z a_bg
|
||||||
|
clc
|
||||||
|
adc.z b_bg
|
||||||
|
// [21] plus::return_border = plus::$0 -- vbuz1=vbuxx
|
||||||
|
stx.z return_border
|
||||||
|
// [22] plus::return_bg = plus::$1 -- vbuz1=vbuaa
|
||||||
|
sta.z return_bg
|
||||||
|
jmp __breturn
|
||||||
|
// plus::@return
|
||||||
|
__breturn:
|
||||||
|
// [23] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
||||||
|
ASSEMBLER OPTIMIZATIONS
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Succesful ASM optimization Pass5NextJumpElimination
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||||
|
|
||||||
|
FINAL SYMBOL TABLE
|
||||||
|
__constant struct Cols * const COLS = (struct Cols *) 53280
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
void main()
|
||||||
|
__constant char main::a_bg = 2
|
||||||
|
__constant char main::a_border = 1
|
||||||
|
char main::c_bg
|
||||||
|
char main::c_bg#0 // reg byte a 1.5
|
||||||
|
char main::c_bg#1 // reg byte a 2.0
|
||||||
|
char main::c_border
|
||||||
|
char main::c_border#0 // reg byte x 1.5
|
||||||
|
char main::c_border#1 // reg byte x 2.0
|
||||||
|
__varcall struct Cols plus(char a_border , char a_bg , char b_border , char b_bg)
|
||||||
|
char plus::$0 // reg byte x 11.0
|
||||||
|
char plus::$1 // reg byte a 11.0
|
||||||
|
__loadstore char plus::a_bg // zp[1]:6 2.142857142857143
|
||||||
|
__loadstore char plus::a_border // zp[1]:7 1.875
|
||||||
|
__loadstore char plus::b_bg // zp[1]:2 5.0
|
||||||
|
__loadstore char plus::b_border // zp[1]:3 3.75
|
||||||
|
__loadstore char plus::return_bg // zp[1]:5 2.5
|
||||||
|
__loadstore char plus::return_border // zp[1]:4 3.0
|
||||||
|
|
||||||
|
zp[1]:7 [ plus::a_border ]
|
||||||
|
zp[1]:6 [ plus::a_bg ]
|
||||||
|
zp[1]:3 [ plus::b_border ]
|
||||||
|
zp[1]:2 [ plus::b_bg ]
|
||||||
|
reg byte x [ main::c_border#0 ]
|
||||||
|
reg byte a [ main::c_bg#0 ]
|
||||||
|
reg byte x [ main::c_border#1 ]
|
||||||
|
reg byte a [ main::c_bg#1 ]
|
||||||
|
reg byte x [ plus::$0 ]
|
||||||
|
reg byte a [ plus::$1 ]
|
||||||
|
zp[1]:4 [ plus::return_border ]
|
||||||
|
zp[1]:5 [ plus::return_bg ]
|
||||||
|
|
||||||
|
|
||||||
|
FINAL ASSEMBLER
|
||||||
|
Score: 112
|
||||||
|
|
||||||
|
// File Comments
|
||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct parameter & return value
|
||||||
|
// Upstart
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-6.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
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
.const a_border = 1
|
||||||
|
.const a_bg = 2
|
||||||
|
// struct Cols c = plus(a, { 2, 3 })
|
||||||
|
// [0] plus::a_border = main::a_border -- vbuz1=vbuc1
|
||||||
|
lda #a_border
|
||||||
|
sta.z plus.a_border
|
||||||
|
// [1] plus::a_bg = main::a_bg -- vbuz1=vbuc1
|
||||||
|
lda #a_bg
|
||||||
|
sta.z plus.a_bg
|
||||||
|
// [2] plus::b_border = 2 -- vbuz1=vbuc1
|
||||||
|
lda #2
|
||||||
|
sta.z plus.b_border
|
||||||
|
// [3] plus::b_bg = 3 -- vbuz1=vbuc1
|
||||||
|
lda #3
|
||||||
|
sta.z plus.b_bg
|
||||||
|
// [4] callexecute plus -- call_vprc1
|
||||||
|
jsr plus
|
||||||
|
// [5] main::c_border#0 = plus::return_border -- vbuxx=vbuz1
|
||||||
|
ldx.z plus.return_border
|
||||||
|
// [6] main::c_bg#0 = plus::return_bg -- vbuaa=vbuz1
|
||||||
|
lda.z plus.return_bg
|
||||||
|
// *COLS = c
|
||||||
|
// [7] *((char *)COLS) = main::c_border#0 -- _deref_pbuc1=vbuxx
|
||||||
|
stx COLS
|
||||||
|
// [8] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#0 -- _deref_pbuc1=vbuaa
|
||||||
|
sta COLS+OFFSET_STRUCT_COLS_BG
|
||||||
|
// plus(c, a)
|
||||||
|
// [9] plus::a_border = main::c_border#0 -- vbuz1=vbuxx
|
||||||
|
stx.z plus.a_border
|
||||||
|
// [10] plus::a_bg = main::c_bg#0 -- vbuz1=vbuaa
|
||||||
|
sta.z plus.a_bg
|
||||||
|
// [11] plus::b_border = main::a_border -- vbuz1=vbuc1
|
||||||
|
lda #a_border
|
||||||
|
sta.z plus.b_border
|
||||||
|
// [12] plus::b_bg = main::a_bg -- vbuz1=vbuc1
|
||||||
|
lda #a_bg
|
||||||
|
sta.z plus.b_bg
|
||||||
|
// [13] callexecute plus -- call_vprc1
|
||||||
|
jsr plus
|
||||||
|
// c = plus(c, a)
|
||||||
|
// [14] main::c_border#1 = plus::return_border -- vbuxx=vbuz1
|
||||||
|
ldx.z plus.return_border
|
||||||
|
// [15] main::c_bg#1 = plus::return_bg -- vbuaa=vbuz1
|
||||||
|
lda.z plus.return_bg
|
||||||
|
// *COLS = c
|
||||||
|
// [16] *((char *)COLS) = main::c_border#1 -- _deref_pbuc1=vbuxx
|
||||||
|
stx COLS
|
||||||
|
// [17] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#1 -- _deref_pbuc1=vbuaa
|
||||||
|
sta COLS+OFFSET_STRUCT_COLS_BG
|
||||||
|
// main::@return
|
||||||
|
// }
|
||||||
|
// [18] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// plus
|
||||||
|
// struct Cols plus(__zp(7) char a_border, __zp(6) char a_bg, __zp(3) char b_border, __zp(2) char b_bg)
|
||||||
|
plus: {
|
||||||
|
.label a_border = 7
|
||||||
|
.label a_bg = 6
|
||||||
|
.label b_border = 3
|
||||||
|
.label b_bg = 2
|
||||||
|
.label return_border = 4
|
||||||
|
.label return_bg = 5
|
||||||
|
// a.border+b.border
|
||||||
|
// [19] plus::$0 = plus::a_border + plus::b_border -- vbuxx=vbuz1_plus_vbuz2
|
||||||
|
lda.z a_border
|
||||||
|
clc
|
||||||
|
adc.z b_border
|
||||||
|
tax
|
||||||
|
// a.bg+b.bg
|
||||||
|
// [20] plus::$1 = plus::a_bg + plus::b_bg -- vbuaa=vbuz1_plus_vbuz2
|
||||||
|
lda.z a_bg
|
||||||
|
clc
|
||||||
|
adc.z b_bg
|
||||||
|
// return { a.border+b.border, a.bg+b.bg };
|
||||||
|
// [21] plus::return_border = plus::$0 -- vbuz1=vbuxx
|
||||||
|
stx.z return_border
|
||||||
|
// [22] plus::return_bg = plus::$1 -- vbuz1=vbuaa
|
||||||
|
sta.z return_bg
|
||||||
|
// plus::@return
|
||||||
|
// }
|
||||||
|
// [23] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
33
src/test/ref/varcall-6.sym
Normal file
33
src/test/ref/varcall-6.sym
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
__constant struct Cols * const COLS = (struct Cols *) 53280
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
void main()
|
||||||
|
__constant char main::a_bg = 2
|
||||||
|
__constant char main::a_border = 1
|
||||||
|
char main::c_bg
|
||||||
|
char main::c_bg#0 // reg byte a 1.5
|
||||||
|
char main::c_bg#1 // reg byte a 2.0
|
||||||
|
char main::c_border
|
||||||
|
char main::c_border#0 // reg byte x 1.5
|
||||||
|
char main::c_border#1 // reg byte x 2.0
|
||||||
|
__varcall struct Cols plus(char a_border , char a_bg , char b_border , char b_bg)
|
||||||
|
char plus::$0 // reg byte x 11.0
|
||||||
|
char plus::$1 // reg byte a 11.0
|
||||||
|
__loadstore char plus::a_bg // zp[1]:6 2.142857142857143
|
||||||
|
__loadstore char plus::a_border // zp[1]:7 1.875
|
||||||
|
__loadstore char plus::b_bg // zp[1]:2 5.0
|
||||||
|
__loadstore char plus::b_border // zp[1]:3 3.75
|
||||||
|
__loadstore char plus::return_bg // zp[1]:5 2.5
|
||||||
|
__loadstore char plus::return_border // zp[1]:4 3.0
|
||||||
|
|
||||||
|
zp[1]:7 [ plus::a_border ]
|
||||||
|
zp[1]:6 [ plus::a_bg ]
|
||||||
|
zp[1]:3 [ plus::b_border ]
|
||||||
|
zp[1]:2 [ plus::b_bg ]
|
||||||
|
reg byte x [ main::c_border#0 ]
|
||||||
|
reg byte a [ main::c_bg#0 ]
|
||||||
|
reg byte x [ main::c_border#1 ]
|
||||||
|
reg byte a [ main::c_bg#1 ]
|
||||||
|
reg byte x [ plus::$0 ]
|
||||||
|
reg byte a [ plus::$1 ]
|
||||||
|
zp[1]:4 [ plus::return_border ]
|
||||||
|
zp[1]:5 [ plus::return_bg ]
|
33
src/test/ref/varcall-7.asm
Normal file
33
src/test/ref/varcall-7.asm
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct parameter & return value - only a single call
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-7.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)
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
main: {
|
||||||
|
.label a_border = 1
|
||||||
|
.label a_bg = 2
|
||||||
|
.label b_border = 2
|
||||||
|
.label b_bg = 3
|
||||||
|
// struct Cols c = plus(a, b)
|
||||||
|
jsr plus
|
||||||
|
// *COLS = c
|
||||||
|
lda #plus.return_border
|
||||||
|
sta COLS
|
||||||
|
lda #plus.return_bg
|
||||||
|
sta COLS+OFFSET_STRUCT_COLS_BG
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
plus: {
|
||||||
|
.label return_border = main.a_border+main.b_border
|
||||||
|
.label return_bg = main.a_bg+main.b_bg
|
||||||
|
rts
|
||||||
|
}
|
19
src/test/ref/varcall-7.cfg
Normal file
19
src/test/ref/varcall-7.cfg
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] phi()
|
||||||
|
[1] callexecute plus
|
||||||
|
[2] *((char *)COLS) = plus::return_border
|
||||||
|
[3] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = plus::return_bg
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[4] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
__varcall struct Cols plus()
|
||||||
|
plus: scope:[plus] from
|
||||||
|
[5] phi()
|
||||||
|
to:plus::@return
|
||||||
|
plus::@return: scope:[plus] from plus
|
||||||
|
[6] return
|
||||||
|
to:@return
|
301
src/test/ref/varcall-7.log
Normal file
301
src/test/ref/varcall-7.log
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
Converting parameter in __varcall procedure to load/store plus::a
|
||||||
|
Converting parameter in __varcall procedure to load/store plus::b
|
||||||
|
Converting return in __varcall procedure to load/store plus::return
|
||||||
|
Constantified RValue plus::return = (struct Cols){ plus::$0, plus::$1 }
|
||||||
|
Eliminating unused variable with no statement plus::a
|
||||||
|
Eliminating unused variable with no statement plus::b
|
||||||
|
Eliminating unused variable with no statement main::$0
|
||||||
|
Calling convention __varcall adding prepare/execute/finalize for { main::c_border, main::c_bg } = call plus(main::a_border, main::a_bg, main::b_border, main::b_bg)
|
||||||
|
|
||||||
|
CONTROL FLOW GRAPH SSA
|
||||||
|
|
||||||
|
__varcall struct Cols plus(char a_border , char a_bg , char b_border , char b_bg)
|
||||||
|
plus: scope:[plus] from
|
||||||
|
plus::$0 = plus::a_border + plus::b_border
|
||||||
|
plus::$1 = plus::a_bg + plus::b_bg
|
||||||
|
plus::return_border = plus::$0
|
||||||
|
plus::return_bg = plus::$1
|
||||||
|
plus::return = struct-unwound {plus::return_border, plus::return_bg}
|
||||||
|
to:plus::@return
|
||||||
|
plus::@return: scope:[plus] from plus
|
||||||
|
return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from __start
|
||||||
|
plus::a_border = main::a_border
|
||||||
|
plus::a_bg = main::a_bg
|
||||||
|
plus::b_border = main::b_border
|
||||||
|
plus::b_bg = main::b_bg
|
||||||
|
callexecute plus
|
||||||
|
main::c_border#0 = plus::return_border
|
||||||
|
main::c_bg#0 = plus::return_bg
|
||||||
|
*((char *)COLS+OFFSET_STRUCT_COLS_BORDER) = main::c_border#0
|
||||||
|
*((char *)COLS+OFFSET_STRUCT_COLS_BG) = main::c_bg#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 struct Cols * const COLS = (struct Cols *)$d020
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BORDER = 0
|
||||||
|
void __start()
|
||||||
|
void main()
|
||||||
|
__constant char main::a_bg = 2
|
||||||
|
__constant char main::a_border = 1
|
||||||
|
__constant char main::b_bg = 3
|
||||||
|
__constant char main::b_border = 2
|
||||||
|
struct Cols main::c
|
||||||
|
char main::c_bg
|
||||||
|
char main::c_bg#0
|
||||||
|
char main::c_border
|
||||||
|
char main::c_border#0
|
||||||
|
__varcall struct Cols plus(char a_border , char a_bg , char b_border , char b_bg)
|
||||||
|
char plus::$0
|
||||||
|
char plus::$1
|
||||||
|
__loadstore char plus::a_bg
|
||||||
|
__loadstore char plus::a_border
|
||||||
|
__loadstore char plus::b_bg
|
||||||
|
__loadstore char plus::b_border
|
||||||
|
__loadstore struct Cols plus::return
|
||||||
|
__loadstore char plus::return_bg
|
||||||
|
__loadstore char plus::return_border
|
||||||
|
|
||||||
|
Simplifying constant pointer cast (struct Cols *) 53280
|
||||||
|
Successful SSA optimization PassNCastSimplification
|
||||||
|
Alias candidate removed (volatile)plus::return_border = plus::$0
|
||||||
|
Alias candidate removed (volatile)plus::return_bg = plus::$1
|
||||||
|
Constant plus::a_border = main::a_border
|
||||||
|
Constant plus::a_bg = main::a_bg
|
||||||
|
Constant plus::b_border = main::b_border
|
||||||
|
Constant plus::b_bg = main::b_bg
|
||||||
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
|
Simplifying expression containing zero (char *)COLS in [13] *((char *)COLS+OFFSET_STRUCT_COLS_BORDER) = main::c_border#0
|
||||||
|
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||||
|
Eliminating unused variable plus::return and assignment [4] plus::return = struct-unwound {plus::return_border, plus::return_bg}
|
||||||
|
Eliminating unused constant OFFSET_STRUCT_COLS_BORDER
|
||||||
|
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
|
||||||
|
Alias candidate removed (volatile)plus::return_border = plus::$0
|
||||||
|
Alias candidate removed (volatile)plus::return_bg = plus::$1
|
||||||
|
Constant right-side identified [0] plus::$0 = plus::a_border + plus::b_border
|
||||||
|
Constant right-side identified [1] plus::$1 = plus::a_bg + plus::b_bg
|
||||||
|
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||||
|
Constant plus::$0 = plus::a_border+plus::b_border
|
||||||
|
Constant plus::$1 = plus::a_bg+plus::b_bg
|
||||||
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
|
Constant plus::return_border = plus::$0
|
||||||
|
Constant plus::return_bg = plus::$1
|
||||||
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
|
Constant main::c_border#0 = plus::return_border
|
||||||
|
Constant main::c_bg#0 = plus::return_bg
|
||||||
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
|
Parameter inlined plus::b_bg
|
||||||
|
Parameter inlined plus::a_bg
|
||||||
|
Parameter inlined plus::b_border
|
||||||
|
Parameter inlined plus::a_border
|
||||||
|
Constant inlined main::c_border#0 = plus::return_border
|
||||||
|
Constant inlined plus::b_bg = main::b_bg
|
||||||
|
Constant inlined plus::a_bg = main::a_bg
|
||||||
|
Constant inlined plus::b_border = main::b_border
|
||||||
|
Constant inlined plus::a_border = main::a_border
|
||||||
|
Constant inlined plus::$1 = main::a_bg+main::b_bg
|
||||||
|
Constant inlined plus::$0 = main::a_border+main::b_border
|
||||||
|
Constant inlined main::c_bg#0 = plus::return_bg
|
||||||
|
Successful SSA optimization Pass2ConstantInlining
|
||||||
|
Adding NOP phi() at start of main
|
||||||
|
Adding NOP phi() at start of plus
|
||||||
|
CALL GRAPH
|
||||||
|
Calls in [main] to plus:1
|
||||||
|
|
||||||
|
Created 0 initial phi equivalence classes
|
||||||
|
Coalesced down to 0 phi equivalence classes
|
||||||
|
Adding NOP phi() at start of main
|
||||||
|
Adding NOP phi() at start of plus
|
||||||
|
|
||||||
|
FINAL CONTROL FLOW GRAPH
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] phi()
|
||||||
|
[1] callexecute plus
|
||||||
|
[2] *((char *)COLS) = plus::return_border
|
||||||
|
[3] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = plus::return_bg
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[4] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
__varcall struct Cols plus()
|
||||||
|
plus: scope:[plus] from
|
||||||
|
[5] phi()
|
||||||
|
to:plus::@return
|
||||||
|
plus::@return: scope:[plus] from plus
|
||||||
|
[6] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
|
||||||
|
VARIABLE REGISTER WEIGHTS
|
||||||
|
void main()
|
||||||
|
struct Cols main::c
|
||||||
|
char main::c_bg
|
||||||
|
char main::c_border
|
||||||
|
__varcall struct Cols plus()
|
||||||
|
|
||||||
|
Initial phi equivalence classes
|
||||||
|
Complete equivalence classes
|
||||||
|
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||||
|
Statement [2] *((char *)COLS) = plus::return_border [ ] ( [ ] { } ) always clobbers reg byte a
|
||||||
|
Statement [3] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = plus::return_bg [ ] ( [ ] { } ) always clobbers reg byte a
|
||||||
|
|
||||||
|
REGISTER UPLIFT SCOPES
|
||||||
|
Uplift Scope [Cols]
|
||||||
|
Uplift Scope [plus]
|
||||||
|
Uplift Scope [main]
|
||||||
|
Uplift Scope []
|
||||||
|
|
||||||
|
Uplifting [Cols] best 63 combination
|
||||||
|
Uplifting [plus] best 63 combination
|
||||||
|
Uplifting [main] best 63 combination
|
||||||
|
Uplifting [] best 63 combination
|
||||||
|
|
||||||
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
|
// File Comments
|
||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct parameter & return value - only a single call
|
||||||
|
// Upstart
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-7.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
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
.label a_border = 1
|
||||||
|
.label a_bg = 2
|
||||||
|
.label b_border = 2
|
||||||
|
.label b_bg = 3
|
||||||
|
// [1] callexecute plus -- call_vprc1
|
||||||
|
jsr plus
|
||||||
|
// [2] *((char *)COLS) = plus::return_border -- _deref_pbuc1=vbuc2
|
||||||
|
lda #plus.return_border
|
||||||
|
sta COLS
|
||||||
|
// [3] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = plus::return_bg -- _deref_pbuc1=vbuc2
|
||||||
|
lda #plus.return_bg
|
||||||
|
sta COLS+OFFSET_STRUCT_COLS_BG
|
||||||
|
jmp __breturn
|
||||||
|
// main::@return
|
||||||
|
__breturn:
|
||||||
|
// [4] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// plus
|
||||||
|
plus: {
|
||||||
|
.label return_border = main.a_border+main.b_border
|
||||||
|
.label return_bg = main.a_bg+main.b_bg
|
||||||
|
jmp __breturn
|
||||||
|
// plus::@return
|
||||||
|
__breturn:
|
||||||
|
// [6] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
||||||
|
ASSEMBLER OPTIMIZATIONS
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Succesful ASM optimization Pass5NextJumpElimination
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||||
|
|
||||||
|
FINAL SYMBOL TABLE
|
||||||
|
__constant struct Cols * const COLS = (struct Cols *) 53280
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
void main()
|
||||||
|
__constant char main::a_bg = 2
|
||||||
|
__constant char main::a_border = 1
|
||||||
|
__constant char main::b_bg = 3
|
||||||
|
__constant char main::b_border = 2
|
||||||
|
struct Cols main::c
|
||||||
|
char main::c_bg
|
||||||
|
char main::c_border
|
||||||
|
__varcall struct Cols plus()
|
||||||
|
__constant char plus::return_bg = main::a_bg+main::b_bg
|
||||||
|
__constant char plus::return_border = main::a_border+main::b_border
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FINAL ASSEMBLER
|
||||||
|
Score: 30
|
||||||
|
|
||||||
|
// File Comments
|
||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct parameter & return value - only a single call
|
||||||
|
// Upstart
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-7.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
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
.label a_border = 1
|
||||||
|
.label a_bg = 2
|
||||||
|
.label b_border = 2
|
||||||
|
.label b_bg = 3
|
||||||
|
// struct Cols c = plus(a, b)
|
||||||
|
// [1] callexecute plus -- call_vprc1
|
||||||
|
jsr plus
|
||||||
|
// *COLS = c
|
||||||
|
// [2] *((char *)COLS) = plus::return_border -- _deref_pbuc1=vbuc2
|
||||||
|
lda #plus.return_border
|
||||||
|
sta COLS
|
||||||
|
// [3] *((char *)COLS+OFFSET_STRUCT_COLS_BG) = plus::return_bg -- _deref_pbuc1=vbuc2
|
||||||
|
lda #plus.return_bg
|
||||||
|
sta COLS+OFFSET_STRUCT_COLS_BG
|
||||||
|
// main::@return
|
||||||
|
// }
|
||||||
|
// [4] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// plus
|
||||||
|
plus: {
|
||||||
|
.label return_border = main.a_border+main.b_border
|
||||||
|
.label return_bg = main.a_bg+main.b_bg
|
||||||
|
// plus::@return
|
||||||
|
// [6] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
14
src/test/ref/varcall-7.sym
Normal file
14
src/test/ref/varcall-7.sym
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
__constant struct Cols * const COLS = (struct Cols *) 53280
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
void main()
|
||||||
|
__constant char main::a_bg = 2
|
||||||
|
__constant char main::a_border = 1
|
||||||
|
__constant char main::b_bg = 3
|
||||||
|
__constant char main::b_border = 2
|
||||||
|
struct Cols main::c
|
||||||
|
char main::c_bg
|
||||||
|
char main::c_border
|
||||||
|
__varcall struct Cols plus()
|
||||||
|
__constant char plus::return_bg = main::a_bg+main::b_bg
|
||||||
|
__constant char plus::return_border = main::a_border+main::b_border
|
||||||
|
|
102
src/test/ref/varcall-8.asm
Normal file
102
src/test/ref/varcall-8.asm
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// Test __varcall calling convention
|
||||||
|
// Pointer to Struct parameter & return value
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-8.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)
|
||||||
|
.const SIZEOF_STRUCT_COLS = 2
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
main: {
|
||||||
|
.label a = 6
|
||||||
|
.label b = 8
|
||||||
|
.label c = $a
|
||||||
|
.label m = 2
|
||||||
|
// struct Cols a = { 1, 7 }
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda __0-1,y
|
||||||
|
sta a-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// struct Cols b = { 2, 6 }
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda __1-1,y
|
||||||
|
sta b-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// struct Cols c = { 3, 5 }
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda __2-1,y
|
||||||
|
sta c-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// struct Cols *m = min(&a,&b)
|
||||||
|
lda #<a
|
||||||
|
sta.z min.a
|
||||||
|
lda #>a
|
||||||
|
sta.z min.a+1
|
||||||
|
lda #<b
|
||||||
|
sta.z min.b
|
||||||
|
lda #>b
|
||||||
|
sta.z min.b+1
|
||||||
|
jsr min
|
||||||
|
// *COLS = *m
|
||||||
|
ldx #SIZEOF_STRUCT_COLS
|
||||||
|
ldy #0
|
||||||
|
!:
|
||||||
|
lda (m),y
|
||||||
|
sta COLS,y
|
||||||
|
iny
|
||||||
|
dex
|
||||||
|
bne !-
|
||||||
|
// min(m,&c)
|
||||||
|
lda #<c
|
||||||
|
sta.z min.b
|
||||||
|
lda #>c
|
||||||
|
sta.z min.b+1
|
||||||
|
jsr min
|
||||||
|
// m = min(m,&c)
|
||||||
|
// *COLS = *m
|
||||||
|
ldx #SIZEOF_STRUCT_COLS
|
||||||
|
ldy #0
|
||||||
|
!:
|
||||||
|
lda (m),y
|
||||||
|
sta COLS,y
|
||||||
|
iny
|
||||||
|
dex
|
||||||
|
bne !-
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// __zp(2) struct Cols * min(__zp(2) struct Cols *a, __zp(4) struct Cols *b)
|
||||||
|
min: {
|
||||||
|
.label a = 2
|
||||||
|
.label b = 4
|
||||||
|
.label return = 2
|
||||||
|
// if(a->bg < b->bg)
|
||||||
|
ldy #OFFSET_STRUCT_COLS_BG
|
||||||
|
lda (b),y
|
||||||
|
cmp (a),y
|
||||||
|
bcc __breturn
|
||||||
|
// return b;
|
||||||
|
lda.z b
|
||||||
|
sta.z return
|
||||||
|
lda.z b+1
|
||||||
|
sta.z return+1
|
||||||
|
__breturn:
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
// return a;
|
||||||
|
}
|
||||||
|
.segment Data
|
||||||
|
__0: .byte 1, 7
|
||||||
|
__1: .byte 2, 6
|
||||||
|
__2: .byte 3, 5
|
34
src/test/ref/varcall-8.cfg
Normal file
34
src/test/ref/varcall-8.cfg
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] *(&main::a) = memcpy(*(&$0), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
[1] *(&main::b) = memcpy(*(&$1), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
[2] *(&main::c) = memcpy(*(&$2), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
[3] min::a = &main::a
|
||||||
|
[4] min::b = &main::b
|
||||||
|
[5] callexecute min
|
||||||
|
[6] main::m#0 = min::return
|
||||||
|
[7] *COLS = memcpy(*main::m#0, struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
[8] min::a = main::m#0
|
||||||
|
[9] min::b = &main::c
|
||||||
|
[10] callexecute min
|
||||||
|
[11] main::m#1 = min::return
|
||||||
|
[12] *COLS = memcpy(*main::m#1, struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[13] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
__varcall struct Cols * min(struct Cols *a , struct Cols *b)
|
||||||
|
min: scope:[min] from
|
||||||
|
[14] if(((char *)min::a)[OFFSET_STRUCT_COLS_BG]<((char *)min::b)[OFFSET_STRUCT_COLS_BG]) goto min::@1
|
||||||
|
to:min::@2
|
||||||
|
min::@2: scope:[min] from min
|
||||||
|
[15] min::return = min::b
|
||||||
|
to:min::@return
|
||||||
|
min::@return: scope:[min] from min::@1 min::@2
|
||||||
|
[16] return
|
||||||
|
to:@return
|
||||||
|
min::@1: scope:[min] from min
|
||||||
|
[17] min::return = min::a
|
||||||
|
to:min::@return
|
539
src/test/ref/varcall-8.log
Normal file
539
src/test/ref/varcall-8.log
Normal file
@ -0,0 +1,539 @@
|
|||||||
|
Setting struct to load/store in variable affected by address-of main::m = call min(&main::a, &main::b)
|
||||||
|
Setting struct to load/store in variable affected by address-of main::m = call min(&main::a, &main::b)
|
||||||
|
Setting struct to load/store in variable affected by address-of main::$1 = call min(main::m, &main::c)
|
||||||
|
Converting parameter in __varcall procedure to load/store min::a
|
||||||
|
Converting parameter in __varcall procedure to load/store min::b
|
||||||
|
Converting return in __varcall procedure to load/store min::return
|
||||||
|
Eliminating unused variable with no statement main::$0
|
||||||
|
Calling convention __varcall adding prepare/execute/finalize for main::m = call min(&main::a, &main::b)
|
||||||
|
Calling convention __varcall adding prepare/execute/finalize for main::$1 = call min(main::m, &main::c)
|
||||||
|
Calling convention VAR_CALL adding return value assignment main::m = min::return
|
||||||
|
Calling convention VAR_CALL adding return value assignment main::$1 = min::return
|
||||||
|
Removing C-classic struct-unwound assignment main::a = struct-unwound {*(&main::a)}
|
||||||
|
Removing C-classic struct-unwound assignment main::b = struct-unwound {*(&main::b)}
|
||||||
|
Removing C-classic struct-unwound assignment main::c = struct-unwound {*(&main::c)}
|
||||||
|
|
||||||
|
CONTROL FLOW GRAPH SSA
|
||||||
|
|
||||||
|
__varcall struct Cols * min(struct Cols *a , struct Cols *b)
|
||||||
|
min: scope:[min] from
|
||||||
|
min::$3 = (char *)min::a
|
||||||
|
min::$1 = min::$3 + OFFSET_STRUCT_COLS_BG
|
||||||
|
min::$4 = (char *)min::b
|
||||||
|
min::$2 = min::$4 + OFFSET_STRUCT_COLS_BG
|
||||||
|
min::$0 = *min::$1 < *min::$2
|
||||||
|
if(min::$0) goto min::@1
|
||||||
|
to:min::@2
|
||||||
|
min::@1: scope:[min] from min
|
||||||
|
min::return = min::a
|
||||||
|
to:min::@return
|
||||||
|
min::@2: scope:[min] from min
|
||||||
|
min::return = min::b
|
||||||
|
to:min::@return
|
||||||
|
min::@return: scope:[min] from min::@1 min::@2
|
||||||
|
return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from __start
|
||||||
|
*(&main::a) = memcpy(*(&$0), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
*(&main::b) = memcpy(*(&$1), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
*(&main::c) = memcpy(*(&$2), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
min::a = &main::a
|
||||||
|
min::b = &main::b
|
||||||
|
callexecute min
|
||||||
|
main::m#0 = min::return
|
||||||
|
*COLS = memcpy(*main::m#0, struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
min::a = main::m#0
|
||||||
|
min::b = &main::c
|
||||||
|
callexecute min
|
||||||
|
main::$1 = min::return
|
||||||
|
main::m#1 = main::$1
|
||||||
|
*COLS = memcpy(*main::m#1, struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
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 struct Cols $0 = { border: 1, bg: 7 }
|
||||||
|
__constant struct Cols $1 = { border: 2, bg: 6 }
|
||||||
|
__constant struct Cols $2 = { border: 3, bg: 5 }
|
||||||
|
__constant struct Cols * const COLS = (struct Cols *)$d020
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
__constant char SIZEOF_STRUCT_COLS = 2
|
||||||
|
void __start()
|
||||||
|
void main()
|
||||||
|
struct Cols *main::$1
|
||||||
|
__loadstore volatile struct Cols main::a
|
||||||
|
__loadstore volatile struct Cols main::b
|
||||||
|
__loadstore volatile struct Cols main::c
|
||||||
|
struct Cols *main::m
|
||||||
|
struct Cols *main::m#0
|
||||||
|
struct Cols *main::m#1
|
||||||
|
__varcall struct Cols * min(struct Cols *a , struct Cols *b)
|
||||||
|
bool min::$0
|
||||||
|
char *min::$1
|
||||||
|
char *min::$2
|
||||||
|
char *min::$3
|
||||||
|
char *min::$4
|
||||||
|
__loadstore struct Cols *min::a
|
||||||
|
__loadstore struct Cols *min::b
|
||||||
|
__loadstore struct Cols *min::return
|
||||||
|
|
||||||
|
Simplifying constant pointer cast (struct Cols *) 53280
|
||||||
|
Successful SSA optimization PassNCastSimplification
|
||||||
|
Alias main::m#1 = main::$1
|
||||||
|
Successful SSA optimization Pass2AliasElimination
|
||||||
|
Simple Condition min::$0 [5] if(*min::$1<*min::$2) goto min::@1
|
||||||
|
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||||
|
Converting *(pointer+n) to pointer[n] [5] if(*min::$1<*min::$2) goto min::@1 -- min::$3[OFFSET_STRUCT_COLS_BG]
|
||||||
|
Converting *(pointer+n) to pointer[n] [5] if(min::$3[OFFSET_STRUCT_COLS_BG]<*min::$2) goto min::@1 -- min::$4[OFFSET_STRUCT_COLS_BG]
|
||||||
|
Successful SSA optimization Pass2InlineDerefIdx
|
||||||
|
Eliminating unused variable min::$1 and assignment [1] min::$1 = min::$3 + OFFSET_STRUCT_COLS_BG
|
||||||
|
Eliminating unused variable min::$2 and assignment [3] min::$2 = min::$4 + OFFSET_STRUCT_COLS_BG
|
||||||
|
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
|
||||||
|
Inlining Noop Cast [0] min::$3 = (char *)min::a keeping min::a
|
||||||
|
Inlining Noop Cast [1] min::$4 = (char *)min::b keeping min::b
|
||||||
|
Successful SSA optimization Pass2NopCastInlining
|
||||||
|
CALL GRAPH
|
||||||
|
Calls in [main] to min:5 min:10
|
||||||
|
|
||||||
|
Created 0 initial phi equivalence classes
|
||||||
|
Coalesced down to 0 phi equivalence classes
|
||||||
|
|
||||||
|
FINAL CONTROL FLOW GRAPH
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] *(&main::a) = memcpy(*(&$0), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
[1] *(&main::b) = memcpy(*(&$1), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
[2] *(&main::c) = memcpy(*(&$2), struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
[3] min::a = &main::a
|
||||||
|
[4] min::b = &main::b
|
||||||
|
[5] callexecute min
|
||||||
|
[6] main::m#0 = min::return
|
||||||
|
[7] *COLS = memcpy(*main::m#0, struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
[8] min::a = main::m#0
|
||||||
|
[9] min::b = &main::c
|
||||||
|
[10] callexecute min
|
||||||
|
[11] main::m#1 = min::return
|
||||||
|
[12] *COLS = memcpy(*main::m#1, struct Cols, SIZEOF_STRUCT_COLS)
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[13] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
__varcall struct Cols * min(struct Cols *a , struct Cols *b)
|
||||||
|
min: scope:[min] from
|
||||||
|
[14] if(((char *)min::a)[OFFSET_STRUCT_COLS_BG]<((char *)min::b)[OFFSET_STRUCT_COLS_BG]) goto min::@1
|
||||||
|
to:min::@2
|
||||||
|
min::@2: scope:[min] from min
|
||||||
|
[15] min::return = min::b
|
||||||
|
to:min::@return
|
||||||
|
min::@return: scope:[min] from min::@1 min::@2
|
||||||
|
[16] return
|
||||||
|
to:@return
|
||||||
|
min::@1: scope:[min] from min
|
||||||
|
[17] min::return = min::a
|
||||||
|
to:min::@return
|
||||||
|
|
||||||
|
|
||||||
|
VARIABLE REGISTER WEIGHTS
|
||||||
|
void main()
|
||||||
|
__loadstore volatile struct Cols main::a
|
||||||
|
__loadstore volatile struct Cols main::b
|
||||||
|
__loadstore volatile struct Cols main::c
|
||||||
|
struct Cols *main::m
|
||||||
|
struct Cols *main::m#0 // 2.0
|
||||||
|
struct Cols *main::m#1 // 2.0
|
||||||
|
__varcall struct Cols * min(struct Cols *a , struct Cols *b)
|
||||||
|
__loadstore struct Cols *min::a // 3.0
|
||||||
|
__loadstore struct Cols *min::b // 5.0
|
||||||
|
__loadstore struct Cols *min::return // 5.2
|
||||||
|
|
||||||
|
Initial phi equivalence classes
|
||||||
|
Added variable min::a to live range equivalence class [ min::a ]
|
||||||
|
Added variable min::b to live range equivalence class [ min::b ]
|
||||||
|
Added variable main::m#0 to live range equivalence class [ main::m#0 ]
|
||||||
|
Added variable main::m#1 to live range equivalence class [ main::m#1 ]
|
||||||
|
Added variable min::return to live range equivalence class [ min::return ]
|
||||||
|
Added variable main::a to live range equivalence class [ main::a ]
|
||||||
|
Added variable main::b to live range equivalence class [ main::b ]
|
||||||
|
Added variable main::c to live range equivalence class [ main::c ]
|
||||||
|
Complete equivalence classes
|
||||||
|
[ min::a ]
|
||||||
|
[ min::b ]
|
||||||
|
[ main::m#0 ]
|
||||||
|
[ main::m#1 ]
|
||||||
|
[ min::return ]
|
||||||
|
[ main::a ]
|
||||||
|
[ main::b ]
|
||||||
|
[ main::c ]
|
||||||
|
Allocated zp[2]:2 [ min::return ]
|
||||||
|
Allocated zp[2]:4 [ min::b ]
|
||||||
|
Allocated zp[2]:6 [ min::a ]
|
||||||
|
Allocated zp[2]:8 [ main::m#0 ]
|
||||||
|
Allocated zp[2]:10 [ main::m#1 ]
|
||||||
|
Allocated zp[2]:12 [ main::a ]
|
||||||
|
Allocated zp[2]:14 [ main::b ]
|
||||||
|
Allocated zp[2]:16 [ main::c ]
|
||||||
|
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||||
|
Statement [0] *(&main::a) = memcpy(*(&$0), struct Cols, SIZEOF_STRUCT_COLS) [ main::b main::c main::a ] ( [ main::b main::c main::a ] { } ) always clobbers reg byte a reg byte y
|
||||||
|
Statement [1] *(&main::b) = memcpy(*(&$1), struct Cols, SIZEOF_STRUCT_COLS) [ main::b main::c main::a ] ( [ main::b main::c main::a ] { } ) always clobbers reg byte a reg byte y
|
||||||
|
Statement [2] *(&main::c) = memcpy(*(&$2), struct Cols, SIZEOF_STRUCT_COLS) [ main::b main::c main::a ] ( [ main::b main::c main::a ] { } ) always clobbers reg byte a reg byte y
|
||||||
|
Statement [3] min::a = &main::a [ main::b main::c min::a ] ( [ main::b main::c min::a ] { } ) always clobbers reg byte a
|
||||||
|
Statement [4] min::b = &main::b [ main::c min::a min::b ] ( [ main::c min::a min::b ] { } ) always clobbers reg byte a
|
||||||
|
Statement [6] main::m#0 = min::return [ main::c main::m#0 ] ( [ main::c main::m#0 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [7] *COLS = memcpy(*main::m#0, struct Cols, SIZEOF_STRUCT_COLS) [ main::c main::m#0 ] ( [ main::c main::m#0 ] { } ) always clobbers reg byte a reg byte x reg byte y
|
||||||
|
Statement [8] min::a = main::m#0 [ main::c min::a ] ( [ main::c min::a ] { } ) always clobbers reg byte a
|
||||||
|
Statement [9] min::b = &main::c [ min::a min::b ] ( [ min::a min::b ] { } ) always clobbers reg byte a
|
||||||
|
Statement [11] main::m#1 = min::return [ main::m#1 ] ( [ main::m#1 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [12] *COLS = memcpy(*main::m#1, struct Cols, SIZEOF_STRUCT_COLS) [ ] ( [ ] { } ) always clobbers reg byte a reg byte x reg byte y
|
||||||
|
Statement [14] if(((char *)min::a)[OFFSET_STRUCT_COLS_BG]<((char *)min::b)[OFFSET_STRUCT_COLS_BG]) goto min::@1 [ min::a min::b ] ( min:5 [ main::c min::a min::b ] { { main::m#0 = min::a } } min:10 [ min::a min::b ] { { main::m#0 = min::a } } ) always clobbers reg byte a reg byte y
|
||||||
|
Statement [15] min::return = min::b [ min::return ] ( min:5 [ main::c min::return ] { { main::m#0 = min::a } } min:10 [ min::return ] { { main::m#0 = min::a } } ) always clobbers reg byte a
|
||||||
|
Statement [17] min::return = min::a [ min::return ] ( min:5 [ main::c min::return ] { { main::m#0 = min::a } } min:10 [ min::return ] { { main::m#0 = min::a } } ) always clobbers reg byte a
|
||||||
|
Potential registers zp[2]:6 [ min::a ] : zp[2]:6 ,
|
||||||
|
Potential registers zp[2]:4 [ min::b ] : zp[2]:4 ,
|
||||||
|
Potential registers zp[2]:8 [ main::m#0 ] : zp[2]:8 ,
|
||||||
|
Potential registers zp[2]:10 [ main::m#1 ] : zp[2]:10 ,
|
||||||
|
Potential registers zp[2]:2 [ min::return ] : zp[2]:2 ,
|
||||||
|
Potential registers zp[2]:12 [ main::a ] : zp[2]:12 ,
|
||||||
|
Potential registers zp[2]:14 [ main::b ] : zp[2]:14 ,
|
||||||
|
Potential registers zp[2]:16 [ main::c ] : zp[2]:16 ,
|
||||||
|
|
||||||
|
REGISTER UPLIFT SCOPES
|
||||||
|
Uplift Scope [min] 5.2: zp[2]:2 [ min::return ] 5: zp[2]:4 [ min::b ] 3: zp[2]:6 [ min::a ]
|
||||||
|
Uplift Scope [main] 2: zp[2]:8 [ main::m#0 ] 2: zp[2]:10 [ main::m#1 ] 0: zp[2]:12 [ main::a ] 0: zp[2]:14 [ main::b ] 0: zp[2]:16 [ main::c ]
|
||||||
|
Uplift Scope [Cols]
|
||||||
|
Uplift Scope []
|
||||||
|
|
||||||
|
Uplifting [min] best 231 combination zp[2]:2 [ min::return ] zp[2]:4 [ min::b ] zp[2]:6 [ min::a ]
|
||||||
|
Uplifting [main] best 231 combination zp[2]:8 [ main::m#0 ] zp[2]:10 [ main::m#1 ] zp[2]:12 [ main::a ] zp[2]:14 [ main::b ] zp[2]:16 [ main::c ]
|
||||||
|
Uplifting [Cols] best 231 combination
|
||||||
|
Uplifting [] best 231 combination
|
||||||
|
Coalescing zero page register [ zp[2]:6 [ min::a ] ] with [ zp[2]:8 [ main::m#0 ] ] - score: 1
|
||||||
|
Coalescing zero page register [ zp[2]:6 [ min::a main::m#0 ] ] with [ zp[2]:2 [ min::return ] ] - score: 1
|
||||||
|
Coalescing zero page register [ zp[2]:6 [ min::a main::m#0 min::return ] ] with [ zp[2]:10 [ main::m#1 ] ] - score: 1
|
||||||
|
Allocated (was zp[2]:6) zp[2]:2 [ min::a main::m#0 min::return main::m#1 ]
|
||||||
|
Allocated (was zp[2]:12) zp[2]:6 [ main::a ]
|
||||||
|
Allocated (was zp[2]:14) zp[2]:8 [ main::b ]
|
||||||
|
Allocated (was zp[2]:16) zp[2]:10 [ main::c ]
|
||||||
|
|
||||||
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
|
// File Comments
|
||||||
|
// Test __varcall calling convention
|
||||||
|
// Pointer to Struct parameter & return value
|
||||||
|
// Upstart
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-8.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
|
||||||
|
.const SIZEOF_STRUCT_COLS = 2
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
.label a = 6
|
||||||
|
.label b = 8
|
||||||
|
.label c = $a
|
||||||
|
.label m = 2
|
||||||
|
// [0] *(&main::a) = memcpy(*(&$0), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda __0-1,y
|
||||||
|
sta a-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// [1] *(&main::b) = memcpy(*(&$1), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda __1-1,y
|
||||||
|
sta b-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// [2] *(&main::c) = memcpy(*(&$2), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda __2-1,y
|
||||||
|
sta c-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// [3] min::a = &main::a -- pssz1=pssc1
|
||||||
|
lda #<a
|
||||||
|
sta.z min.a
|
||||||
|
lda #>a
|
||||||
|
sta.z min.a+1
|
||||||
|
// [4] min::b = &main::b -- pssz1=pssc1
|
||||||
|
lda #<b
|
||||||
|
sta.z min.b
|
||||||
|
lda #>b
|
||||||
|
sta.z min.b+1
|
||||||
|
// [5] callexecute min -- call_vprc1
|
||||||
|
jsr min
|
||||||
|
// [6] main::m#0 = min::return
|
||||||
|
// [7] *COLS = memcpy(*main::m#0, struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssz1_memcpy_vbuc2
|
||||||
|
ldx #SIZEOF_STRUCT_COLS
|
||||||
|
ldy #0
|
||||||
|
!:
|
||||||
|
lda (m),y
|
||||||
|
sta COLS,y
|
||||||
|
iny
|
||||||
|
dex
|
||||||
|
bne !-
|
||||||
|
// [8] min::a = main::m#0
|
||||||
|
// [9] min::b = &main::c -- pssz1=pssc1
|
||||||
|
lda #<c
|
||||||
|
sta.z min.b
|
||||||
|
lda #>c
|
||||||
|
sta.z min.b+1
|
||||||
|
// [10] callexecute min -- call_vprc1
|
||||||
|
jsr min
|
||||||
|
// [11] main::m#1 = min::return
|
||||||
|
// [12] *COLS = memcpy(*main::m#1, struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssz1_memcpy_vbuc2
|
||||||
|
ldx #SIZEOF_STRUCT_COLS
|
||||||
|
ldy #0
|
||||||
|
!:
|
||||||
|
lda (m),y
|
||||||
|
sta COLS,y
|
||||||
|
iny
|
||||||
|
dex
|
||||||
|
bne !-
|
||||||
|
jmp __breturn
|
||||||
|
// main::@return
|
||||||
|
__breturn:
|
||||||
|
// [13] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// min
|
||||||
|
// __zp(2) struct Cols * min(__zp(2) struct Cols *a, __zp(4) struct Cols *b)
|
||||||
|
min: {
|
||||||
|
.label a = 2
|
||||||
|
.label b = 4
|
||||||
|
.label return = 2
|
||||||
|
// [14] if(((char *)min::a)[OFFSET_STRUCT_COLS_BG]<((char *)min::b)[OFFSET_STRUCT_COLS_BG]) goto min::@1 -- pbuz1_derefidx_vbuc1_lt_pbuz2_derefidx_vbuc1_then_la1
|
||||||
|
ldy #OFFSET_STRUCT_COLS_BG
|
||||||
|
lda (b),y
|
||||||
|
cmp (a),y
|
||||||
|
bcc __b1
|
||||||
|
jmp __b2
|
||||||
|
// min::@2
|
||||||
|
__b2:
|
||||||
|
// [15] min::return = min::b -- pssz1=pssz2
|
||||||
|
lda.z b
|
||||||
|
sta.z return
|
||||||
|
lda.z b+1
|
||||||
|
sta.z return+1
|
||||||
|
jmp __breturn
|
||||||
|
// min::@return
|
||||||
|
__breturn:
|
||||||
|
// [16] return
|
||||||
|
rts
|
||||||
|
// min::@1
|
||||||
|
__b1:
|
||||||
|
// [17] min::return = min::a
|
||||||
|
jmp __breturn
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
.segment Data
|
||||||
|
__0: .byte 1, 7
|
||||||
|
__1: .byte 2, 6
|
||||||
|
__2: .byte 3, 5
|
||||||
|
|
||||||
|
ASSEMBLER OPTIMIZATIONS
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Removing instruction jmp __b2
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Succesful ASM optimization Pass5NextJumpElimination
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Removing instruction __b2:
|
||||||
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||||
|
Skipping double jump to __breturn in bcc __b1
|
||||||
|
Replacing jump to rts with rts in jmp __breturn
|
||||||
|
Succesful ASM optimization Pass5DoubleJumpElimination
|
||||||
|
Removing instruction __b1:
|
||||||
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||||
|
Removing unreachable instruction rts
|
||||||
|
Succesful ASM optimization Pass5UnreachableCodeElimination
|
||||||
|
|
||||||
|
FINAL SYMBOL TABLE
|
||||||
|
__constant struct Cols $0 = { border: 1, bg: 7 }
|
||||||
|
__constant struct Cols $1 = { border: 2, bg: 6 }
|
||||||
|
__constant struct Cols $2 = { border: 3, bg: 5 }
|
||||||
|
__constant struct Cols * const COLS = (struct Cols *) 53280
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
__constant char SIZEOF_STRUCT_COLS = 2
|
||||||
|
void main()
|
||||||
|
__loadstore volatile struct Cols main::a // zp[2]:6
|
||||||
|
__loadstore volatile struct Cols main::b // zp[2]:8
|
||||||
|
__loadstore volatile struct Cols main::c // zp[2]:10
|
||||||
|
struct Cols *main::m
|
||||||
|
struct Cols *main::m#0 // m zp[2]:2 2.0
|
||||||
|
struct Cols *main::m#1 // m zp[2]:2 2.0
|
||||||
|
__varcall struct Cols * min(struct Cols *a , struct Cols *b)
|
||||||
|
__loadstore struct Cols *min::a // zp[2]:2 3.0
|
||||||
|
__loadstore struct Cols *min::b // zp[2]:4 5.0
|
||||||
|
__loadstore struct Cols *min::return // zp[2]:2 5.2
|
||||||
|
|
||||||
|
zp[2]:2 [ min::a main::m#0 min::return main::m#1 ]
|
||||||
|
zp[2]:4 [ min::b ]
|
||||||
|
zp[2]:6 [ main::a ]
|
||||||
|
zp[2]:8 [ main::b ]
|
||||||
|
zp[2]:10 [ main::c ]
|
||||||
|
|
||||||
|
|
||||||
|
FINAL ASSEMBLER
|
||||||
|
Score: 171
|
||||||
|
|
||||||
|
// File Comments
|
||||||
|
// Test __varcall calling convention
|
||||||
|
// Pointer to Struct parameter & return value
|
||||||
|
// Upstart
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-8.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
|
||||||
|
.const SIZEOF_STRUCT_COLS = 2
|
||||||
|
.const OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
.label COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
.label a = 6
|
||||||
|
.label b = 8
|
||||||
|
.label c = $a
|
||||||
|
.label m = 2
|
||||||
|
// struct Cols a = { 1, 7 }
|
||||||
|
// [0] *(&main::a) = memcpy(*(&$0), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda __0-1,y
|
||||||
|
sta a-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// struct Cols b = { 2, 6 }
|
||||||
|
// [1] *(&main::b) = memcpy(*(&$1), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda __1-1,y
|
||||||
|
sta b-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// struct Cols c = { 3, 5 }
|
||||||
|
// [2] *(&main::c) = memcpy(*(&$2), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||||
|
ldy #SIZEOF_STRUCT_COLS
|
||||||
|
!:
|
||||||
|
lda __2-1,y
|
||||||
|
sta c-1,y
|
||||||
|
dey
|
||||||
|
bne !-
|
||||||
|
// struct Cols *m = min(&a,&b)
|
||||||
|
// [3] min::a = &main::a -- pssz1=pssc1
|
||||||
|
lda #<a
|
||||||
|
sta.z min.a
|
||||||
|
lda #>a
|
||||||
|
sta.z min.a+1
|
||||||
|
// [4] min::b = &main::b -- pssz1=pssc1
|
||||||
|
lda #<b
|
||||||
|
sta.z min.b
|
||||||
|
lda #>b
|
||||||
|
sta.z min.b+1
|
||||||
|
// [5] callexecute min -- call_vprc1
|
||||||
|
jsr min
|
||||||
|
// [6] main::m#0 = min::return
|
||||||
|
// *COLS = *m
|
||||||
|
// [7] *COLS = memcpy(*main::m#0, struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssz1_memcpy_vbuc2
|
||||||
|
ldx #SIZEOF_STRUCT_COLS
|
||||||
|
ldy #0
|
||||||
|
!:
|
||||||
|
lda (m),y
|
||||||
|
sta COLS,y
|
||||||
|
iny
|
||||||
|
dex
|
||||||
|
bne !-
|
||||||
|
// min(m,&c)
|
||||||
|
// [8] min::a = main::m#0
|
||||||
|
// [9] min::b = &main::c -- pssz1=pssc1
|
||||||
|
lda #<c
|
||||||
|
sta.z min.b
|
||||||
|
lda #>c
|
||||||
|
sta.z min.b+1
|
||||||
|
// [10] callexecute min -- call_vprc1
|
||||||
|
jsr min
|
||||||
|
// m = min(m,&c)
|
||||||
|
// [11] main::m#1 = min::return
|
||||||
|
// *COLS = *m
|
||||||
|
// [12] *COLS = memcpy(*main::m#1, struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssz1_memcpy_vbuc2
|
||||||
|
ldx #SIZEOF_STRUCT_COLS
|
||||||
|
ldy #0
|
||||||
|
!:
|
||||||
|
lda (m),y
|
||||||
|
sta COLS,y
|
||||||
|
iny
|
||||||
|
dex
|
||||||
|
bne !-
|
||||||
|
// main::@return
|
||||||
|
// }
|
||||||
|
// [13] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// min
|
||||||
|
// __zp(2) struct Cols * min(__zp(2) struct Cols *a, __zp(4) struct Cols *b)
|
||||||
|
min: {
|
||||||
|
.label a = 2
|
||||||
|
.label b = 4
|
||||||
|
.label return = 2
|
||||||
|
// if(a->bg < b->bg)
|
||||||
|
// [14] if(((char *)min::a)[OFFSET_STRUCT_COLS_BG]<((char *)min::b)[OFFSET_STRUCT_COLS_BG]) goto min::@1 -- pbuz1_derefidx_vbuc1_lt_pbuz2_derefidx_vbuc1_then_la1
|
||||||
|
ldy #OFFSET_STRUCT_COLS_BG
|
||||||
|
lda (b),y
|
||||||
|
cmp (a),y
|
||||||
|
bcc __breturn
|
||||||
|
// min::@2
|
||||||
|
// return b;
|
||||||
|
// [15] min::return = min::b -- pssz1=pssz2
|
||||||
|
lda.z b
|
||||||
|
sta.z return
|
||||||
|
lda.z b+1
|
||||||
|
sta.z return+1
|
||||||
|
// min::@return
|
||||||
|
__breturn:
|
||||||
|
// }
|
||||||
|
// [16] return
|
||||||
|
rts
|
||||||
|
// min::@1
|
||||||
|
// return a;
|
||||||
|
// [17] min::return = min::a
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
.segment Data
|
||||||
|
__0: .byte 1, 7
|
||||||
|
__1: .byte 2, 6
|
||||||
|
__2: .byte 3, 5
|
||||||
|
|
23
src/test/ref/varcall-8.sym
Normal file
23
src/test/ref/varcall-8.sym
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
__constant struct Cols $0 = { border: 1, bg: 7 }
|
||||||
|
__constant struct Cols $1 = { border: 2, bg: 6 }
|
||||||
|
__constant struct Cols $2 = { border: 3, bg: 5 }
|
||||||
|
__constant struct Cols * const COLS = (struct Cols *) 53280
|
||||||
|
__constant char OFFSET_STRUCT_COLS_BG = 1
|
||||||
|
__constant char SIZEOF_STRUCT_COLS = 2
|
||||||
|
void main()
|
||||||
|
__loadstore volatile struct Cols main::a // zp[2]:6
|
||||||
|
__loadstore volatile struct Cols main::b // zp[2]:8
|
||||||
|
__loadstore volatile struct Cols main::c // zp[2]:10
|
||||||
|
struct Cols *main::m
|
||||||
|
struct Cols *main::m#0 // m zp[2]:2 2.0
|
||||||
|
struct Cols *main::m#1 // m zp[2]:2 2.0
|
||||||
|
__varcall struct Cols * min(struct Cols *a , struct Cols *b)
|
||||||
|
__loadstore struct Cols *min::a // zp[2]:2 3.0
|
||||||
|
__loadstore struct Cols *min::b // zp[2]:4 5.0
|
||||||
|
__loadstore struct Cols *min::return // zp[2]:2 5.2
|
||||||
|
|
||||||
|
zp[2]:2 [ min::a main::m#0 min::return main::m#1 ]
|
||||||
|
zp[2]:4 [ min::b ]
|
||||||
|
zp[2]:6 [ main::a ]
|
||||||
|
zp[2]:8 [ main::b ]
|
||||||
|
zp[2]:10 [ main::c ]
|
108
src/test/ref/varcall-9.asm
Normal file
108
src/test/ref/varcall-9.asm
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct of struct parameter value
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-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 COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
main: {
|
||||||
|
.const a_normal_border = 1
|
||||||
|
.const a_normal_bg = 2
|
||||||
|
.const a_error_border = 3
|
||||||
|
.const a_error_bg = 4
|
||||||
|
.const b_normal_border = 5
|
||||||
|
.const b_normal_bg = 6
|
||||||
|
.const b_error_border = 7
|
||||||
|
.const b_error_bg = 8
|
||||||
|
.const c_normal_border = 9
|
||||||
|
.const c_normal_bg = $a
|
||||||
|
.const c_error_border = $b
|
||||||
|
.const c_error_bg = $c
|
||||||
|
// plus(a, b)
|
||||||
|
lda #a_normal_border
|
||||||
|
sta.z plus.a_normal_border
|
||||||
|
lda #a_normal_bg
|
||||||
|
sta.z plus.a_normal_bg
|
||||||
|
lda #a_error_border
|
||||||
|
sta.z plus.a_error_border
|
||||||
|
lda #a_error_bg
|
||||||
|
sta.z plus.a_error_bg
|
||||||
|
lda #b_normal_border
|
||||||
|
sta.z plus.b_normal_border
|
||||||
|
lda #b_normal_bg
|
||||||
|
sta.z plus.b_normal_bg
|
||||||
|
lda #b_error_border
|
||||||
|
sta.z plus.b_error_border
|
||||||
|
lda #b_error_bg
|
||||||
|
sta.z plus.b_error_bg
|
||||||
|
jsr plus
|
||||||
|
lda.z plus.return
|
||||||
|
// *COLS = plus(a, b)
|
||||||
|
sta COLS
|
||||||
|
// plus(b, c)
|
||||||
|
lda #b_normal_border
|
||||||
|
sta.z plus.a_normal_border
|
||||||
|
lda #b_normal_bg
|
||||||
|
sta.z plus.a_normal_bg
|
||||||
|
lda #b_error_border
|
||||||
|
sta.z plus.a_error_border
|
||||||
|
lda #b_error_bg
|
||||||
|
sta.z plus.a_error_bg
|
||||||
|
lda #c_normal_border
|
||||||
|
sta.z plus.b_normal_border
|
||||||
|
lda #c_normal_bg
|
||||||
|
sta.z plus.b_normal_bg
|
||||||
|
lda #c_error_border
|
||||||
|
sta.z plus.b_error_border
|
||||||
|
lda #c_error_bg
|
||||||
|
sta.z plus.b_error_bg
|
||||||
|
jsr plus
|
||||||
|
lda.z plus.return
|
||||||
|
// *COLS = plus(b, c)
|
||||||
|
sta COLS
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// __zp(2) char plus(__zp($a) char a_normal_border, __zp(7) char a_normal_bg, __zp(8) char a_error_border, __zp(9) char a_error_bg, __zp(3) char b_normal_border, __zp(4) char b_normal_bg, __zp(5) char b_error_border, __zp(6) char b_error_bg)
|
||||||
|
plus: {
|
||||||
|
.label return = 2
|
||||||
|
.label a_normal_border = $a
|
||||||
|
.label a_normal_bg = 7
|
||||||
|
.label a_error_border = 8
|
||||||
|
.label a_error_bg = 9
|
||||||
|
.label b_normal_border = 3
|
||||||
|
.label b_normal_bg = 4
|
||||||
|
.label b_error_border = 5
|
||||||
|
.label b_error_bg = 6
|
||||||
|
// a.normal.border + b.normal.border
|
||||||
|
lda.z a_normal_border
|
||||||
|
clc
|
||||||
|
adc.z b_normal_border
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg
|
||||||
|
clc
|
||||||
|
adc.z a_normal_bg
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg + b.normal.bg
|
||||||
|
clc
|
||||||
|
adc.z b_normal_bg
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border
|
||||||
|
clc
|
||||||
|
adc.z a_error_border
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border + b.error.border
|
||||||
|
clc
|
||||||
|
adc.z b_error_border
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border + b.error.border + a.error.bg
|
||||||
|
clc
|
||||||
|
adc.z a_error_bg
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border + b.error.border + a.error.bg + b.error.bg
|
||||||
|
clc
|
||||||
|
adc.z b_error_bg
|
||||||
|
// return a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border + b.error.border + a.error.bg + b.error.bg;
|
||||||
|
sta.z return
|
||||||
|
// }
|
||||||
|
rts
|
||||||
|
}
|
44
src/test/ref/varcall-9.cfg
Normal file
44
src/test/ref/varcall-9.cfg
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] plus::a_normal_border = main::a_normal_border
|
||||||
|
[1] plus::a_normal_bg = main::a_normal_bg
|
||||||
|
[2] plus::a_error_border = main::a_error_border
|
||||||
|
[3] plus::a_error_bg = main::a_error_bg
|
||||||
|
[4] plus::b_normal_border = main::b_normal_border
|
||||||
|
[5] plus::b_normal_bg = main::b_normal_bg
|
||||||
|
[6] plus::b_error_border = main::b_error_border
|
||||||
|
[7] plus::b_error_bg = main::b_error_bg
|
||||||
|
[8] callexecute plus
|
||||||
|
[9] main::$0 = plus::return
|
||||||
|
[10] *COLS = main::$0
|
||||||
|
[11] plus::a_normal_border = main::b_normal_border
|
||||||
|
[12] plus::a_normal_bg = main::b_normal_bg
|
||||||
|
[13] plus::a_error_border = main::b_error_border
|
||||||
|
[14] plus::a_error_bg = main::b_error_bg
|
||||||
|
[15] plus::b_normal_border = main::c_normal_border
|
||||||
|
[16] plus::b_normal_bg = main::c_normal_bg
|
||||||
|
[17] plus::b_error_border = main::c_error_border
|
||||||
|
[18] plus::b_error_bg = main::c_error_bg
|
||||||
|
[19] callexecute plus
|
||||||
|
[20] main::$1 = plus::return
|
||||||
|
[21] *COLS = main::$1
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[22] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
__varcall char plus(char a_normal_border , char a_normal_bg , char a_error_border , char a_error_bg , char b_normal_border , char b_normal_bg , char b_error_border , char b_error_bg)
|
||||||
|
plus: scope:[plus] from
|
||||||
|
[23] plus::$0 = plus::a_normal_border + plus::b_normal_border
|
||||||
|
[24] plus::$1 = plus::$0 + plus::a_normal_bg
|
||||||
|
[25] plus::$2 = plus::$1 + plus::b_normal_bg
|
||||||
|
[26] plus::$3 = plus::$2 + plus::a_error_border
|
||||||
|
[27] plus::$4 = plus::$3 + plus::b_error_border
|
||||||
|
[28] plus::$5 = plus::$4 + plus::a_error_bg
|
||||||
|
[29] plus::$6 = plus::$5 + plus::b_error_bg
|
||||||
|
[30] plus::return = plus::$6
|
||||||
|
to:plus::@return
|
||||||
|
plus::@return: scope:[plus] from plus
|
||||||
|
[31] return
|
||||||
|
to:@return
|
711
src/test/ref/varcall-9.log
Normal file
711
src/test/ref/varcall-9.log
Normal file
@ -0,0 +1,711 @@
|
|||||||
|
Converting parameter in __varcall procedure to load/store plus::a
|
||||||
|
Converting parameter in __varcall procedure to load/store plus::b
|
||||||
|
Converting return in __varcall procedure to load/store plus::return
|
||||||
|
Eliminating unused variable with no statement plus::a
|
||||||
|
Eliminating unused variable with no statement plus::b
|
||||||
|
Eliminating unused variable with no statement plus::a_normal
|
||||||
|
Eliminating unused variable with no statement plus::a_error
|
||||||
|
Eliminating unused variable with no statement plus::b_normal
|
||||||
|
Eliminating unused variable with no statement plus::b_error
|
||||||
|
Calling convention __varcall adding prepare/execute/finalize for main::$0 = call plus(main::a_normal_border, main::a_normal_bg, main::a_error_border, main::a_error_bg, main::b_normal_border, main::b_normal_bg, main::b_error_border, main::b_error_bg)
|
||||||
|
Calling convention __varcall adding prepare/execute/finalize for main::$1 = call plus(main::b_normal_border, main::b_normal_bg, main::b_error_border, main::b_error_bg, main::c_normal_border, main::c_normal_bg, main::c_error_border, main::c_error_bg)
|
||||||
|
Calling convention VAR_CALL adding return value assignment main::$0 = plus::return
|
||||||
|
Calling convention VAR_CALL adding return value assignment main::$1 = plus::return
|
||||||
|
|
||||||
|
CONTROL FLOW GRAPH SSA
|
||||||
|
|
||||||
|
__varcall char plus(char a_normal_border , char a_normal_bg , char a_error_border , char a_error_bg , char b_normal_border , char b_normal_bg , char b_error_border , char b_error_bg)
|
||||||
|
plus: scope:[plus] from
|
||||||
|
plus::$0 = plus::a_normal_border + plus::b_normal_border
|
||||||
|
plus::$1 = plus::$0 + plus::a_normal_bg
|
||||||
|
plus::$2 = plus::$1 + plus::b_normal_bg
|
||||||
|
plus::$3 = plus::$2 + plus::a_error_border
|
||||||
|
plus::$4 = plus::$3 + plus::b_error_border
|
||||||
|
plus::$5 = plus::$4 + plus::a_error_bg
|
||||||
|
plus::$6 = plus::$5 + plus::b_error_bg
|
||||||
|
plus::return = plus::$6
|
||||||
|
to:plus::@return
|
||||||
|
plus::@return: scope:[plus] from plus
|
||||||
|
return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from __start
|
||||||
|
plus::a_normal_border = main::a_normal_border
|
||||||
|
plus::a_normal_bg = main::a_normal_bg
|
||||||
|
plus::a_error_border = main::a_error_border
|
||||||
|
plus::a_error_bg = main::a_error_bg
|
||||||
|
plus::b_normal_border = main::b_normal_border
|
||||||
|
plus::b_normal_bg = main::b_normal_bg
|
||||||
|
plus::b_error_border = main::b_error_border
|
||||||
|
plus::b_error_bg = main::b_error_bg
|
||||||
|
callexecute plus
|
||||||
|
main::$0 = plus::return
|
||||||
|
*COLS = main::$0
|
||||||
|
plus::a_normal_border = main::b_normal_border
|
||||||
|
plus::a_normal_bg = main::b_normal_bg
|
||||||
|
plus::a_error_border = main::b_error_border
|
||||||
|
plus::a_error_bg = main::b_error_bg
|
||||||
|
plus::b_normal_border = main::c_normal_border
|
||||||
|
plus::b_normal_bg = main::c_normal_bg
|
||||||
|
plus::b_error_border = main::c_error_border
|
||||||
|
plus::b_error_bg = main::c_error_bg
|
||||||
|
callexecute plus
|
||||||
|
main::$1 = plus::return
|
||||||
|
*COLS = main::$1
|
||||||
|
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 * const COLS = (char *)$d020
|
||||||
|
void __start()
|
||||||
|
void main()
|
||||||
|
char main::$0
|
||||||
|
char main::$1
|
||||||
|
struct Col main::a_error
|
||||||
|
__constant char main::a_error_bg = 4
|
||||||
|
__constant char main::a_error_border = 3
|
||||||
|
struct Col main::a_normal
|
||||||
|
__constant char main::a_normal_bg = 2
|
||||||
|
__constant char main::a_normal_border = 1
|
||||||
|
struct Col main::b_error
|
||||||
|
__constant char main::b_error_bg = 8
|
||||||
|
__constant char main::b_error_border = 7
|
||||||
|
struct Col main::b_normal
|
||||||
|
__constant char main::b_normal_bg = 6
|
||||||
|
__constant char main::b_normal_border = 5
|
||||||
|
struct Col main::c_error
|
||||||
|
__constant char main::c_error_bg = $c
|
||||||
|
__constant char main::c_error_border = $b
|
||||||
|
struct Col main::c_normal
|
||||||
|
__constant char main::c_normal_bg = $a
|
||||||
|
__constant char main::c_normal_border = 9
|
||||||
|
__varcall char plus(char a_normal_border , char a_normal_bg , char a_error_border , char a_error_bg , char b_normal_border , char b_normal_bg , char b_error_border , char b_error_bg)
|
||||||
|
char plus::$0
|
||||||
|
char plus::$1
|
||||||
|
char plus::$2
|
||||||
|
char plus::$3
|
||||||
|
char plus::$4
|
||||||
|
char plus::$5
|
||||||
|
char plus::$6
|
||||||
|
__loadstore char plus::a_error_bg
|
||||||
|
__loadstore char plus::a_error_border
|
||||||
|
__loadstore char plus::a_normal_bg
|
||||||
|
__loadstore char plus::a_normal_border
|
||||||
|
__loadstore char plus::b_error_bg
|
||||||
|
__loadstore char plus::b_error_border
|
||||||
|
__loadstore char plus::b_normal_bg
|
||||||
|
__loadstore char plus::b_normal_border
|
||||||
|
__loadstore char plus::return
|
||||||
|
|
||||||
|
Simplifying constant pointer cast (char *) 53280
|
||||||
|
Successful SSA optimization PassNCastSimplification
|
||||||
|
Alias candidate removed (volatile)plus::return = plus::$6
|
||||||
|
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
|
||||||
|
Alias candidate removed (volatile)plus::return = plus::$6
|
||||||
|
Alias candidate removed (volatile)plus::return = plus::$6
|
||||||
|
Alias candidate removed (volatile)plus::return = plus::$6
|
||||||
|
CALL GRAPH
|
||||||
|
Calls in [main] to plus:8 plus:19
|
||||||
|
|
||||||
|
Created 0 initial phi equivalence classes
|
||||||
|
Coalesced down to 0 phi equivalence classes
|
||||||
|
|
||||||
|
FINAL CONTROL FLOW GRAPH
|
||||||
|
|
||||||
|
void main()
|
||||||
|
main: scope:[main] from
|
||||||
|
[0] plus::a_normal_border = main::a_normal_border
|
||||||
|
[1] plus::a_normal_bg = main::a_normal_bg
|
||||||
|
[2] plus::a_error_border = main::a_error_border
|
||||||
|
[3] plus::a_error_bg = main::a_error_bg
|
||||||
|
[4] plus::b_normal_border = main::b_normal_border
|
||||||
|
[5] plus::b_normal_bg = main::b_normal_bg
|
||||||
|
[6] plus::b_error_border = main::b_error_border
|
||||||
|
[7] plus::b_error_bg = main::b_error_bg
|
||||||
|
[8] callexecute plus
|
||||||
|
[9] main::$0 = plus::return
|
||||||
|
[10] *COLS = main::$0
|
||||||
|
[11] plus::a_normal_border = main::b_normal_border
|
||||||
|
[12] plus::a_normal_bg = main::b_normal_bg
|
||||||
|
[13] plus::a_error_border = main::b_error_border
|
||||||
|
[14] plus::a_error_bg = main::b_error_bg
|
||||||
|
[15] plus::b_normal_border = main::c_normal_border
|
||||||
|
[16] plus::b_normal_bg = main::c_normal_bg
|
||||||
|
[17] plus::b_error_border = main::c_error_border
|
||||||
|
[18] plus::b_error_bg = main::c_error_bg
|
||||||
|
[19] callexecute plus
|
||||||
|
[20] main::$1 = plus::return
|
||||||
|
[21] *COLS = main::$1
|
||||||
|
to:main::@return
|
||||||
|
main::@return: scope:[main] from main
|
||||||
|
[22] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
__varcall char plus(char a_normal_border , char a_normal_bg , char a_error_border , char a_error_bg , char b_normal_border , char b_normal_bg , char b_error_border , char b_error_bg)
|
||||||
|
plus: scope:[plus] from
|
||||||
|
[23] plus::$0 = plus::a_normal_border + plus::b_normal_border
|
||||||
|
[24] plus::$1 = plus::$0 + plus::a_normal_bg
|
||||||
|
[25] plus::$2 = plus::$1 + plus::b_normal_bg
|
||||||
|
[26] plus::$3 = plus::$2 + plus::a_error_border
|
||||||
|
[27] plus::$4 = plus::$3 + plus::b_error_border
|
||||||
|
[28] plus::$5 = plus::$4 + plus::a_error_bg
|
||||||
|
[29] plus::$6 = plus::$5 + plus::b_error_bg
|
||||||
|
[30] plus::return = plus::$6
|
||||||
|
to:plus::@return
|
||||||
|
plus::@return: scope:[plus] from plus
|
||||||
|
[31] return
|
||||||
|
to:@return
|
||||||
|
|
||||||
|
|
||||||
|
VARIABLE REGISTER WEIGHTS
|
||||||
|
void main()
|
||||||
|
char main::$0 // 4.0
|
||||||
|
char main::$1 // 4.0
|
||||||
|
struct Col main::a_error
|
||||||
|
struct Col main::a_normal
|
||||||
|
struct Col main::b_error
|
||||||
|
struct Col main::b_normal
|
||||||
|
struct Col main::c_error
|
||||||
|
struct Col main::c_normal
|
||||||
|
__varcall char plus(char a_normal_border , char a_normal_bg , char a_error_border , char a_error_bg , char b_normal_border , char b_normal_bg , char b_error_border , char b_error_bg)
|
||||||
|
char plus::$0 // 22.0
|
||||||
|
char plus::$1 // 22.0
|
||||||
|
char plus::$2 // 22.0
|
||||||
|
char plus::$3 // 22.0
|
||||||
|
char plus::$4 // 22.0
|
||||||
|
char plus::$5 // 22.0
|
||||||
|
char plus::$6 // 22.0
|
||||||
|
__loadstore char plus::a_error_bg // 1.0
|
||||||
|
__loadstore char plus::a_error_border // 1.0
|
||||||
|
__loadstore char plus::a_normal_bg // 1.0
|
||||||
|
__loadstore char plus::a_normal_border // 0.9375
|
||||||
|
__loadstore char plus::b_error_bg // 1.875
|
||||||
|
__loadstore char plus::b_error_border // 1.875
|
||||||
|
__loadstore char plus::b_normal_bg // 1.875
|
||||||
|
__loadstore char plus::b_normal_border // 1.875
|
||||||
|
__loadstore char plus::return // 3.75
|
||||||
|
|
||||||
|
Initial phi equivalence classes
|
||||||
|
Added variable plus::a_normal_border to live range equivalence class [ plus::a_normal_border ]
|
||||||
|
Added variable plus::a_normal_bg to live range equivalence class [ plus::a_normal_bg ]
|
||||||
|
Added variable plus::a_error_border to live range equivalence class [ plus::a_error_border ]
|
||||||
|
Added variable plus::a_error_bg to live range equivalence class [ plus::a_error_bg ]
|
||||||
|
Added variable plus::b_normal_border to live range equivalence class [ plus::b_normal_border ]
|
||||||
|
Added variable plus::b_normal_bg to live range equivalence class [ plus::b_normal_bg ]
|
||||||
|
Added variable plus::b_error_border to live range equivalence class [ plus::b_error_border ]
|
||||||
|
Added variable plus::b_error_bg to live range equivalence class [ plus::b_error_bg ]
|
||||||
|
Added variable main::$0 to live range equivalence class [ main::$0 ]
|
||||||
|
Added variable main::$1 to live range equivalence class [ main::$1 ]
|
||||||
|
Added variable plus::$0 to live range equivalence class [ plus::$0 ]
|
||||||
|
Added variable plus::$1 to live range equivalence class [ plus::$1 ]
|
||||||
|
Added variable plus::$2 to live range equivalence class [ plus::$2 ]
|
||||||
|
Added variable plus::$3 to live range equivalence class [ plus::$3 ]
|
||||||
|
Added variable plus::$4 to live range equivalence class [ plus::$4 ]
|
||||||
|
Added variable plus::$5 to live range equivalence class [ plus::$5 ]
|
||||||
|
Added variable plus::$6 to live range equivalence class [ plus::$6 ]
|
||||||
|
Added variable plus::return to live range equivalence class [ plus::return ]
|
||||||
|
Complete equivalence classes
|
||||||
|
[ plus::a_normal_border ]
|
||||||
|
[ plus::a_normal_bg ]
|
||||||
|
[ plus::a_error_border ]
|
||||||
|
[ plus::a_error_bg ]
|
||||||
|
[ plus::b_normal_border ]
|
||||||
|
[ plus::b_normal_bg ]
|
||||||
|
[ plus::b_error_border ]
|
||||||
|
[ plus::b_error_bg ]
|
||||||
|
[ main::$0 ]
|
||||||
|
[ main::$1 ]
|
||||||
|
[ plus::$0 ]
|
||||||
|
[ plus::$1 ]
|
||||||
|
[ plus::$2 ]
|
||||||
|
[ plus::$3 ]
|
||||||
|
[ plus::$4 ]
|
||||||
|
[ plus::$5 ]
|
||||||
|
[ plus::$6 ]
|
||||||
|
[ plus::return ]
|
||||||
|
Allocated zp[1]:2 [ plus::$0 ]
|
||||||
|
Allocated zp[1]:3 [ plus::$1 ]
|
||||||
|
Allocated zp[1]:4 [ plus::$2 ]
|
||||||
|
Allocated zp[1]:5 [ plus::$3 ]
|
||||||
|
Allocated zp[1]:6 [ plus::$4 ]
|
||||||
|
Allocated zp[1]:7 [ plus::$5 ]
|
||||||
|
Allocated zp[1]:8 [ plus::$6 ]
|
||||||
|
Allocated zp[1]:9 [ main::$0 ]
|
||||||
|
Allocated zp[1]:10 [ main::$1 ]
|
||||||
|
Allocated zp[1]:11 [ plus::return ]
|
||||||
|
Allocated zp[1]:12 [ plus::b_normal_border ]
|
||||||
|
Allocated zp[1]:13 [ plus::b_normal_bg ]
|
||||||
|
Allocated zp[1]:14 [ plus::b_error_border ]
|
||||||
|
Allocated zp[1]:15 [ plus::b_error_bg ]
|
||||||
|
Allocated zp[1]:16 [ plus::a_normal_bg ]
|
||||||
|
Allocated zp[1]:17 [ plus::a_error_border ]
|
||||||
|
Allocated zp[1]:18 [ plus::a_error_bg ]
|
||||||
|
Allocated zp[1]:19 [ plus::a_normal_border ]
|
||||||
|
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||||
|
Statement [0] plus::a_normal_border = main::a_normal_border [ plus::a_normal_border ] ( [ plus::a_normal_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [1] plus::a_normal_bg = main::a_normal_bg [ plus::a_normal_border plus::a_normal_bg ] ( [ plus::a_normal_border plus::a_normal_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [2] plus::a_error_border = main::a_error_border [ plus::a_normal_border plus::a_normal_bg plus::a_error_border ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [3] plus::a_error_bg = main::a_error_bg [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [4] plus::b_normal_border = main::b_normal_border [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [5] plus::b_normal_bg = main::b_normal_bg [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [6] plus::b_error_border = main::b_error_border [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg plus::b_error_border ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg plus::b_error_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [7] plus::b_error_bg = main::b_error_bg [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg plus::b_error_border plus::b_error_bg ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg plus::b_error_border plus::b_error_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [11] plus::a_normal_border = main::b_normal_border [ plus::a_normal_border ] ( [ plus::a_normal_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [12] plus::a_normal_bg = main::b_normal_bg [ plus::a_normal_border plus::a_normal_bg ] ( [ plus::a_normal_border plus::a_normal_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [13] plus::a_error_border = main::b_error_border [ plus::a_normal_border plus::a_normal_bg plus::a_error_border ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [14] plus::a_error_bg = main::b_error_bg [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [15] plus::b_normal_border = main::c_normal_border [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [16] plus::b_normal_bg = main::c_normal_bg [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [17] plus::b_error_border = main::c_error_border [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg plus::b_error_border ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg plus::b_error_border ] { } ) always clobbers reg byte a
|
||||||
|
Statement [18] plus::b_error_bg = main::c_error_bg [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg plus::b_error_border plus::b_error_bg ] ( [ plus::a_normal_border plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_border plus::b_normal_bg plus::b_error_border plus::b_error_bg ] { } ) always clobbers reg byte a
|
||||||
|
Statement [23] plus::$0 = plus::a_normal_border + plus::b_normal_border [ plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_bg plus::b_error_border plus::b_error_bg plus::$0 ] ( plus:8 [ plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_bg plus::b_error_border plus::b_error_bg plus::$0 ] { } plus:19 [ plus::a_normal_bg plus::a_error_border plus::a_error_bg plus::b_normal_bg plus::b_error_border plus::b_error_bg plus::$0 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [24] plus::$1 = plus::$0 + plus::a_normal_bg [ plus::a_error_border plus::a_error_bg plus::b_normal_bg plus::b_error_border plus::b_error_bg plus::$1 ] ( plus:8 [ plus::a_error_border plus::a_error_bg plus::b_normal_bg plus::b_error_border plus::b_error_bg plus::$1 ] { } plus:19 [ plus::a_error_border plus::a_error_bg plus::b_normal_bg plus::b_error_border plus::b_error_bg plus::$1 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [25] plus::$2 = plus::$1 + plus::b_normal_bg [ plus::a_error_border plus::a_error_bg plus::b_error_border plus::b_error_bg plus::$2 ] ( plus:8 [ plus::a_error_border plus::a_error_bg plus::b_error_border plus::b_error_bg plus::$2 ] { } plus:19 [ plus::a_error_border plus::a_error_bg plus::b_error_border plus::b_error_bg plus::$2 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [26] plus::$3 = plus::$2 + plus::a_error_border [ plus::a_error_bg plus::b_error_border plus::b_error_bg plus::$3 ] ( plus:8 [ plus::a_error_bg plus::b_error_border plus::b_error_bg plus::$3 ] { } plus:19 [ plus::a_error_bg plus::b_error_border plus::b_error_bg plus::$3 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [27] plus::$4 = plus::$3 + plus::b_error_border [ plus::a_error_bg plus::b_error_bg plus::$4 ] ( plus:8 [ plus::a_error_bg plus::b_error_bg plus::$4 ] { } plus:19 [ plus::a_error_bg plus::b_error_bg plus::$4 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [28] plus::$5 = plus::$4 + plus::a_error_bg [ plus::b_error_bg plus::$5 ] ( plus:8 [ plus::b_error_bg plus::$5 ] { } plus:19 [ plus::b_error_bg plus::$5 ] { } ) always clobbers reg byte a
|
||||||
|
Statement [29] plus::$6 = plus::$5 + plus::b_error_bg [ plus::$6 ] ( plus:8 [ plus::$6 ] { } plus:19 [ plus::$6 ] { } ) always clobbers reg byte a
|
||||||
|
Potential registers zp[1]:19 [ plus::a_normal_border ] : zp[1]:19 ,
|
||||||
|
Potential registers zp[1]:16 [ plus::a_normal_bg ] : zp[1]:16 ,
|
||||||
|
Potential registers zp[1]:17 [ plus::a_error_border ] : zp[1]:17 ,
|
||||||
|
Potential registers zp[1]:18 [ plus::a_error_bg ] : zp[1]:18 ,
|
||||||
|
Potential registers zp[1]:12 [ plus::b_normal_border ] : zp[1]:12 ,
|
||||||
|
Potential registers zp[1]:13 [ plus::b_normal_bg ] : zp[1]:13 ,
|
||||||
|
Potential registers zp[1]:14 [ plus::b_error_border ] : zp[1]:14 ,
|
||||||
|
Potential registers zp[1]:15 [ plus::b_error_bg ] : zp[1]:15 ,
|
||||||
|
Potential registers zp[1]:9 [ main::$0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:10 [ main::$1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:2 [ plus::$0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:3 [ plus::$1 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:4 [ plus::$2 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:5 [ plus::$3 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:6 [ plus::$4 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:7 [ plus::$5 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:8 [ plus::$6 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y ,
|
||||||
|
Potential registers zp[1]:11 [ plus::return ] : zp[1]:11 ,
|
||||||
|
|
||||||
|
REGISTER UPLIFT SCOPES
|
||||||
|
Uplift Scope [plus] 22: zp[1]:2 [ plus::$0 ] 22: zp[1]:3 [ plus::$1 ] 22: zp[1]:4 [ plus::$2 ] 22: zp[1]:5 [ plus::$3 ] 22: zp[1]:6 [ plus::$4 ] 22: zp[1]:7 [ plus::$5 ] 22: zp[1]:8 [ plus::$6 ] 3.75: zp[1]:11 [ plus::return ] 1.88: zp[1]:12 [ plus::b_normal_border ] 1.88: zp[1]:13 [ plus::b_normal_bg ] 1.88: zp[1]:14 [ plus::b_error_border ] 1.88: zp[1]:15 [ plus::b_error_bg ] 1: zp[1]:16 [ plus::a_normal_bg ] 1: zp[1]:17 [ plus::a_error_border ] 1: zp[1]:18 [ plus::a_error_bg ] 0.94: zp[1]:19 [ plus::a_normal_border ]
|
||||||
|
Uplift Scope [main] 4: zp[1]:9 [ main::$0 ] 4: zp[1]:10 [ main::$1 ]
|
||||||
|
Uplift Scope [Col]
|
||||||
|
Uplift Scope [Cols]
|
||||||
|
Uplift Scope []
|
||||||
|
|
||||||
|
Uplifting [plus] best 195 combination reg byte a [ plus::$0 ] reg byte a [ plus::$1 ] reg byte a [ plus::$2 ] reg byte a [ plus::$3 ] zp[1]:6 [ plus::$4 ] zp[1]:7 [ plus::$5 ] zp[1]:8 [ plus::$6 ] zp[1]:11 [ plus::return ] zp[1]:12 [ plus::b_normal_border ] zp[1]:13 [ plus::b_normal_bg ] zp[1]:14 [ plus::b_error_border ] zp[1]:15 [ plus::b_error_bg ] zp[1]:16 [ plus::a_normal_bg ] zp[1]:17 [ plus::a_error_border ] zp[1]:18 [ plus::a_error_bg ] zp[1]:19 [ plus::a_normal_border ]
|
||||||
|
Limited combination testing to 100 combinations of 16384 possible.
|
||||||
|
Uplifting [main] best 183 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ]
|
||||||
|
Uplifting [Col] best 183 combination
|
||||||
|
Uplifting [Cols] best 183 combination
|
||||||
|
Uplifting [] best 183 combination
|
||||||
|
Attempting to uplift remaining variables inzp[1]:6 [ plus::$4 ]
|
||||||
|
Uplifting [plus] best 177 combination reg byte a [ plus::$4 ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:7 [ plus::$5 ]
|
||||||
|
Uplifting [plus] best 171 combination reg byte a [ plus::$5 ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:8 [ plus::$6 ]
|
||||||
|
Uplifting [plus] best 165 combination reg byte a [ plus::$6 ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:11 [ plus::return ]
|
||||||
|
Uplifting [plus] best 165 combination zp[1]:11 [ plus::return ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:12 [ plus::b_normal_border ]
|
||||||
|
Uplifting [plus] best 165 combination zp[1]:12 [ plus::b_normal_border ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:13 [ plus::b_normal_bg ]
|
||||||
|
Uplifting [plus] best 165 combination zp[1]:13 [ plus::b_normal_bg ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:14 [ plus::b_error_border ]
|
||||||
|
Uplifting [plus] best 165 combination zp[1]:14 [ plus::b_error_border ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:15 [ plus::b_error_bg ]
|
||||||
|
Uplifting [plus] best 165 combination zp[1]:15 [ plus::b_error_bg ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:16 [ plus::a_normal_bg ]
|
||||||
|
Uplifting [plus] best 165 combination zp[1]:16 [ plus::a_normal_bg ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:17 [ plus::a_error_border ]
|
||||||
|
Uplifting [plus] best 165 combination zp[1]:17 [ plus::a_error_border ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:18 [ plus::a_error_bg ]
|
||||||
|
Uplifting [plus] best 165 combination zp[1]:18 [ plus::a_error_bg ]
|
||||||
|
Attempting to uplift remaining variables inzp[1]:19 [ plus::a_normal_border ]
|
||||||
|
Uplifting [plus] best 165 combination zp[1]:19 [ plus::a_normal_border ]
|
||||||
|
Allocated (was zp[1]:11) zp[1]:2 [ plus::return ]
|
||||||
|
Allocated (was zp[1]:12) zp[1]:3 [ plus::b_normal_border ]
|
||||||
|
Allocated (was zp[1]:13) zp[1]:4 [ plus::b_normal_bg ]
|
||||||
|
Allocated (was zp[1]:14) zp[1]:5 [ plus::b_error_border ]
|
||||||
|
Allocated (was zp[1]:15) zp[1]:6 [ plus::b_error_bg ]
|
||||||
|
Allocated (was zp[1]:16) zp[1]:7 [ plus::a_normal_bg ]
|
||||||
|
Allocated (was zp[1]:17) zp[1]:8 [ plus::a_error_border ]
|
||||||
|
Allocated (was zp[1]:18) zp[1]:9 [ plus::a_error_bg ]
|
||||||
|
Allocated (was zp[1]:19) zp[1]:10 [ plus::a_normal_border ]
|
||||||
|
|
||||||
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
|
// File Comments
|
||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct of struct parameter value
|
||||||
|
// Upstart
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-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 COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
.const a_normal_border = 1
|
||||||
|
.const a_normal_bg = 2
|
||||||
|
.const a_error_border = 3
|
||||||
|
.const a_error_bg = 4
|
||||||
|
.const b_normal_border = 5
|
||||||
|
.const b_normal_bg = 6
|
||||||
|
.const b_error_border = 7
|
||||||
|
.const b_error_bg = 8
|
||||||
|
.const c_normal_border = 9
|
||||||
|
.const c_normal_bg = $a
|
||||||
|
.const c_error_border = $b
|
||||||
|
.const c_error_bg = $c
|
||||||
|
// [0] plus::a_normal_border = main::a_normal_border -- vbuz1=vbuc1
|
||||||
|
lda #a_normal_border
|
||||||
|
sta.z plus.a_normal_border
|
||||||
|
// [1] plus::a_normal_bg = main::a_normal_bg -- vbuz1=vbuc1
|
||||||
|
lda #a_normal_bg
|
||||||
|
sta.z plus.a_normal_bg
|
||||||
|
// [2] plus::a_error_border = main::a_error_border -- vbuz1=vbuc1
|
||||||
|
lda #a_error_border
|
||||||
|
sta.z plus.a_error_border
|
||||||
|
// [3] plus::a_error_bg = main::a_error_bg -- vbuz1=vbuc1
|
||||||
|
lda #a_error_bg
|
||||||
|
sta.z plus.a_error_bg
|
||||||
|
// [4] plus::b_normal_border = main::b_normal_border -- vbuz1=vbuc1
|
||||||
|
lda #b_normal_border
|
||||||
|
sta.z plus.b_normal_border
|
||||||
|
// [5] plus::b_normal_bg = main::b_normal_bg -- vbuz1=vbuc1
|
||||||
|
lda #b_normal_bg
|
||||||
|
sta.z plus.b_normal_bg
|
||||||
|
// [6] plus::b_error_border = main::b_error_border -- vbuz1=vbuc1
|
||||||
|
lda #b_error_border
|
||||||
|
sta.z plus.b_error_border
|
||||||
|
// [7] plus::b_error_bg = main::b_error_bg -- vbuz1=vbuc1
|
||||||
|
lda #b_error_bg
|
||||||
|
sta.z plus.b_error_bg
|
||||||
|
// [8] callexecute plus -- call_vprc1
|
||||||
|
jsr plus
|
||||||
|
// [9] main::$0 = plus::return -- vbuaa=vbuz1
|
||||||
|
lda.z plus.return
|
||||||
|
// [10] *COLS = main::$0 -- _deref_pbuc1=vbuaa
|
||||||
|
sta COLS
|
||||||
|
// [11] plus::a_normal_border = main::b_normal_border -- vbuz1=vbuc1
|
||||||
|
lda #b_normal_border
|
||||||
|
sta.z plus.a_normal_border
|
||||||
|
// [12] plus::a_normal_bg = main::b_normal_bg -- vbuz1=vbuc1
|
||||||
|
lda #b_normal_bg
|
||||||
|
sta.z plus.a_normal_bg
|
||||||
|
// [13] plus::a_error_border = main::b_error_border -- vbuz1=vbuc1
|
||||||
|
lda #b_error_border
|
||||||
|
sta.z plus.a_error_border
|
||||||
|
// [14] plus::a_error_bg = main::b_error_bg -- vbuz1=vbuc1
|
||||||
|
lda #b_error_bg
|
||||||
|
sta.z plus.a_error_bg
|
||||||
|
// [15] plus::b_normal_border = main::c_normal_border -- vbuz1=vbuc1
|
||||||
|
lda #c_normal_border
|
||||||
|
sta.z plus.b_normal_border
|
||||||
|
// [16] plus::b_normal_bg = main::c_normal_bg -- vbuz1=vbuc1
|
||||||
|
lda #c_normal_bg
|
||||||
|
sta.z plus.b_normal_bg
|
||||||
|
// [17] plus::b_error_border = main::c_error_border -- vbuz1=vbuc1
|
||||||
|
lda #c_error_border
|
||||||
|
sta.z plus.b_error_border
|
||||||
|
// [18] plus::b_error_bg = main::c_error_bg -- vbuz1=vbuc1
|
||||||
|
lda #c_error_bg
|
||||||
|
sta.z plus.b_error_bg
|
||||||
|
// [19] callexecute plus -- call_vprc1
|
||||||
|
jsr plus
|
||||||
|
// [20] main::$1 = plus::return -- vbuaa=vbuz1
|
||||||
|
lda.z plus.return
|
||||||
|
// [21] *COLS = main::$1 -- _deref_pbuc1=vbuaa
|
||||||
|
sta COLS
|
||||||
|
jmp __breturn
|
||||||
|
// main::@return
|
||||||
|
__breturn:
|
||||||
|
// [22] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// plus
|
||||||
|
// __zp(2) char plus(__zp($a) char a_normal_border, __zp(7) char a_normal_bg, __zp(8) char a_error_border, __zp(9) char a_error_bg, __zp(3) char b_normal_border, __zp(4) char b_normal_bg, __zp(5) char b_error_border, __zp(6) char b_error_bg)
|
||||||
|
plus: {
|
||||||
|
.label return = 2
|
||||||
|
.label a_normal_border = $a
|
||||||
|
.label a_normal_bg = 7
|
||||||
|
.label a_error_border = 8
|
||||||
|
.label a_error_bg = 9
|
||||||
|
.label b_normal_border = 3
|
||||||
|
.label b_normal_bg = 4
|
||||||
|
.label b_error_border = 5
|
||||||
|
.label b_error_bg = 6
|
||||||
|
// [23] plus::$0 = plus::a_normal_border + plus::b_normal_border -- vbuaa=vbuz1_plus_vbuz2
|
||||||
|
lda.z a_normal_border
|
||||||
|
clc
|
||||||
|
adc.z b_normal_border
|
||||||
|
// [24] plus::$1 = plus::$0 + plus::a_normal_bg -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z a_normal_bg
|
||||||
|
// [25] plus::$2 = plus::$1 + plus::b_normal_bg -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z b_normal_bg
|
||||||
|
// [26] plus::$3 = plus::$2 + plus::a_error_border -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z a_error_border
|
||||||
|
// [27] plus::$4 = plus::$3 + plus::b_error_border -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z b_error_border
|
||||||
|
// [28] plus::$5 = plus::$4 + plus::a_error_bg -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z a_error_bg
|
||||||
|
// [29] plus::$6 = plus::$5 + plus::b_error_bg -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z b_error_bg
|
||||||
|
// [30] plus::return = plus::$6 -- vbuz1=vbuaa
|
||||||
|
sta.z return
|
||||||
|
jmp __breturn
|
||||||
|
// plus::@return
|
||||||
|
__breturn:
|
||||||
|
// [31] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
||||||
|
ASSEMBLER OPTIMIZATIONS
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Removing instruction jmp __breturn
|
||||||
|
Succesful ASM optimization Pass5NextJumpElimination
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Removing instruction __breturn:
|
||||||
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||||
|
|
||||||
|
FINAL SYMBOL TABLE
|
||||||
|
__constant char * const COLS = (char *) 53280
|
||||||
|
void main()
|
||||||
|
char main::$0 // reg byte a 4.0
|
||||||
|
char main::$1 // reg byte a 4.0
|
||||||
|
struct Col main::a_error
|
||||||
|
__constant char main::a_error_bg = 4
|
||||||
|
__constant char main::a_error_border = 3
|
||||||
|
struct Col main::a_normal
|
||||||
|
__constant char main::a_normal_bg = 2
|
||||||
|
__constant char main::a_normal_border = 1
|
||||||
|
struct Col main::b_error
|
||||||
|
__constant char main::b_error_bg = 8
|
||||||
|
__constant char main::b_error_border = 7
|
||||||
|
struct Col main::b_normal
|
||||||
|
__constant char main::b_normal_bg = 6
|
||||||
|
__constant char main::b_normal_border = 5
|
||||||
|
struct Col main::c_error
|
||||||
|
__constant char main::c_error_bg = $c
|
||||||
|
__constant char main::c_error_border = $b
|
||||||
|
struct Col main::c_normal
|
||||||
|
__constant char main::c_normal_bg = $a
|
||||||
|
__constant char main::c_normal_border = 9
|
||||||
|
__varcall char plus(char a_normal_border , char a_normal_bg , char a_error_border , char a_error_bg , char b_normal_border , char b_normal_bg , char b_error_border , char b_error_bg)
|
||||||
|
char plus::$0 // reg byte a 22.0
|
||||||
|
char plus::$1 // reg byte a 22.0
|
||||||
|
char plus::$2 // reg byte a 22.0
|
||||||
|
char plus::$3 // reg byte a 22.0
|
||||||
|
char plus::$4 // reg byte a 22.0
|
||||||
|
char plus::$5 // reg byte a 22.0
|
||||||
|
char plus::$6 // reg byte a 22.0
|
||||||
|
__loadstore char plus::a_error_bg // zp[1]:9 1.0
|
||||||
|
__loadstore char plus::a_error_border // zp[1]:8 1.0
|
||||||
|
__loadstore char plus::a_normal_bg // zp[1]:7 1.0
|
||||||
|
__loadstore char plus::a_normal_border // zp[1]:10 0.9375
|
||||||
|
__loadstore char plus::b_error_bg // zp[1]:6 1.875
|
||||||
|
__loadstore char plus::b_error_border // zp[1]:5 1.875
|
||||||
|
__loadstore char plus::b_normal_bg // zp[1]:4 1.875
|
||||||
|
__loadstore char plus::b_normal_border // zp[1]:3 1.875
|
||||||
|
__loadstore char plus::return // zp[1]:2 3.75
|
||||||
|
|
||||||
|
zp[1]:10 [ plus::a_normal_border ]
|
||||||
|
zp[1]:7 [ plus::a_normal_bg ]
|
||||||
|
zp[1]:8 [ plus::a_error_border ]
|
||||||
|
zp[1]:9 [ plus::a_error_bg ]
|
||||||
|
zp[1]:3 [ plus::b_normal_border ]
|
||||||
|
zp[1]:4 [ plus::b_normal_bg ]
|
||||||
|
zp[1]:5 [ plus::b_error_border ]
|
||||||
|
zp[1]:6 [ plus::b_error_bg ]
|
||||||
|
reg byte a [ main::$0 ]
|
||||||
|
reg byte a [ main::$1 ]
|
||||||
|
reg byte a [ plus::$0 ]
|
||||||
|
reg byte a [ plus::$1 ]
|
||||||
|
reg byte a [ plus::$2 ]
|
||||||
|
reg byte a [ plus::$3 ]
|
||||||
|
reg byte a [ plus::$4 ]
|
||||||
|
reg byte a [ plus::$5 ]
|
||||||
|
reg byte a [ plus::$6 ]
|
||||||
|
zp[1]:2 [ plus::return ]
|
||||||
|
|
||||||
|
|
||||||
|
FINAL ASSEMBLER
|
||||||
|
Score: 159
|
||||||
|
|
||||||
|
// File Comments
|
||||||
|
// Test __varcall calling convention
|
||||||
|
// Struct of struct parameter value
|
||||||
|
// Upstart
|
||||||
|
// Commodore 64 PRG executable file
|
||||||
|
.file [name="varcall-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 COLS = $d020
|
||||||
|
.segment Code
|
||||||
|
// main
|
||||||
|
main: {
|
||||||
|
.const a_normal_border = 1
|
||||||
|
.const a_normal_bg = 2
|
||||||
|
.const a_error_border = 3
|
||||||
|
.const a_error_bg = 4
|
||||||
|
.const b_normal_border = 5
|
||||||
|
.const b_normal_bg = 6
|
||||||
|
.const b_error_border = 7
|
||||||
|
.const b_error_bg = 8
|
||||||
|
.const c_normal_border = 9
|
||||||
|
.const c_normal_bg = $a
|
||||||
|
.const c_error_border = $b
|
||||||
|
.const c_error_bg = $c
|
||||||
|
// plus(a, b)
|
||||||
|
// [0] plus::a_normal_border = main::a_normal_border -- vbuz1=vbuc1
|
||||||
|
lda #a_normal_border
|
||||||
|
sta.z plus.a_normal_border
|
||||||
|
// [1] plus::a_normal_bg = main::a_normal_bg -- vbuz1=vbuc1
|
||||||
|
lda #a_normal_bg
|
||||||
|
sta.z plus.a_normal_bg
|
||||||
|
// [2] plus::a_error_border = main::a_error_border -- vbuz1=vbuc1
|
||||||
|
lda #a_error_border
|
||||||
|
sta.z plus.a_error_border
|
||||||
|
// [3] plus::a_error_bg = main::a_error_bg -- vbuz1=vbuc1
|
||||||
|
lda #a_error_bg
|
||||||
|
sta.z plus.a_error_bg
|
||||||
|
// [4] plus::b_normal_border = main::b_normal_border -- vbuz1=vbuc1
|
||||||
|
lda #b_normal_border
|
||||||
|
sta.z plus.b_normal_border
|
||||||
|
// [5] plus::b_normal_bg = main::b_normal_bg -- vbuz1=vbuc1
|
||||||
|
lda #b_normal_bg
|
||||||
|
sta.z plus.b_normal_bg
|
||||||
|
// [6] plus::b_error_border = main::b_error_border -- vbuz1=vbuc1
|
||||||
|
lda #b_error_border
|
||||||
|
sta.z plus.b_error_border
|
||||||
|
// [7] plus::b_error_bg = main::b_error_bg -- vbuz1=vbuc1
|
||||||
|
lda #b_error_bg
|
||||||
|
sta.z plus.b_error_bg
|
||||||
|
// [8] callexecute plus -- call_vprc1
|
||||||
|
jsr plus
|
||||||
|
// [9] main::$0 = plus::return -- vbuaa=vbuz1
|
||||||
|
lda.z plus.return
|
||||||
|
// *COLS = plus(a, b)
|
||||||
|
// [10] *COLS = main::$0 -- _deref_pbuc1=vbuaa
|
||||||
|
sta COLS
|
||||||
|
// plus(b, c)
|
||||||
|
// [11] plus::a_normal_border = main::b_normal_border -- vbuz1=vbuc1
|
||||||
|
lda #b_normal_border
|
||||||
|
sta.z plus.a_normal_border
|
||||||
|
// [12] plus::a_normal_bg = main::b_normal_bg -- vbuz1=vbuc1
|
||||||
|
lda #b_normal_bg
|
||||||
|
sta.z plus.a_normal_bg
|
||||||
|
// [13] plus::a_error_border = main::b_error_border -- vbuz1=vbuc1
|
||||||
|
lda #b_error_border
|
||||||
|
sta.z plus.a_error_border
|
||||||
|
// [14] plus::a_error_bg = main::b_error_bg -- vbuz1=vbuc1
|
||||||
|
lda #b_error_bg
|
||||||
|
sta.z plus.a_error_bg
|
||||||
|
// [15] plus::b_normal_border = main::c_normal_border -- vbuz1=vbuc1
|
||||||
|
lda #c_normal_border
|
||||||
|
sta.z plus.b_normal_border
|
||||||
|
// [16] plus::b_normal_bg = main::c_normal_bg -- vbuz1=vbuc1
|
||||||
|
lda #c_normal_bg
|
||||||
|
sta.z plus.b_normal_bg
|
||||||
|
// [17] plus::b_error_border = main::c_error_border -- vbuz1=vbuc1
|
||||||
|
lda #c_error_border
|
||||||
|
sta.z plus.b_error_border
|
||||||
|
// [18] plus::b_error_bg = main::c_error_bg -- vbuz1=vbuc1
|
||||||
|
lda #c_error_bg
|
||||||
|
sta.z plus.b_error_bg
|
||||||
|
// [19] callexecute plus -- call_vprc1
|
||||||
|
jsr plus
|
||||||
|
// [20] main::$1 = plus::return -- vbuaa=vbuz1
|
||||||
|
lda.z plus.return
|
||||||
|
// *COLS = plus(b, c)
|
||||||
|
// [21] *COLS = main::$1 -- _deref_pbuc1=vbuaa
|
||||||
|
sta COLS
|
||||||
|
// main::@return
|
||||||
|
// }
|
||||||
|
// [22] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// plus
|
||||||
|
// __zp(2) char plus(__zp($a) char a_normal_border, __zp(7) char a_normal_bg, __zp(8) char a_error_border, __zp(9) char a_error_bg, __zp(3) char b_normal_border, __zp(4) char b_normal_bg, __zp(5) char b_error_border, __zp(6) char b_error_bg)
|
||||||
|
plus: {
|
||||||
|
.label return = 2
|
||||||
|
.label a_normal_border = $a
|
||||||
|
.label a_normal_bg = 7
|
||||||
|
.label a_error_border = 8
|
||||||
|
.label a_error_bg = 9
|
||||||
|
.label b_normal_border = 3
|
||||||
|
.label b_normal_bg = 4
|
||||||
|
.label b_error_border = 5
|
||||||
|
.label b_error_bg = 6
|
||||||
|
// a.normal.border + b.normal.border
|
||||||
|
// [23] plus::$0 = plus::a_normal_border + plus::b_normal_border -- vbuaa=vbuz1_plus_vbuz2
|
||||||
|
lda.z a_normal_border
|
||||||
|
clc
|
||||||
|
adc.z b_normal_border
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg
|
||||||
|
// [24] plus::$1 = plus::$0 + plus::a_normal_bg -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z a_normal_bg
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg + b.normal.bg
|
||||||
|
// [25] plus::$2 = plus::$1 + plus::b_normal_bg -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z b_normal_bg
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border
|
||||||
|
// [26] plus::$3 = plus::$2 + plus::a_error_border -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z a_error_border
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border + b.error.border
|
||||||
|
// [27] plus::$4 = plus::$3 + plus::b_error_border -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z b_error_border
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border + b.error.border + a.error.bg
|
||||||
|
// [28] plus::$5 = plus::$4 + plus::a_error_bg -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z a_error_bg
|
||||||
|
// a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border + b.error.border + a.error.bg + b.error.bg
|
||||||
|
// [29] plus::$6 = plus::$5 + plus::b_error_bg -- vbuaa=vbuaa_plus_vbuz1
|
||||||
|
clc
|
||||||
|
adc.z b_error_bg
|
||||||
|
// return a.normal.border + b.normal.border + a.normal.bg + b.normal.bg + a.error.border + b.error.border + a.error.bg + b.error.bg;
|
||||||
|
// [30] plus::return = plus::$6 -- vbuz1=vbuaa
|
||||||
|
sta.z return
|
||||||
|
// plus::@return
|
||||||
|
// }
|
||||||
|
// [31] return
|
||||||
|
rts
|
||||||
|
}
|
||||||
|
// File Data
|
||||||
|
|
58
src/test/ref/varcall-9.sym
Normal file
58
src/test/ref/varcall-9.sym
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
__constant char * const COLS = (char *) 53280
|
||||||
|
void main()
|
||||||
|
char main::$0 // reg byte a 4.0
|
||||||
|
char main::$1 // reg byte a 4.0
|
||||||
|
struct Col main::a_error
|
||||||
|
__constant char main::a_error_bg = 4
|
||||||
|
__constant char main::a_error_border = 3
|
||||||
|
struct Col main::a_normal
|
||||||
|
__constant char main::a_normal_bg = 2
|
||||||
|
__constant char main::a_normal_border = 1
|
||||||
|
struct Col main::b_error
|
||||||
|
__constant char main::b_error_bg = 8
|
||||||
|
__constant char main::b_error_border = 7
|
||||||
|
struct Col main::b_normal
|
||||||
|
__constant char main::b_normal_bg = 6
|
||||||
|
__constant char main::b_normal_border = 5
|
||||||
|
struct Col main::c_error
|
||||||
|
__constant char main::c_error_bg = $c
|
||||||
|
__constant char main::c_error_border = $b
|
||||||
|
struct Col main::c_normal
|
||||||
|
__constant char main::c_normal_bg = $a
|
||||||
|
__constant char main::c_normal_border = 9
|
||||||
|
__varcall char plus(char a_normal_border , char a_normal_bg , char a_error_border , char a_error_bg , char b_normal_border , char b_normal_bg , char b_error_border , char b_error_bg)
|
||||||
|
char plus::$0 // reg byte a 22.0
|
||||||
|
char plus::$1 // reg byte a 22.0
|
||||||
|
char plus::$2 // reg byte a 22.0
|
||||||
|
char plus::$3 // reg byte a 22.0
|
||||||
|
char plus::$4 // reg byte a 22.0
|
||||||
|
char plus::$5 // reg byte a 22.0
|
||||||
|
char plus::$6 // reg byte a 22.0
|
||||||
|
__loadstore char plus::a_error_bg // zp[1]:9 1.0
|
||||||
|
__loadstore char plus::a_error_border // zp[1]:8 1.0
|
||||||
|
__loadstore char plus::a_normal_bg // zp[1]:7 1.0
|
||||||
|
__loadstore char plus::a_normal_border // zp[1]:10 0.9375
|
||||||
|
__loadstore char plus::b_error_bg // zp[1]:6 1.875
|
||||||
|
__loadstore char plus::b_error_border // zp[1]:5 1.875
|
||||||
|
__loadstore char plus::b_normal_bg // zp[1]:4 1.875
|
||||||
|
__loadstore char plus::b_normal_border // zp[1]:3 1.875
|
||||||
|
__loadstore char plus::return // zp[1]:2 3.75
|
||||||
|
|
||||||
|
zp[1]:10 [ plus::a_normal_border ]
|
||||||
|
zp[1]:7 [ plus::a_normal_bg ]
|
||||||
|
zp[1]:8 [ plus::a_error_border ]
|
||||||
|
zp[1]:9 [ plus::a_error_bg ]
|
||||||
|
zp[1]:3 [ plus::b_normal_border ]
|
||||||
|
zp[1]:4 [ plus::b_normal_bg ]
|
||||||
|
zp[1]:5 [ plus::b_error_border ]
|
||||||
|
zp[1]:6 [ plus::b_error_bg ]
|
||||||
|
reg byte a [ main::$0 ]
|
||||||
|
reg byte a [ main::$1 ]
|
||||||
|
reg byte a [ plus::$0 ]
|
||||||
|
reg byte a [ plus::$1 ]
|
||||||
|
reg byte a [ plus::$2 ]
|
||||||
|
reg byte a [ plus::$3 ]
|
||||||
|
reg byte a [ plus::$4 ]
|
||||||
|
reg byte a [ plus::$5 ]
|
||||||
|
reg byte a [ plus::$6 ]
|
||||||
|
zp[1]:2 [ plus::return ]
|
Loading…
Reference in New Issue
Block a user