mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-29 05:31:11 +00:00
parent
fa937d4874
commit
29633a2479
@ -312,6 +312,9 @@ public class Compiler {
|
||||
new Pass1CallPhiReturn(program).execute();
|
||||
new PassNUnwindLValueLists(program).execute();
|
||||
|
||||
new Pass1UnwindStructValues(program).execute();
|
||||
|
||||
|
||||
getLog().append("\nCONTROL FLOW GRAPH SSA");
|
||||
getLog().append(program.getGraph().toString(program));
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package dk.camelot64.kickc.model;
|
||||
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.StatementSource;
|
||||
import dk.camelot64.kickc.model.symbols.ArraySpec;
|
||||
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
||||
@ -92,7 +91,7 @@ public class Initializers {
|
||||
}
|
||||
} else if(initValue instanceof ValueList) {
|
||||
ValueList initList = (ValueList) initValue;
|
||||
if(typeSpec.getType() instanceof SymbolTypePointer && ((SymbolTypePointer)typeSpec.getType()).getArraySpec() != null) {
|
||||
if(typeSpec.getType() instanceof SymbolTypePointer && ((SymbolTypePointer) typeSpec.getType()).getArraySpec() != null) {
|
||||
// Type is an array
|
||||
initValue = constantifyArray(initList, (SymbolTypePointer) typeSpec.getType(), program, source);
|
||||
} else if(typeSpec.getType() instanceof SymbolTypeStruct) {
|
||||
@ -107,7 +106,7 @@ public class Initializers {
|
||||
if(typeSpec.getType() instanceof SymbolTypeIntegerFixed) {
|
||||
SymbolTypeIntegerFixed typeIntegerFixed = (SymbolTypeIntegerFixed) typeSpec.getType();
|
||||
if(!typeIntegerFixed.contains(integer)) {
|
||||
throw new CompileError( "Constant init-value has a non-matching type \n type: " + typeSpec.getType().toString() +"\n value: " + initValue.toString(), source);
|
||||
throw new CompileError("Constant init-value has a non-matching type \n type: " + typeSpec.getType().toString() + "\n value: " + initValue.toString(), source);
|
||||
}
|
||||
}
|
||||
initValue = new ConstantInteger(integer, typeSpec.getType());
|
||||
@ -141,13 +140,21 @@ public class Initializers {
|
||||
// Recursively cast all sub-elements
|
||||
StructDefinition structDefinition = structType.getStructDefinition(program.getScope());
|
||||
Collection<Variable> memberDefinitions = structDefinition.getAllVars(false);
|
||||
int structInitNeedSize = structDefinition.isUnion()? 1 : memberDefinitions.size() ;
|
||||
int structInitNeedSize = structDefinition.isUnion() ? 1 : memberDefinitions.size();
|
||||
if(structInitNeedSize != valueList.getList().size()) {
|
||||
throw new CompileError(
|
||||
"Struct initializer has wrong size (" + valueList.getList().size() + "), " +
|
||||
"which does not match the number of members in " + structType.getTypeName() + " (" + structInitNeedSize + " members).\n" +
|
||||
" Struct initializer: " + valueList.toString(program),
|
||||
source);
|
||||
if(structDefinition.isUnion()) {
|
||||
throw new CompileError(
|
||||
"Union initializer has too many values, since only one is allowed.\n" +
|
||||
" Union initializer: " + valueList.toString(program),
|
||||
source);
|
||||
} else {
|
||||
throw new CompileError(
|
||||
"Struct initializer has wrong size (" + valueList.getList().size() + "), " +
|
||||
"which does not match the number of members in " + structType.getTypeName() + " (" + structInitNeedSize + " members).\n" +
|
||||
" Struct initializer: " + valueList.toString(program),
|
||||
source);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
boolean allConst = true;
|
||||
|
@ -505,10 +505,12 @@ public class Variable implements Symbol {
|
||||
* @return true if an unwinding struct
|
||||
*/
|
||||
public boolean isStructUnwind() {
|
||||
if(getType() instanceof SymbolTypeStruct)
|
||||
return isKindPhiMaster() || isKindIntermediate() || isKindPhiVersion();
|
||||
else
|
||||
return false;
|
||||
if(getType() instanceof SymbolTypeStruct) {
|
||||
final SymbolTypeStruct typeStruct = (SymbolTypeStruct) getType();
|
||||
if(!typeStruct.isUnion())
|
||||
return isKindPhiMaster() || isKindIntermediate() || isKindPhiVersion();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -517,7 +519,15 @@ public class Variable implements Symbol {
|
||||
* @return true if an classic struct
|
||||
*/
|
||||
public boolean isStructClassic() {
|
||||
return getType() instanceof SymbolTypeStruct && isKindLoadStore();
|
||||
|
||||
if(getType() instanceof SymbolTypeStruct) {
|
||||
final SymbolTypeStruct typeStruct = (SymbolTypeStruct) getType();
|
||||
if(typeStruct.isUnion())
|
||||
return true;
|
||||
if(isKindLoadStore())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDeclarationOnly() {
|
||||
|
@ -98,7 +98,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
Variable procReturnVar = procedure.getLocalVariable("return");
|
||||
// TODO: Return-variable has been unwound - detect that instead - use getProgram().getStructVariableMemberUnwinding().getUnwindingMaster() like for parameters
|
||||
if(procReturnVar != null && procReturnVar.isStructUnwind()) {
|
||||
if(!(call.getlValue() instanceof ValueList)) {
|
||||
if(call.getlValue()!=null && !(call.getlValue() instanceof ValueList)) {
|
||||
// Return value already unwound - move on
|
||||
final ValueSource valueSource = ValueSourceFactory.getValueSource(call.getlValue(), getProgram(), getScope(), call, stmtIt, currentBlock);
|
||||
RValue unwoundLValue = unwindValue(valueSource, call, stmtIt, currentBlock);
|
||||
@ -118,30 +118,32 @@ public class Pass1UnwindStructValues extends Pass1Base {
|
||||
boolean anyParameterUnwound = false;
|
||||
final List<Variable> procParameters = procedure.getParameters();
|
||||
final List<RValue> callParameters = call.getParameters();
|
||||
for(int idx_call = 0, idx_proc = 0; idx_call < callParameters.size(); idx_call++) {
|
||||
final RValue callParameter = callParameters.get(idx_call);
|
||||
final Variable procParameter = procParameters.get(idx_proc);
|
||||
boolean unwound = false;
|
||||
final SymbolVariableRef unwindingMaster = getProgram().getStructVariableMemberUnwinding().getUnwindingMaster(procParameter.getRef());
|
||||
if(unwindingMaster != null) {
|
||||
// The procedure parameter is unwound
|
||||
final ValueSource parameterSource = ValueSourceFactory.getValueSource(callParameter, getProgram(), getScope(), call, stmtIt, currentBlock);
|
||||
if(parameterSource != null && parameterSource.isUnwindable())
|
||||
// Passing an unwinding struct value
|
||||
for(String memberName : parameterSource.getMemberNames(getScope())) {
|
||||
ValueSource memberUnwinding = parameterSource.getMemberUnwinding(memberName, getProgram(), getScope(), call, stmtIt, currentBlock);
|
||||
unwoundParameters.add(memberUnwinding.getSimpleValue(getScope()));
|
||||
unwound = true;
|
||||
anyParameterUnwound = true;
|
||||
if(callParameters!=null && callParameters.size()>0 ){
|
||||
for(int idx_call = 0, idx_proc = 0; idx_call < callParameters.size(); idx_call++) {
|
||||
final RValue callParameter = callParameters.get(idx_call);
|
||||
final Variable procParameter = procParameters.get(idx_proc);
|
||||
boolean unwound = false;
|
||||
final SymbolVariableRef unwindingMaster = getProgram().getStructVariableMemberUnwinding().getUnwindingMaster(procParameter.getRef());
|
||||
if(unwindingMaster != null) {
|
||||
// The procedure parameter is unwound
|
||||
final ValueSource parameterSource = ValueSourceFactory.getValueSource(callParameter, getProgram(), getScope(), call, stmtIt, currentBlock);
|
||||
if(parameterSource != null && parameterSource.isUnwindable())
|
||||
// Passing an unwinding struct value
|
||||
for(String memberName : parameterSource.getMemberNames(getScope())) {
|
||||
ValueSource memberUnwinding = parameterSource.getMemberUnwinding(memberName, getProgram(), getScope(), call, stmtIt, currentBlock);
|
||||
unwoundParameters.add(memberUnwinding.getSimpleValue(getScope()));
|
||||
unwound = true;
|
||||
anyParameterUnwound = true;
|
||||
idx_proc++;
|
||||
}
|
||||
else
|
||||
idx_proc++;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
idx_proc++;
|
||||
} else {
|
||||
idx_proc++;
|
||||
}
|
||||
if(!unwound) {
|
||||
unwoundParameters.add(callParameter);
|
||||
}
|
||||
if(!unwound) {
|
||||
unwoundParameters.add(callParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.StatementCallFinalize;
|
||||
import dk.camelot64.kickc.model.symbols.StructDefinition;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.ValueList;
|
||||
@ -59,6 +60,8 @@ public class Pass4LiveRangeEquivalenceClassesFinalize extends Pass2Base {
|
||||
|
||||
// Add any load/store variables with an initializer - and load/store struct variables
|
||||
for(Variable variable : getSymbols().getAllVariables(true)) {
|
||||
if(variable.getScope() instanceof StructDefinition)
|
||||
continue;
|
||||
if(variable.isKindLoadStore() && variable.getInitValue()!=null)
|
||||
addToEquivalenceClassSet(variable.getVariableRef(), new ArrayList<>(), liveRangeEquivalenceClassSet);
|
||||
else if(variable.isStructClassic())
|
||||
|
@ -221,12 +221,16 @@ public class TestProgramsFast extends TestPrograms {
|
||||
compileAndCompare("struct-unwinding-1.c");
|
||||
}
|
||||
|
||||
// TODO: Fix __varcall returning structs
|
||||
//@Test
|
||||
//public void testVarCall4() throws IOException {
|
||||
// compileAndCompare("varcall-4.c", log().verboseStructUnwind().verboseCreateSsa());
|
||||
//public void testVarCall5() throws IOException {
|
||||
// compileAndCompare("varcall-5.c", log().verboseCreateSsa().verboseStructUnwind());
|
||||
//}
|
||||
|
||||
@Test
|
||||
public void testVarCall4() throws IOException {
|
||||
compileAndCompare("varcall-4.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarCall3() throws IOException {
|
||||
compileAndCompare("varcall-3.c");
|
||||
@ -2223,6 +2227,11 @@ public class TestProgramsFast extends TestPrograms {
|
||||
compileAndCompare("struct-directives.c");
|
||||
}
|
||||
|
||||
//@Test
|
||||
//public void testUnion7() throws IOException {
|
||||
// compileAndCompare("union-7.c", log().verboseStructUnwind());
|
||||
//}
|
||||
|
||||
@Test
|
||||
public void testUnion6() throws IOException {
|
||||
compileAndCompare("union-6.c");
|
||||
@ -2814,7 +2823,7 @@ public class TestProgramsFast extends TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testTypeIdPlusBytes() throws IOException {
|
||||
compileAndCompare("typeid-plus-bytes.c", log());
|
||||
compileAndCompare("typeid-plus-bytes.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
23
src/test/kc/union-7.c
Normal file
23
src/test/kc/union-7.c
Normal file
@ -0,0 +1,23 @@
|
||||
// Minimal union with C-Standard behavior - union parameter
|
||||
|
||||
union Data {
|
||||
unsigned char b;
|
||||
unsigned int w;
|
||||
};
|
||||
|
||||
union Data data1 = { 0x12 };
|
||||
union Data data2 = { 0x34 };
|
||||
|
||||
void main() {
|
||||
print(data1);
|
||||
print(data2);
|
||||
}
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
char idx = 0;
|
||||
|
||||
void print(union Data data) {
|
||||
SCREEN[idx++] = BYTE1(data.w);
|
||||
SCREEN[idx++] = data.b;
|
||||
SCREEN[idx++] = ' ';
|
||||
}
|
@ -1,22 +1,27 @@
|
||||
// Test __varcall calling convention
|
||||
// Struct parameter & return value
|
||||
// Struct parameter
|
||||
|
||||
struct Cols {
|
||||
char border;
|
||||
char bg;
|
||||
char fg;
|
||||
};
|
||||
|
||||
struct Cols * const COLS = (struct Cols *)0xd020;
|
||||
char * const COLS = (char *)0xd020;
|
||||
|
||||
struct Cols a = { 1, 2, 3 };
|
||||
struct Cols b = { 3, 4, 6 };
|
||||
struct Cols c = { 5, 6, 7 };
|
||||
struct Cols d;
|
||||
|
||||
void main() {
|
||||
struct Cols a = { 1, 2 };
|
||||
//*COLS = a;
|
||||
a = plus(a, { 2, 3 } );
|
||||
*COLS = a;
|
||||
//a = plus(a, a);
|
||||
//*COLS = a;
|
||||
char sum1 = fg_sum(a, b);
|
||||
*COLS = sum1;
|
||||
d = b;
|
||||
char sum2 = fg_sum(c, d);
|
||||
*COLS = sum2;
|
||||
}
|
||||
|
||||
__varcall struct Cols plus(struct Cols a, struct Cols b) {
|
||||
return { a.border+b.border, a.bg+b.bg };
|
||||
__varcall char fg_sum(struct Cols a, struct Cols b) {
|
||||
return a.fg+b.fg;
|
||||
}
|
22
src/test/kc/varcall-5.c
Normal file
22
src/test/kc/varcall-5.c
Normal file
@ -0,0 +1,22 @@
|
||||
// Test __varcall calling convention
|
||||
// Struct return value
|
||||
|
||||
struct Cols {
|
||||
char border;
|
||||
char bg;
|
||||
};
|
||||
|
||||
struct Cols * const COLS = (struct Cols *)0xd020;
|
||||
|
||||
struct Cols a;
|
||||
|
||||
void main() {
|
||||
a = make(1);
|
||||
*COLS = a;
|
||||
a = make(2);
|
||||
*COLS = a;
|
||||
}
|
||||
|
||||
__varcall struct Cols make(char v) {
|
||||
return { v, v+v };
|
||||
}
|
22
src/test/kc/varcall-6.c
Normal file
22
src/test/kc/varcall-6.c
Normal file
@ -0,0 +1,22 @@
|
||||
// Test __varcall calling convention
|
||||
// Struct parameter & return value
|
||||
|
||||
struct Cols {
|
||||
char border;
|
||||
char bg;
|
||||
};
|
||||
|
||||
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) {
|
||||
return { a.border+b.border, a.bg+b.bg };
|
||||
}
|
80
src/test/ref/varcall-4.asm
Normal file
80
src/test/ref/varcall-4.asm
Normal file
@ -0,0 +1,80 @@
|
||||
// Test __varcall calling convention
|
||||
// Struct parameter
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="varcall-4.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 = 3
|
||||
.const OFFSET_STRUCT_COLS_FG = 2
|
||||
.label COLS = $d020
|
||||
.segment Code
|
||||
// fg_sum(struct Cols zp(3) a, struct Cols zp(6) b)
|
||||
fg_sum: {
|
||||
.label a = 3
|
||||
.label b = 6
|
||||
.label return = 2
|
||||
// a.fg+b.fg
|
||||
lda a+OFFSET_STRUCT_COLS_FG
|
||||
clc
|
||||
adc b+OFFSET_STRUCT_COLS_FG
|
||||
// return a.fg+b.fg;
|
||||
sta.z return
|
||||
// }
|
||||
rts
|
||||
}
|
||||
main: {
|
||||
// fg_sum(a, b)
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda a-1,y
|
||||
sta fg_sum.a-1,y
|
||||
dey
|
||||
bne !-
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda b-1,y
|
||||
sta fg_sum.b-1,y
|
||||
dey
|
||||
bne !-
|
||||
jsr fg_sum
|
||||
// char sum1 = fg_sum(a, b)
|
||||
lda.z fg_sum.return
|
||||
// *COLS = sum1
|
||||
sta COLS
|
||||
// d = b
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda b-1,y
|
||||
sta d-1,y
|
||||
dey
|
||||
bne !-
|
||||
// fg_sum(c, d)
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda c-1,y
|
||||
sta fg_sum.a-1,y
|
||||
dey
|
||||
bne !-
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda d-1,y
|
||||
sta fg_sum.b-1,y
|
||||
dey
|
||||
bne !-
|
||||
jsr fg_sum
|
||||
// char sum2 = fg_sum(c, d)
|
||||
lda.z fg_sum.return
|
||||
// *COLS = sum2
|
||||
sta COLS
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment Data
|
||||
a: .byte 1, 2, 3
|
||||
b: .byte 3, 4, 6
|
||||
c: .byte 5, 6, 7
|
||||
d: .fill SIZEOF_STRUCT_COLS, 0
|
27
src/test/ref/varcall-4.cfg
Normal file
27
src/test/ref/varcall-4.cfg
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
__varcall byte fg_sum(struct Cols fg_sum::a , struct Cols fg_sum::b)
|
||||
fg_sum: scope:[fg_sum] from
|
||||
[0] fg_sum::$0 = *((byte*)&fg_sum::a+OFFSET_STRUCT_COLS_FG) + *((byte*)&fg_sum::b+OFFSET_STRUCT_COLS_FG)
|
||||
[1] fg_sum::return = fg_sum::$0
|
||||
to:fg_sum::@return
|
||||
fg_sum::@return: scope:[fg_sum] from fg_sum
|
||||
[2] return
|
||||
to:@return
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[3] *(&fg_sum::a) = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
[4] *(&fg_sum::b) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
[5] callexecute fg_sum
|
||||
[6] main::sum1#0 = fg_sum::return
|
||||
[7] *COLS = main::sum1#0
|
||||
[8] *(&d) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
[9] *(&fg_sum::a) = memcpy(*(&c), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
[10] *(&fg_sum::b) = memcpy(*(&d), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
[11] callexecute fg_sum
|
||||
[12] main::sum2#0 = fg_sum::return
|
||||
[13] *COLS = main::sum2#0
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[14] return
|
||||
to:@return
|
458
src/test/ref/varcall-4.log
Normal file
458
src/test/ref/varcall-4.log
Normal file
@ -0,0 +1,458 @@
|
||||
Converting parameter in __varcall procedure to load/store fg_sum::a
|
||||
Converting parameter in __varcall procedure to load/store fg_sum::b
|
||||
Converting return in __varcall procedure to load/store fg_sum::return
|
||||
Calling convention __varcall adding prepare/execute/finalize for main::$0 = call fg_sum a b
|
||||
Calling convention __varcall adding prepare/execute/finalize for main::$1 = call fg_sum c d
|
||||
Calling convention VAR_CALL adding return value assignment main::$0 = fg_sum::return
|
||||
Calling convention VAR_CALL adding return value assignment main::$1 = fg_sum::return
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
*(&fg_sum::a) = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
fg_sum::a = struct-unwound {*(&fg_sum::a)}
|
||||
*(&fg_sum::b) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
fg_sum::b = struct-unwound {*(&fg_sum::b)}
|
||||
callexecute fg_sum
|
||||
main::$0 = fg_sum::return
|
||||
main::sum1#0 = main::$0
|
||||
*COLS = main::sum1#0
|
||||
*(&d) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
d = struct-unwound {*(&d)}
|
||||
*(&fg_sum::a) = memcpy(*(&c), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
fg_sum::a = struct-unwound {*(&fg_sum::a)}
|
||||
*(&fg_sum::b) = memcpy(*(&d), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
fg_sum::b = struct-unwound {*(&fg_sum::b)}
|
||||
callexecute fg_sum
|
||||
main::$1 = fg_sum::return
|
||||
main::sum2#0 = main::$1
|
||||
*COLS = main::sum2#0
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
|
||||
__varcall byte fg_sum(struct Cols fg_sum::a , struct Cols fg_sum::b)
|
||||
fg_sum: scope:[fg_sum] from
|
||||
fg_sum::$0 = *((byte*)&fg_sum::a+OFFSET_STRUCT_COLS_FG) + *((byte*)&fg_sum::b+OFFSET_STRUCT_COLS_FG)
|
||||
fg_sum::return = fg_sum::$0
|
||||
to:fg_sum::@return
|
||||
fg_sum::@return: scope:[fg_sum] from fg_sum
|
||||
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 byte* const COLS = (byte*)$d020
|
||||
constant byte OFFSET_STRUCT_COLS_FG = 2
|
||||
constant byte SIZEOF_STRUCT_COLS = 3
|
||||
void __start()
|
||||
struct Cols a loadstore = { border: 1, bg: 2, fg: 3 }
|
||||
struct Cols b loadstore = { border: 3, bg: 4, fg: 6 }
|
||||
struct Cols c loadstore = { border: 5, bg: 6, fg: 7 }
|
||||
struct Cols d loadstore = {}
|
||||
__varcall byte fg_sum(struct Cols fg_sum::a , struct Cols fg_sum::b)
|
||||
byte~ fg_sum::$0
|
||||
struct Cols fg_sum::a loadstore
|
||||
struct Cols fg_sum::b loadstore
|
||||
byte fg_sum::return loadstore
|
||||
void main()
|
||||
byte~ main::$0
|
||||
byte~ main::$1
|
||||
byte main::sum1
|
||||
byte main::sum1#0
|
||||
byte main::sum2
|
||||
byte main::sum2#0
|
||||
|
||||
Simplifying constant pointer cast (byte*) 53280
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Alias candidate removed (volatile)fg_sum::return = fg_sum::$0
|
||||
Alias main::sum1#0 = main::$0
|
||||
Alias main::sum2#0 = main::$1
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Alias candidate removed (volatile)fg_sum::return = fg_sum::$0
|
||||
Removing C-classic struct-unwound assignment [1] fg_sum::a = struct-unwound {*(&fg_sum::a)}
|
||||
Removing C-classic struct-unwound assignment [3] fg_sum::b = struct-unwound {*(&fg_sum::b)}
|
||||
Removing C-classic struct-unwound assignment [8] d = struct-unwound {*(&d)}
|
||||
Removing C-classic struct-unwound assignment [10] fg_sum::a = struct-unwound {*(&fg_sum::a)}
|
||||
Removing C-classic struct-unwound assignment [12] fg_sum::b = struct-unwound {*(&fg_sum::b)}
|
||||
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)fg_sum::return = fg_sum::$0
|
||||
Alias candidate removed (volatile)fg_sum::return = fg_sum::$0
|
||||
Alias candidate removed (volatile)fg_sum::return = fg_sum::$0
|
||||
CALL GRAPH
|
||||
Calls in [main] to fg_sum:5 fg_sum:11
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
__varcall byte fg_sum(struct Cols fg_sum::a , struct Cols fg_sum::b)
|
||||
fg_sum: scope:[fg_sum] from
|
||||
[0] fg_sum::$0 = *((byte*)&fg_sum::a+OFFSET_STRUCT_COLS_FG) + *((byte*)&fg_sum::b+OFFSET_STRUCT_COLS_FG)
|
||||
[1] fg_sum::return = fg_sum::$0
|
||||
to:fg_sum::@return
|
||||
fg_sum::@return: scope:[fg_sum] from fg_sum
|
||||
[2] return
|
||||
to:@return
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[3] *(&fg_sum::a) = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
[4] *(&fg_sum::b) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
[5] callexecute fg_sum
|
||||
[6] main::sum1#0 = fg_sum::return
|
||||
[7] *COLS = main::sum1#0
|
||||
[8] *(&d) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
[9] *(&fg_sum::a) = memcpy(*(&c), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
[10] *(&fg_sum::b) = memcpy(*(&d), struct Cols, SIZEOF_STRUCT_COLS)
|
||||
[11] callexecute fg_sum
|
||||
[12] main::sum2#0 = fg_sum::return
|
||||
[13] *COLS = main::sum2#0
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[14] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
struct Cols a loadstore = { border: 1, bg: 2, fg: 3 }
|
||||
struct Cols b loadstore = { border: 3, bg: 4, fg: 6 }
|
||||
struct Cols c loadstore = { border: 5, bg: 6, fg: 7 }
|
||||
struct Cols d loadstore = {}
|
||||
__varcall byte fg_sum(struct Cols fg_sum::a , struct Cols fg_sum::b)
|
||||
byte~ fg_sum::$0 22.0
|
||||
struct Cols fg_sum::a loadstore
|
||||
struct Cols fg_sum::b loadstore
|
||||
byte fg_sum::return loadstore 3.75
|
||||
void main()
|
||||
byte main::sum1
|
||||
byte main::sum1#0 4.0
|
||||
byte main::sum2
|
||||
byte main::sum2#0 4.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable fg_sum::$0 to live range equivalence class [ fg_sum::$0 ]
|
||||
Added variable fg_sum::return to live range equivalence class [ fg_sum::return ]
|
||||
Added variable main::sum1#0 to live range equivalence class [ main::sum1#0 ]
|
||||
Added variable main::sum2#0 to live range equivalence class [ main::sum2#0 ]
|
||||
Added variable a to live range equivalence class [ a ]
|
||||
Added variable b to live range equivalence class [ b ]
|
||||
Added variable c to live range equivalence class [ c ]
|
||||
Added variable d to live range equivalence class [ d ]
|
||||
Added variable fg_sum::a to live range equivalence class [ fg_sum::a ]
|
||||
Added variable fg_sum::b to live range equivalence class [ fg_sum::b ]
|
||||
Complete equivalence classes
|
||||
[ fg_sum::$0 ]
|
||||
[ fg_sum::return ]
|
||||
[ main::sum1#0 ]
|
||||
[ main::sum2#0 ]
|
||||
[ a ]
|
||||
[ b ]
|
||||
[ c ]
|
||||
[ d ]
|
||||
[ fg_sum::a ]
|
||||
[ fg_sum::b ]
|
||||
Allocated zp[1]:2 [ fg_sum::$0 ]
|
||||
Allocated zp[1]:3 [ fg_sum::return ]
|
||||
Allocated zp[1]:4 [ main::sum1#0 ]
|
||||
Allocated zp[1]:5 [ main::sum2#0 ]
|
||||
Allocated mem[3] [ a ]
|
||||
Allocated mem[3] [ b ]
|
||||
Allocated mem[3] [ c ]
|
||||
Allocated mem[3] [ d ]
|
||||
Allocated zp[3]:6 [ fg_sum::a ]
|
||||
Allocated zp[3]:9 [ fg_sum::b ]
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] fg_sum::$0 = *((byte*)&fg_sum::a+OFFSET_STRUCT_COLS_FG) + *((byte*)&fg_sum::b+OFFSET_STRUCT_COLS_FG) [ fg_sum::$0 fg_sum::a fg_sum::b ] ( fg_sum:5 [ b d c fg_sum::$0 fg_sum::a fg_sum::b ] { } fg_sum:11 [ fg_sum::$0 fg_sum::a fg_sum::b ] { } ) always clobbers reg byte a
|
||||
Statement [3] *(&fg_sum::a) = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) [ fg_sum::a fg_sum::b b d c ] ( [ fg_sum::a fg_sum::b b d c ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [4] *(&fg_sum::b) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS) [ fg_sum::a fg_sum::b b d c ] ( [ fg_sum::a fg_sum::b b d c ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [8] *(&d) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS) [ fg_sum::a fg_sum::b d c ] ( [ fg_sum::a fg_sum::b d c ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [9] *(&fg_sum::a) = memcpy(*(&c), struct Cols, SIZEOF_STRUCT_COLS) [ fg_sum::a fg_sum::b d ] ( [ fg_sum::a fg_sum::b d ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [10] *(&fg_sum::b) = memcpy(*(&d), struct Cols, SIZEOF_STRUCT_COLS) [ fg_sum::a fg_sum::b ] ( [ fg_sum::a fg_sum::b ] { } ) always clobbers reg byte a reg byte y
|
||||
Potential registers zp[1]:2 [ fg_sum::$0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:3 [ fg_sum::return ] : zp[1]:3 ,
|
||||
Potential registers zp[1]:4 [ main::sum1#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:5 [ main::sum2#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers mem[3] [ a ] : mem[3] ,
|
||||
Potential registers mem[3] [ b ] : mem[3] ,
|
||||
Potential registers mem[3] [ c ] : mem[3] ,
|
||||
Potential registers mem[3] [ d ] : mem[3] ,
|
||||
Potential registers zp[3]:6 [ fg_sum::a ] : zp[3]:6 ,
|
||||
Potential registers zp[3]:9 [ fg_sum::b ] : zp[3]:9 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [fg_sum] 22: zp[1]:2 [ fg_sum::$0 ] 3.75: zp[1]:3 [ fg_sum::return ] 0: zp[3]:6 [ fg_sum::a ] 0: zp[3]:9 [ fg_sum::b ]
|
||||
Uplift Scope [main] 4: zp[1]:4 [ main::sum1#0 ] 4: zp[1]:5 [ main::sum2#0 ]
|
||||
Uplift Scope [Cols]
|
||||
Uplift Scope [] 0: mem[3] [ a ] 0: mem[3] [ b ] 0: mem[3] [ c ] 0: mem[3] [ d ]
|
||||
|
||||
Uplifting [fg_sum] best 149 combination reg byte a [ fg_sum::$0 ] zp[1]:3 [ fg_sum::return ] zp[3]:6 [ fg_sum::a ] zp[3]:9 [ fg_sum::b ]
|
||||
Uplifting [main] best 137 combination reg byte a [ main::sum1#0 ] reg byte a [ main::sum2#0 ]
|
||||
Uplifting [Cols] best 137 combination
|
||||
Uplifting [] best 137 combination mem[3] [ a ] mem[3] [ b ] mem[3] [ c ] mem[3] [ d ]
|
||||
Attempting to uplift remaining variables inzp[1]:3 [ fg_sum::return ]
|
||||
Uplifting [fg_sum] best 137 combination zp[1]:3 [ fg_sum::return ]
|
||||
Allocated (was zp[1]:3) zp[1]:2 [ fg_sum::return ]
|
||||
Allocated (was zp[3]:6) zp[3]:3 [ fg_sum::a ]
|
||||
Allocated (was zp[3]:9) zp[3]:6 [ fg_sum::b ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test __varcall calling convention
|
||||
// Struct parameter
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="varcall-4.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 = 3
|
||||
.const OFFSET_STRUCT_COLS_FG = 2
|
||||
.label COLS = $d020
|
||||
.segment Code
|
||||
// fg_sum
|
||||
// fg_sum(struct Cols zp(3) a, struct Cols zp(6) b)
|
||||
fg_sum: {
|
||||
.label a = 3
|
||||
.label b = 6
|
||||
.label return = 2
|
||||
// [0] fg_sum::$0 = *((byte*)&fg_sum::a+OFFSET_STRUCT_COLS_FG) + *((byte*)&fg_sum::b+OFFSET_STRUCT_COLS_FG) -- vbuaa=_deref_pbuc1_plus__deref_pbuc2
|
||||
lda a+OFFSET_STRUCT_COLS_FG
|
||||
clc
|
||||
adc b+OFFSET_STRUCT_COLS_FG
|
||||
// [1] fg_sum::return = fg_sum::$0 -- vbuz1=vbuaa
|
||||
sta.z return
|
||||
jmp __breturn
|
||||
// fg_sum::@return
|
||||
__breturn:
|
||||
// [2] return
|
||||
rts
|
||||
}
|
||||
// main
|
||||
main: {
|
||||
// [3] *(&fg_sum::a) = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda a-1,y
|
||||
sta fg_sum.a-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [4] *(&fg_sum::b) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda b-1,y
|
||||
sta fg_sum.b-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [5] callexecute fg_sum -- jsr
|
||||
jsr fg_sum
|
||||
// [6] main::sum1#0 = fg_sum::return -- vbuaa=vbuz1
|
||||
lda.z fg_sum.return
|
||||
// [7] *COLS = main::sum1#0 -- _deref_pbuc1=vbuaa
|
||||
sta COLS
|
||||
// [8] *(&d) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda b-1,y
|
||||
sta d-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [9] *(&fg_sum::a) = memcpy(*(&c), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda c-1,y
|
||||
sta fg_sum.a-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [10] *(&fg_sum::b) = memcpy(*(&d), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda d-1,y
|
||||
sta fg_sum.b-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [11] callexecute fg_sum -- jsr
|
||||
jsr fg_sum
|
||||
// [12] main::sum2#0 = fg_sum::return -- vbuaa=vbuz1
|
||||
lda.z fg_sum.return
|
||||
// [13] *COLS = main::sum2#0 -- _deref_pbuc1=vbuaa
|
||||
sta COLS
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [14] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
a: .byte 1, 2, 3
|
||||
b: .byte 3, 4, 6
|
||||
c: .byte 5, 6, 7
|
||||
d: .fill SIZEOF_STRUCT_COLS, 0
|
||||
|
||||
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 byte* const COLS = (byte*) 53280
|
||||
constant byte OFFSET_STRUCT_COLS_FG = 2
|
||||
constant byte SIZEOF_STRUCT_COLS = 3
|
||||
struct Cols a loadstore mem[3] = { border: 1, bg: 2, fg: 3 }
|
||||
struct Cols b loadstore mem[3] = { border: 3, bg: 4, fg: 6 }
|
||||
struct Cols c loadstore mem[3] = { border: 5, bg: 6, fg: 7 }
|
||||
struct Cols d loadstore mem[3] = {}
|
||||
__varcall byte fg_sum(struct Cols fg_sum::a , struct Cols fg_sum::b)
|
||||
byte~ fg_sum::$0 reg byte a 22.0
|
||||
struct Cols fg_sum::a loadstore zp[3]:3
|
||||
struct Cols fg_sum::b loadstore zp[3]:6
|
||||
byte fg_sum::return loadstore zp[1]:2 3.75
|
||||
void main()
|
||||
byte main::sum1
|
||||
byte main::sum1#0 reg byte a 4.0
|
||||
byte main::sum2
|
||||
byte main::sum2#0 reg byte a 4.0
|
||||
|
||||
reg byte a [ fg_sum::$0 ]
|
||||
zp[1]:2 [ fg_sum::return ]
|
||||
reg byte a [ main::sum1#0 ]
|
||||
reg byte a [ main::sum2#0 ]
|
||||
mem[3] [ a ]
|
||||
mem[3] [ b ]
|
||||
mem[3] [ c ]
|
||||
mem[3] [ d ]
|
||||
zp[3]:3 [ fg_sum::a ]
|
||||
zp[3]:6 [ fg_sum::b ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 131
|
||||
|
||||
// File Comments
|
||||
// Test __varcall calling convention
|
||||
// Struct parameter
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="varcall-4.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 = 3
|
||||
.const OFFSET_STRUCT_COLS_FG = 2
|
||||
.label COLS = $d020
|
||||
.segment Code
|
||||
// fg_sum
|
||||
// fg_sum(struct Cols zp(3) a, struct Cols zp(6) b)
|
||||
fg_sum: {
|
||||
.label a = 3
|
||||
.label b = 6
|
||||
.label return = 2
|
||||
// a.fg+b.fg
|
||||
// [0] fg_sum::$0 = *((byte*)&fg_sum::a+OFFSET_STRUCT_COLS_FG) + *((byte*)&fg_sum::b+OFFSET_STRUCT_COLS_FG) -- vbuaa=_deref_pbuc1_plus__deref_pbuc2
|
||||
lda a+OFFSET_STRUCT_COLS_FG
|
||||
clc
|
||||
adc b+OFFSET_STRUCT_COLS_FG
|
||||
// return a.fg+b.fg;
|
||||
// [1] fg_sum::return = fg_sum::$0 -- vbuz1=vbuaa
|
||||
sta.z return
|
||||
// fg_sum::@return
|
||||
// }
|
||||
// [2] return
|
||||
rts
|
||||
}
|
||||
// main
|
||||
main: {
|
||||
// fg_sum(a, b)
|
||||
// [3] *(&fg_sum::a) = memcpy(*(&a), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda a-1,y
|
||||
sta fg_sum.a-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [4] *(&fg_sum::b) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda b-1,y
|
||||
sta fg_sum.b-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [5] callexecute fg_sum -- jsr
|
||||
jsr fg_sum
|
||||
// char sum1 = fg_sum(a, b)
|
||||
// [6] main::sum1#0 = fg_sum::return -- vbuaa=vbuz1
|
||||
lda.z fg_sum.return
|
||||
// *COLS = sum1
|
||||
// [7] *COLS = main::sum1#0 -- _deref_pbuc1=vbuaa
|
||||
sta COLS
|
||||
// d = b
|
||||
// [8] *(&d) = memcpy(*(&b), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda b-1,y
|
||||
sta d-1,y
|
||||
dey
|
||||
bne !-
|
||||
// fg_sum(c, d)
|
||||
// [9] *(&fg_sum::a) = memcpy(*(&c), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda c-1,y
|
||||
sta fg_sum.a-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [10] *(&fg_sum::b) = memcpy(*(&d), struct Cols, SIZEOF_STRUCT_COLS) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_COLS
|
||||
!:
|
||||
lda d-1,y
|
||||
sta fg_sum.b-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [11] callexecute fg_sum -- jsr
|
||||
jsr fg_sum
|
||||
// char sum2 = fg_sum(c, d)
|
||||
// [12] main::sum2#0 = fg_sum::return -- vbuaa=vbuz1
|
||||
lda.z fg_sum.return
|
||||
// *COLS = sum2
|
||||
// [13] *COLS = main::sum2#0 -- _deref_pbuc1=vbuaa
|
||||
sta COLS
|
||||
// main::@return
|
||||
// }
|
||||
// [14] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
a: .byte 1, 2, 3
|
||||
b: .byte 3, 4, 6
|
||||
c: .byte 5, 6, 7
|
||||
d: .fill SIZEOF_STRUCT_COLS, 0
|
||||
|
28
src/test/ref/varcall-4.sym
Normal file
28
src/test/ref/varcall-4.sym
Normal file
@ -0,0 +1,28 @@
|
||||
constant byte* const COLS = (byte*) 53280
|
||||
constant byte OFFSET_STRUCT_COLS_FG = 2
|
||||
constant byte SIZEOF_STRUCT_COLS = 3
|
||||
struct Cols a loadstore mem[3] = { border: 1, bg: 2, fg: 3 }
|
||||
struct Cols b loadstore mem[3] = { border: 3, bg: 4, fg: 6 }
|
||||
struct Cols c loadstore mem[3] = { border: 5, bg: 6, fg: 7 }
|
||||
struct Cols d loadstore mem[3] = {}
|
||||
__varcall byte fg_sum(struct Cols fg_sum::a , struct Cols fg_sum::b)
|
||||
byte~ fg_sum::$0 reg byte a 22.0
|
||||
struct Cols fg_sum::a loadstore zp[3]:3
|
||||
struct Cols fg_sum::b loadstore zp[3]:6
|
||||
byte fg_sum::return loadstore zp[1]:2 3.75
|
||||
void main()
|
||||
byte main::sum1
|
||||
byte main::sum1#0 reg byte a 4.0
|
||||
byte main::sum2
|
||||
byte main::sum2#0 reg byte a 4.0
|
||||
|
||||
reg byte a [ fg_sum::$0 ]
|
||||
zp[1]:2 [ fg_sum::return ]
|
||||
reg byte a [ main::sum1#0 ]
|
||||
reg byte a [ main::sum2#0 ]
|
||||
mem[3] [ a ]
|
||||
mem[3] [ b ]
|
||||
mem[3] [ c ]
|
||||
mem[3] [ d ]
|
||||
zp[3]:3 [ fg_sum::a ]
|
||||
zp[3]:6 [ fg_sum::b ]
|
Loading…
x
Reference in New Issue
Block a user