1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Fixed problems with versioned constant call parameters being mixed up and with missing scope name on constant references across scopes.

This commit is contained in:
jespergravgaard 2017-11-01 12:59:29 +01:00
parent 6097d80b91
commit 4de433730f
17 changed files with 1496 additions and 108 deletions

View File

@ -7,6 +7,7 @@ Known Problems
- (useuninitialized.kc) Using an uninitialized variable fails in the optimizer phase. It should fail much earlier.
Features
- Inline contants that are only call parameters used once (eg. x0#0 and x0#1 in callconstparam.kc)
- Move the main code into a main() function, and disallow code outside functions. The main function per default has no parameters and exits with RTS.
- Improve locality of block sequence for if(cond) { stmt1; } else { stmt2; } to if(!cond) goto @else stmt1; jmp @end; @else: stmt2; @end:
- Optimize if/else by swapping if & else if cond is easier to evaluate than !cond.
@ -31,6 +32,12 @@ Features
- Add UpliftRemains support for attempting to uplift potentials to ALU (requires modifying two registers: 1. the ALU potential to ALU - the one added to the ALU potential to A.)
- Support array-initializer syntax as literal word syntax. byte* plotter = { lo, hi };
Word Math
- Support Word table lookup (through 2 byte-tables)
- Support word math operations (addition, subtraction)
- Implement a word-ALU
- Usage: word[] plotter_x; word[] plotter_y; byte* plotter = plotter_x[x] + plotter_y[y]; -> lda plotter_x_lo,x; clc; adc plotter_y_lo,y; sta plotter; lda plotter_x_hi,x; adc plotter_y_hi,y; sta plotter+1
Arrays / Strings / Inline data
- New semantic: Arrays are always allocated inline (and must therefore have a size). Pointers are never.
- Allow complex array expressions in lValues eg. (SCREEN+$100)[idx]
@ -72,6 +79,8 @@ Register Allocation
- Improve combination testing by finding live range overlaps and not creating combinations that would create an overlap conflict.
- Combinations should be created in a tree-structure instead of just doing all combinations
- Example: For equivalence classes a, b, c if a&c have overlapping live ranges they can never have the same register. Therefore the combination iterator should not create combinations where C has the same register as a.
- Optimize registers in local windows - creating smaller sets of combinations. Currently some programs easily has millions of possible combinations.
Process/Code Structure Improvement
- Eliminate copy visitor
@ -149,4 +158,6 @@ Done
+ Make each phase return a separate object graph (allowing for keeeping the history in memory & performing rollbacks)
+ Remove "string" keyword (if it exists).
+ Support hi/lo-byte lvalues - <plotter = plot_xlo[x]+plot_ylo[y]; >plotter = plot_xhi[x]+plot_yhi[y];
+ Add ALU support for lo/hi operators on pointers - to avoid unnecessary zp-variable holding for cases like byte v = y&$7 | <yoffs;
+ Add ALU support for lo/hi operators on pointers - to avoid unnecessary zp-variable holding for cases like byte v = y&$7 | <yoffs;
+ (callconstparam.kc) Constant parameters to multiple calls are mixed together because their versioned names (x0#0, X0#1) are shortened to not include the version and only one version is output in the ASM.
+ (callconstparam.kc) Constant call parameters are stored as values in the called function - not at the call. The reference from the call to the constant does not include the function name, so the result is an unknown symbol error when compiling the ASM.

View File

@ -27,7 +27,7 @@ public class AsmFragment {
/**
* The scope containing the fragment. Used when referencing symbols defined in other scopes.
*/
private ScopeRef scope;
private ScopeRef codeScopeRef;
/**
* The string signature/name of the fragment fragment.
@ -39,7 +39,7 @@ public class AsmFragment {
ControlFlowBlock block,
Program program,
ControlFlowGraph graph) {
this.scope = program.getGraph().getBlockFromStatementIdx(conditionalJump.getIndex()).getScope();
this.codeScopeRef = program.getGraph().getBlockFromStatementIdx(conditionalJump.getIndex()).getScope();
this.bindings = new LinkedHashMap<>();
this.program = program;
String conditionalJumpSignature = conditionalJumpSignature(conditionalJump, block, graph);
@ -47,7 +47,7 @@ public class AsmFragment {
}
public AsmFragment(StatementAssignment assignment, Program program) {
this.scope = program.getGraph().getBlockFromStatementIdx(assignment.getIndex()).getScope();
this.codeScopeRef = program.getGraph().getBlockFromStatementIdx(assignment.getIndex()).getScope();
this.bindings = new LinkedHashMap<>();
this.program = program;
setSignature(assignmentSignature(
@ -57,65 +57,22 @@ public class AsmFragment {
assignment.getrValue2()));
}
public AsmFragment(LValue lValue, RValue rValue, Program program, ScopeRef scope) {
this.scope = scope;
public AsmFragment(LValue lValue, RValue rValue, Program program, ScopeRef codeScopeRef) {
this.codeScopeRef = codeScopeRef;
this.bindings = new LinkedHashMap<>();
this.program = program;
setSignature(assignmentSignature(lValue, null, null, rValue));
}
public AsmFragment(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
this.scope = program.getGraph().getBlockFromStatementIdx(assignment.getIndex()).getScope();
this.codeScopeRef = program.getGraph().getBlockFromStatementIdx(assignment.getIndex()).getScope();
this.bindings = new LinkedHashMap<>();
this.program = program;
setSignature(assignmentWithAluSignature(assignment, assignmentAlu));
}
/**
* Get ASM code for a constant value
*
* @param value The constant value
* @param precedence The precedence of the outer expression operator. Used to generate perenthesis when needed.
*
* @return The ASM string representing the constant value
*/
public static String getAsmConstant(Program program, ConstantValue value, int precedence) {
if (value instanceof ConstantRef) {
ConstantVar constantVar = program.getScope().getConstant((ConstantRef) value);
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
return asmName.replace("#", "_").replace("$", "_");
} else if (value instanceof ConstantInteger) {
return getAsmNumber(((ConstantInteger) value).getNumber());
} else if (value instanceof ConstantChar) {
return "'"+((ConstantChar) value).getValue()+"'";
} else if (value instanceof ConstantString) {
return "\""+((ConstantString) value).getValue()+"\"";
} else if (value instanceof ConstantUnary) {
ConstantUnary unary = (ConstantUnary) value;
Operator operator = unary.getOperator();
boolean parenthesis = operator.getPrecedence()>precedence;
return
(parenthesis ? "(" : "") +
operator.getOperator() +
getAsmConstant(program, unary.getOperand(), operator.getPrecedence()) +
(parenthesis? ")" : "");
} else if (value instanceof ConstantBinary) {
ConstantBinary binary = (ConstantBinary) value;
Operator operator = binary.getOperator();
boolean parenthesis = operator.getPrecedence()>precedence;
return
(parenthesis? "(" : "") +
getAsmConstant(program, binary.getLeft(), operator.getPrecedence()) +
operator.getOperator() +
getAsmConstant(program, binary.getRight(), operator.getPrecedence()) +
(parenthesis? ")" : "");
} else {
throw new RuntimeException("Constant type not supported " + value);
}
}
private String assignmentWithAluSignature(StatementAssignment assignment, StatementAssignment assignmentAlu) {
this.scope = program.getGraph().getBlockFromStatementIdx(assignment.getIndex()).getScope();
this.codeScopeRef = program.getGraph().getBlockFromStatementIdx(assignment.getIndex()).getScope();
if (!(assignment.getrValue2() instanceof VariableRef)) {
throw new AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
}
@ -291,6 +248,11 @@ public class AsmFragment {
this.signature = signature;
}
private Scope getCodeScope() {
return program.getScope().getScope(codeScopeRef);
}
/**
* Zero page register name indexing.
*/
@ -436,18 +398,18 @@ public class AsmFragment {
Variable boundVar = (Variable) boundValue;
Registers.Register register = boundVar.getAllocation();
if (register != null && register instanceof Registers.RegisterZp) {
return new AsmParameter(getAsmParameter(boundVar), true);
return new AsmParameter(getAsmParamName(boundVar), true);
} else {
throw new RuntimeException("Register Type not implemented " + register);
}
} else if (boundValue instanceof ConstantVar) {
ConstantVar constantVar = (ConstantVar) boundValue;
String constantValueAsm = getAsmConstant(program, constantVar.getRef(), 99);
String constantValueAsm = getAsmConstant(program, constantVar.getRef(), 99, getCodeScope());
boolean constantValueZp = SymbolTypeBasic.BYTE.equals(constantVar.getType(program.getScope()));
return new AsmParameter(constantValueAsm, constantValueZp);
} else if (boundValue instanceof ConstantValue) {
ConstantValue boundConst = (ConstantValue) boundValue;
String constantValueAsm = getAsmConstant(program, boundConst, 99);
String constantValueAsm = getAsmConstant(program, boundConst, 99, getCodeScope());
boolean constantValueZp = SymbolTypeBasic.BYTE.equals(boundConst.getType(program.getScope()));
return new AsmParameter(constantValueAsm, constantValueZp);
} else if (boundValue instanceof Label) {
@ -458,6 +420,50 @@ public class AsmFragment {
}
}
/**
* Get ASM code for a constant value
*
* @param value The constant value
* @param precedence The precedence of the outer expression operator. Used to generate perenthesis when needed.
* @param codeScope The scope containing the code being generated. Used for adding scope to the name when needed (eg. line.x1 when referencing x1 variable inside line scope from outside line scope).
*
* @return The ASM string representing the constant value
*/
public static String getAsmConstant(Program program, ConstantValue value, int precedence, Scope codeScope) {
if (value instanceof ConstantRef) {
ConstantVar constantVar = program.getScope().getConstant((ConstantRef) value);
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
return getAsmParamName(constantVar.getScope(), asmName, codeScope);
} else if (value instanceof ConstantInteger) {
return getAsmNumber(((ConstantInteger) value).getNumber());
} else if (value instanceof ConstantChar) {
return "'"+((ConstantChar) value).getValue()+"'";
} else if (value instanceof ConstantString) {
return "\""+((ConstantString) value).getValue()+"\"";
} else if (value instanceof ConstantUnary) {
ConstantUnary unary = (ConstantUnary) value;
Operator operator = unary.getOperator();
boolean parenthesis = operator.getPrecedence()>precedence;
return
(parenthesis ? "(" : "") +
operator.getOperator() +
getAsmConstant(program, unary.getOperand(), operator.getPrecedence(), codeScope) +
(parenthesis? ")" : "");
} else if (value instanceof ConstantBinary) {
ConstantBinary binary = (ConstantBinary) value;
Operator operator = binary.getOperator();
boolean parenthesis = operator.getPrecedence()>precedence;
return
(parenthesis? "(" : "") +
getAsmConstant(program, binary.getLeft(), operator.getPrecedence(), codeScope) +
operator.getOperator() +
getAsmConstant(program, binary.getRight(), operator.getPrecedence(), codeScope) +
(parenthesis? ")" : "");
} else {
throw new RuntimeException("Constant type not supported " + value);
}
}
public static String getAsmNumber(Number number) {
if(number instanceof Integer) {
if(number.intValue()>=0 && number.intValue()<=9) {
@ -474,31 +480,33 @@ public class AsmFragment {
* @param boundVar The variable
* @return The ASM parameter to use in the ASM code
*/
private String getAsmParameter(Variable boundVar) {
private String getAsmParamName(Variable boundVar) {
Scope varScope = boundVar.getScope();
String asmName = boundVar.getAsmName() == null ? boundVar.getLocalName() : boundVar.getAsmName();
return getAsmParameter(varScope, asmName);
return getAsmParamName(varScope, asmName, getCodeScope());
}
/**
* Get the ASM parameter for a specific bound constant
* @param boundVar The constant
* @return The ASM parameter to use in the ASM code
*/
private String getAsmParameter(ConstantVar boundVar) {
private String getAsmParamName(ConstantVar boundVar) {
Scope varScope = boundVar.getScope();
String asmName = boundVar.getAsmName() == null ? boundVar.getLocalName() : boundVar.getAsmName();
return getAsmParameter(varScope, asmName);
return getAsmParamName(varScope, asmName, getCodeScope());
}
/**
* Get the ASM parameter for a specific bound constant/ variable
* @param varScope The scope containing the var/const
* @param asmName The ASM name of the variable (local name or specific ASM name).
* @param codeScope The scope containing the code being generated. Used for adding scope to the name when needed (eg. line.x1 when referencing x1 variable inside line scope from outside line scope).
* @return The ASM parameter to use in the ASM code
*/
private String getAsmParameter(Scope varScope, String asmName) {
if (!varScope.getRef().equals(scope) && varScope.getRef().getFullName().length() > 0) {
private static String getAsmParamName(Scope varScope, String asmName, Scope codeScope) {
if (!varScope.equals(codeScope) && varScope.getRef().getFullName().length() > 0) {
String param = varScope.getFullName() + "." + asmName
.replace('@', 'b')
.replace(':', '_')

View File

@ -0,0 +1,3 @@
stx $ff
cmp $ff
bcc {la1}

View File

@ -236,6 +236,13 @@ public class Registers {
/** Special register used for constants. Has no corresponding CPU register. */
public static class RegisterConstant implements Register {
private ConstantValue constantValue;
public RegisterConstant(ConstantValue constantValue) {
this.constantValue = constantValue;
}
@Override
public RegisterType getType() {
return RegisterType.CONSTANT;
@ -246,20 +253,28 @@ public class Registers {
return false;
}
public ConstantValue getConstantValue() {
return constantValue;
}
@Override
public String toString(Program program) {
return "const";
return "const "+constantValue.toString(program);
}
@Override
public int hashCode() {
return 31;
return constantValue != null ? constantValue.hashCode() : 0;
}
@Override
public boolean equals(Object obj) {
return obj instanceof RegisterConstant;
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RegisterConstant that = (RegisterConstant) o;
return constantValue != null ? constantValue.equals(that.constantValue) : that.constantValue == null;
}
}
}

View File

@ -95,7 +95,7 @@ public class Pass4CodeGeneration {
if(! (constantVar.getValue() instanceof ConstantArray || constantVar.getValue() instanceof ConstantString)) {
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
if (asmName != null && !added.contains(asmName)) {
asm.addConstant(asmName.replace("#", "_").replace("$", "_"), AsmFragment.getAsmConstant(program, constantVar.getValue(), 99));
asm.addConstant(asmName.replace("#", "_").replace("$", "_"), AsmFragment.getAsmConstant(program, constantVar.getValue(), 99, scope));
added.add(asmName);
}
}
@ -119,7 +119,7 @@ public class Pass4CodeGeneration {
if (asmName != null && !added.contains(asmName)) {
List<String> asmElements = new ArrayList<>();
for (ConstantValue element : constantArray.getElements()) {
String asmElement = AsmFragment.getAsmConstant(program, element, 99);
String asmElement = AsmFragment.getAsmConstant(program, element, 99, scope);
asmElements.add(asmElement);
}
if(SymbolTypeBasic.BYTE.equals(constantArray.getElementType())) {

View File

@ -74,7 +74,7 @@ public class Pass4RegistersFinalize extends Pass2Base {
for (ConstantVar constantVar : scope.getAllConstants(false)) {
String asmName = constantVar.getAsmName();
Registers.Register allocation = new Registers.RegisterConstant();
Registers.Register allocation = new Registers.RegisterConstant(constantVar.getValue());
if (asmName.contains("#")) {
String shortName = asmName.substring(0, asmName.indexOf("#"));
if (shortNames.get(shortName) == null || shortNames.get(shortName).equals(allocation)) {

View File

@ -53,11 +53,6 @@ public class TestErrors extends TestCase {
compileAndCompare(filename);
}
public void testCallConstParamProblem() throws IOException, URISyntaxException {
String filename = "callconstparamproblem";
compileAndCompare(filename);
}
private void compileAndCompare(String filename) throws IOException, URISyntaxException {
TestErrors tester = new TestErrors();
tester.testFile(filename);

View File

@ -28,6 +28,12 @@ public class TestPrograms extends TestCase {
compileAndCompare("bitmap-bresenham");
}
public void testCallConstParam() throws IOException, URISyntaxException {
String filename = "callconstparam";
compileAndCompare(filename);
}
public void testScrollClobber() throws IOException, URISyntaxException {
compileAndCompare("scroll-clobber");
}

View File

@ -93,6 +93,8 @@ void plot(byte x, byte y) {
<plotter = plot_xlo[x]+plot_ylo[y];
>plotter = plot_xhi[x]+plot_yhi[y];
// TODO: <plotter can overflow - and carry must then be added to the >plotter part. Requires new logic?
// TODO: New logic needed is 1) word-table lookup (split into two byte-tables) 2) word-addition 3) ALU-capable word-addition
*plotter = *plotter | plot_bit[x];
}

View File

@ -30,18 +30,18 @@ main: {
sta D018
jsr initscreen
jsr initplottables
lda #y0
lda #line.y0
sta line.y
ldx #$a
lda #x0
lda #line.x0
sta line.x
lda #$14
sta line.x1
jsr line
lda #y0
lda #line.y0_1
sta line.y
ldx #$28
lda #x0
lda #line.x0_1
sta line.x
lda #$28
sta line.x1
@ -51,6 +51,8 @@ main: {
line: {
.const x0 = 0
.const y0 = 0
.const x0_1 = $a
.const y0_1 = $14
.label xd = 8
.label yd = 9
.label x = 3

View File

@ -93,6 +93,8 @@ void plot(byte x, byte y) {
<plotter = plot_xlo[x]+plot_ylo[y];
>plotter = plot_xhi[x]+plot_yhi[y];
// TODO: <plotter can overflow - and carry must then be added to the >plotter part. Requires new logic?
// TODO: New logic needed is 1) word-table lookup (split into two byte-tables) 2) word-addition 3) ALU-capable word-addition
*plotter = *plotter | plot_bit[x];
}
@ -5900,13 +5902,13 @@ main: {
//SEG17 [10] phi from main::@2 to line [phi:main::@2->line]
line_from_b2:
//SEG18 [10] phi (byte) line::y#0 = (const byte) line::y0#0 [phi:main::@2->line#0] -- zpby1=coby1
lda #y0
lda #line.y0
sta line.y
//SEG19 [10] phi (byte) line::y1#2 = (byte) 10 [phi:main::@2->line#1] -- zpby1=coby1
lda #$a
sta line.y1
//SEG20 [10] phi (byte) line::x#0 = (const byte) line::x0#0 [phi:main::@2->line#2] -- zpby1=coby1
lda #x0
lda #line.x0
sta line.x
//SEG21 [10] phi (byte) line::x1#2 = (byte) 20 [phi:main::@2->line#3] -- zpby1=coby1
lda #$14
@ -5919,13 +5921,13 @@ main: {
//SEG24 [10] phi from main::@3 to line [phi:main::@3->line]
line_from_b3:
//SEG25 [10] phi (byte) line::y#0 = (const byte) line::y0#1 [phi:main::@3->line#0] -- zpby1=coby1
lda #y0
lda #line.y0_1
sta line.y
//SEG26 [10] phi (byte) line::y1#2 = (byte) 40 [phi:main::@3->line#1] -- zpby1=coby1
lda #$28
sta line.y1
//SEG27 [10] phi (byte) line::x#0 = (const byte) line::x0#1 [phi:main::@3->line#2] -- zpby1=coby1
lda #x0
lda #line.x0_1
sta line.x
//SEG28 [10] phi (byte) line::x1#2 = (byte) 40 [phi:main::@3->line#3] -- zpby1=coby1
lda #$28
@ -5941,6 +5943,8 @@ main: {
line: {
.const x0 = 0
.const y0 = 0
.const x0_1 = $a
.const y0_1 = $14
.label _10 = 20
.label xd = 16
.label yd = 17
@ -6567,12 +6571,12 @@ main: {
//SEG17 [10] phi from main::@2 to line [phi:main::@2->line]
line_from_b2:
//SEG18 [10] phi (byte) line::y#0 = (const byte) line::y0#0 [phi:main::@2->line#0] -- zpby1=coby1
lda #y0
lda #line.y0
sta line.y
//SEG19 [10] phi (byte) line::y1#2 = (byte) 10 [phi:main::@2->line#1] -- xby=coby1
ldx #$a
//SEG20 [10] phi (byte) line::x#0 = (const byte) line::x0#0 [phi:main::@2->line#2] -- zpby1=coby1
lda #x0
lda #line.x0
sta line.x
//SEG21 [10] phi (byte) line::x1#2 = (byte) 20 [phi:main::@2->line#3] -- zpby1=coby1
lda #$14
@ -6584,12 +6588,12 @@ main: {
//SEG24 [10] phi from main::@3 to line [phi:main::@3->line]
line_from_b3:
//SEG25 [10] phi (byte) line::y#0 = (const byte) line::y0#1 [phi:main::@3->line#0] -- zpby1=coby1
lda #y0
lda #line.y0_1
sta line.y
//SEG26 [10] phi (byte) line::y1#2 = (byte) 40 [phi:main::@3->line#1] -- xby=coby1
ldx #$28
//SEG27 [10] phi (byte) line::x#0 = (const byte) line::x0#1 [phi:main::@3->line#2] -- zpby1=coby1
lda #x0
lda #line.x0_1
sta line.x
//SEG28 [10] phi (byte) line::x1#2 = (byte) 40 [phi:main::@3->line#3] -- zpby1=coby1
lda #$28
@ -6604,6 +6608,8 @@ main: {
line: {
.const x0 = 0
.const y0 = 0
.const x0_1 = $a
.const y0_1 = $14
.label xd = 8
.label yd = 9
.label x = 3
@ -6969,12 +6975,12 @@ main: {
//SEG17 [10] phi from main::@2 to line [phi:main::@2->line]
line_from_b2:
//SEG18 [10] phi (byte) line::y#0 = (const byte) line::y0#0 [phi:main::@2->line#0] -- zpby1=coby1
lda #y0
lda #line.y0
sta line.y
//SEG19 [10] phi (byte) line::y1#2 = (byte) 10 [phi:main::@2->line#1] -- xby=coby1
ldx #$a
//SEG20 [10] phi (byte) line::x#0 = (const byte) line::x0#0 [phi:main::@2->line#2] -- zpby1=coby1
lda #x0
lda #line.x0
sta line.x
//SEG21 [10] phi (byte) line::x1#2 = (byte) 20 [phi:main::@2->line#3] -- zpby1=coby1
lda #$14
@ -6986,12 +6992,12 @@ main: {
//SEG24 [10] phi from main::@3 to line [phi:main::@3->line]
line_from_b3:
//SEG25 [10] phi (byte) line::y#0 = (const byte) line::y0#1 [phi:main::@3->line#0] -- zpby1=coby1
lda #y0
lda #line.y0_1
sta line.y
//SEG26 [10] phi (byte) line::y1#2 = (byte) 40 [phi:main::@3->line#1] -- xby=coby1
ldx #$28
//SEG27 [10] phi (byte) line::x#0 = (const byte) line::x0#1 [phi:main::@3->line#2] -- zpby1=coby1
lda #x0
lda #line.x0_1
sta line.x
//SEG28 [10] phi (byte) line::x1#2 = (byte) 40 [phi:main::@3->line#3] -- zpby1=coby1
lda #$28
@ -7006,6 +7012,8 @@ main: {
line: {
.const x0 = 0
.const y0 = 0
.const x0_1 = $a
.const y0_1 = $14
.label xd = 8
.label yd = 9
.label x = 3
@ -7387,12 +7395,12 @@ main: {
//SEG16 [7] call line param-assignment [ ]
//SEG17 [10] phi from main::@2 to line [phi:main::@2->line]
//SEG18 [10] phi (byte) line::y#0 = (const byte) line::y0#0 [phi:main::@2->line#0] -- zpby1=coby1
lda #y0
lda #line.y0
sta line.y
//SEG19 [10] phi (byte) line::y1#2 = (byte) 10 [phi:main::@2->line#1] -- xby=coby1
ldx #$a
//SEG20 [10] phi (byte) line::x#0 = (const byte) line::x0#0 [phi:main::@2->line#2] -- zpby1=coby1
lda #x0
lda #line.x0
sta line.x
//SEG21 [10] phi (byte) line::x1#2 = (byte) 20 [phi:main::@2->line#3] -- zpby1=coby1
lda #$14
@ -7403,12 +7411,12 @@ main: {
//SEG23 [8] call line param-assignment [ ]
//SEG24 [10] phi from main::@3 to line [phi:main::@3->line]
//SEG25 [10] phi (byte) line::y#0 = (const byte) line::y0#1 [phi:main::@3->line#0] -- zpby1=coby1
lda #y0
lda #line.y0_1
sta line.y
//SEG26 [10] phi (byte) line::y1#2 = (byte) 40 [phi:main::@3->line#1] -- xby=coby1
ldx #$28
//SEG27 [10] phi (byte) line::x#0 = (const byte) line::x0#1 [phi:main::@3->line#2] -- zpby1=coby1
lda #x0
lda #line.x0_1
sta line.x
//SEG28 [10] phi (byte) line::x1#2 = (byte) 40 [phi:main::@3->line#3] -- zpby1=coby1
lda #$28
@ -7423,6 +7431,8 @@ main: {
line: {
.const x0 = 0
.const y0 = 0
.const x0_1 = $a
.const y0_1 = $14
.label xd = 8
.label yd = 9
.label x = 3
@ -7783,12 +7793,12 @@ main: {
//SEG16 [7] call line param-assignment [ ]
//SEG17 [10] phi from main::@2 to line [phi:main::@2->line]
//SEG18 [10] phi (byte) line::y#0 = (const byte) line::y0#0 [phi:main::@2->line#0] -- zpby1=coby1
lda #y0
lda #line.y0
sta line.y
//SEG19 [10] phi (byte) line::y1#2 = (byte) 10 [phi:main::@2->line#1] -- xby=coby1
ldx #$a
//SEG20 [10] phi (byte) line::x#0 = (const byte) line::x0#0 [phi:main::@2->line#2] -- zpby1=coby1
lda #x0
lda #line.x0
sta line.x
//SEG21 [10] phi (byte) line::x1#2 = (byte) 20 [phi:main::@2->line#3] -- zpby1=coby1
lda #$14
@ -7798,12 +7808,12 @@ main: {
//SEG23 [8] call line param-assignment [ ]
//SEG24 [10] phi from main::@3 to line [phi:main::@3->line]
//SEG25 [10] phi (byte) line::y#0 = (const byte) line::y0#1 [phi:main::@3->line#0] -- zpby1=coby1
lda #y0
lda #line.y0_1
sta line.y
//SEG26 [10] phi (byte) line::y1#2 = (byte) 40 [phi:main::@3->line#1] -- xby=coby1
ldx #$28
//SEG27 [10] phi (byte) line::x#0 = (const byte) line::x0#1 [phi:main::@3->line#2] -- zpby1=coby1
lda #x0
lda #line.x0_1
sta line.x
//SEG28 [10] phi (byte) line::x1#2 = (byte) 40 [phi:main::@3->line#3] -- zpby1=coby1
lda #$28
@ -7817,6 +7827,8 @@ main: {
line: {
.const x0 = 0
.const y0 = 0
.const x0_1 = $a
.const y0_1 = $14
.label xd = 8
.label yd = 9
.label x = 3
@ -8150,12 +8162,12 @@ main: {
//SEG16 [7] call line param-assignment [ ]
//SEG17 [10] phi from main::@2 to line [phi:main::@2->line]
//SEG18 [10] phi (byte) line::y#0 = (const byte) line::y0#0 [phi:main::@2->line#0] -- zpby1=coby1
lda #y0
lda #line.y0
sta line.y
//SEG19 [10] phi (byte) line::y1#2 = (byte) 10 [phi:main::@2->line#1] -- xby=coby1
ldx #$a
//SEG20 [10] phi (byte) line::x#0 = (const byte) line::x0#0 [phi:main::@2->line#2] -- zpby1=coby1
lda #x0
lda #line.x0
sta line.x
//SEG21 [10] phi (byte) line::x1#2 = (byte) 20 [phi:main::@2->line#3] -- zpby1=coby1
lda #$14
@ -8165,12 +8177,12 @@ main: {
//SEG23 [8] call line param-assignment [ ]
//SEG24 [10] phi from main::@3 to line [phi:main::@3->line]
//SEG25 [10] phi (byte) line::y#0 = (const byte) line::y0#1 [phi:main::@3->line#0] -- zpby1=coby1
lda #y0
lda #line.y0_1
sta line.y
//SEG26 [10] phi (byte) line::y1#2 = (byte) 40 [phi:main::@3->line#1] -- xby=coby1
ldx #$28
//SEG27 [10] phi (byte) line::x#0 = (const byte) line::x0#1 [phi:main::@3->line#2] -- zpby1=coby1
lda #x0
lda #line.x0_1
sta line.x
//SEG28 [10] phi (byte) line::x1#2 = (byte) 40 [phi:main::@3->line#3] -- zpby1=coby1
lda #$28
@ -8184,6 +8196,8 @@ main: {
line: {
.const x0 = 0
.const y0 = 0
.const x0_1 = $a
.const y0_1 = $14
.label xd = 8
.label yd = 9
.label x = 3
@ -8549,7 +8563,7 @@ FINAL SYMBOL TABLE
(byte) line::x#2 x zp ZP_BYTE:3 8.75
(byte) line::x0
(const byte) line::x0#0 x0 = (byte) 0
(const byte) line::x0#1 x0 = (byte) 10
(const byte) line::x0#1 x0#1 = (byte) 10
(byte) line::x1
(byte) line::x1#2 x1 zp ZP_BYTE:2 0.8125
(byte) line::xd
@ -8561,7 +8575,7 @@ FINAL SYMBOL TABLE
(byte) line::y#4 y zp ZP_BYTE:4 11.0
(byte) line::y0
(const byte) line::y0#0 y0 = (byte) 0
(const byte) line::y0#1 y0 = (byte) 20
(const byte) line::y0#1 y0#1 = (byte) 20
(byte) line::y1
(byte) line::y1#2 reg byte x 1.0
(byte) line::yd
@ -8679,12 +8693,12 @@ main: {
//SEG16 [7] call line param-assignment [ ]
//SEG17 [10] phi from main::@2 to line [phi:main::@2->line]
//SEG18 [10] phi (byte) line::y#0 = (const byte) line::y0#0 [phi:main::@2->line#0] -- zpby1=coby1
lda #y0
lda #line.y0
sta line.y
//SEG19 [10] phi (byte) line::y1#2 = (byte) 10 [phi:main::@2->line#1] -- xby=coby1
ldx #$a
//SEG20 [10] phi (byte) line::x#0 = (const byte) line::x0#0 [phi:main::@2->line#2] -- zpby1=coby1
lda #x0
lda #line.x0
sta line.x
//SEG21 [10] phi (byte) line::x1#2 = (byte) 20 [phi:main::@2->line#3] -- zpby1=coby1
lda #$14
@ -8694,12 +8708,12 @@ main: {
//SEG23 [8] call line param-assignment [ ]
//SEG24 [10] phi from main::@3 to line [phi:main::@3->line]
//SEG25 [10] phi (byte) line::y#0 = (const byte) line::y0#1 [phi:main::@3->line#0] -- zpby1=coby1
lda #y0
lda #line.y0_1
sta line.y
//SEG26 [10] phi (byte) line::y1#2 = (byte) 40 [phi:main::@3->line#1] -- xby=coby1
ldx #$28
//SEG27 [10] phi (byte) line::x#0 = (const byte) line::x0#1 [phi:main::@3->line#2] -- zpby1=coby1
lda #x0
lda #line.x0_1
sta line.x
//SEG28 [10] phi (byte) line::x1#2 = (byte) 40 [phi:main::@3->line#3] -- zpby1=coby1
lda #$28
@ -8713,6 +8727,8 @@ main: {
line: {
.const x0 = 0
.const y0 = 0
.const x0_1 = $a
.const y0_1 = $14
.label xd = 8
.label yd = 9
.label x = 3

View File

@ -90,7 +90,7 @@
(byte) line::x#2 x zp ZP_BYTE:3 8.75
(byte) line::x0
(const byte) line::x0#0 x0 = (byte) 0
(const byte) line::x0#1 x0 = (byte) 10
(const byte) line::x0#1 x0#1 = (byte) 10
(byte) line::x1
(byte) line::x1#2 x1 zp ZP_BYTE:2 0.8125
(byte) line::xd
@ -102,7 +102,7 @@
(byte) line::y#4 y zp ZP_BYTE:4 11.0
(byte) line::y0
(const byte) line::y0#0 y0 = (byte) 0
(const byte) line::y0#1 y0 = (byte) 20
(const byte) line::y0#1 y0#1 = (byte) 20
(byte) line::y1
(byte) line::y1#2 reg byte x 1.0
(byte) line::yd

View File

@ -0,0 +1,34 @@
.label screen = 3
jsr main
main: {
lda #2
sta line.x1
lda #<$400
sta screen
lda #>$400
sta screen+1
ldx #line.x0
jsr line
lda #5
sta line.x1
ldx #line.x0_1
jsr line
rts
}
line: {
.const x0 = 1
.const x0_1 = 3
.label x1 = 2
b1:
txa
ldy #0
sta (screen),y
inc screen
bne !+
inc screen+1
!:
inx
cpx x1
bcc b1
rts
}

View File

@ -0,0 +1,30 @@
@begin: scope:[] from
[0] call main param-assignment [ ]
to:@end
@end: scope:[] from @begin
main: scope:[main] from @begin
[1] phi() [ ]
[2] call line param-assignment [ ]
to:main::@1
main::@1: scope:[main] from main
[3] call line param-assignment [ ]
to:main::@return
main::@return: scope:[main] from main::@1
[4] return [ ]
to:@return
line: scope:[line] from main main::@1
[5] (byte) line::x1#2 ← phi( main/(byte) 2 main::@1/(byte) 5 ) [ line::x#0 screen#14 line::x1#2 ]
[5] (byte*) screen#14 ← phi( main/(word) 1024 main::@1/(byte*) screen#1 ) [ line::x#0 screen#14 line::x1#2 ]
[5] (byte) line::x#0 ← phi( main/(const byte) line::x0#0 main::@1/(const byte) line::x0#1 ) [ line::x#0 screen#14 line::x1#2 ]
to:line::@1
line::@1: scope:[line] from line line::@1
[6] (byte*) screen#11 ← phi( line/(byte*) screen#14 line::@1/(byte*) screen#1 ) [ line::x1#2 line::x#2 screen#11 ]
[6] (byte) line::x#2 ← phi( line/(byte) line::x#0 line::@1/(byte) line::x#1 ) [ line::x1#2 line::x#2 screen#11 ]
[7] *((byte*) screen#11) ← (byte) line::x#2 [ line::x1#2 line::x#2 screen#11 ]
[8] (byte*) screen#1 ← ++ (byte*) screen#11 [ line::x1#2 line::x#2 screen#1 ]
[9] (byte) line::x#1 ← ++ (byte) line::x#2 [ line::x1#2 line::x#1 screen#1 ]
[10] if((byte) line::x#1<(byte) line::x1#2) goto line::@1 [ line::x1#2 line::x#1 screen#1 ]
to:line::@return
line::@return: scope:[line] from line::@1
[11] return [ ]
to:@return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
(label) @begin
(label) @end
(void()) line((byte) line::x0 , (byte) line::x1)
(label) line::@1
(label) line::@return
(byte) line::x
(byte) line::x#0 reg byte x 2.0
(byte) line::x#1 reg byte x 16.5
(byte) line::x#2 reg byte x 11.666666666666666
(byte) line::x0
(const byte) line::x0#0 x0 = (byte) 1
(const byte) line::x0#1 x0#1 = (byte) 3
(byte) line::x1
(byte) line::x1#2 x1 zp ZP_BYTE:2 1.8333333333333333
(void()) main()
(label) main::@1
(label) main::@return
(byte*) screen
(byte*) screen#1 screen zp ZP_PTR_BYTE:3 8.0
(byte*) screen#11 screen zp ZP_PTR_BYTE:3 17.5
(byte*) screen#14 screen zp ZP_PTR_BYTE:3 4.0
zp ZP_BYTE:2 [ line::x1#2 ]
reg byte x [ line::x#2 line::x#0 line::x#1 ]
zp ZP_PTR_BYTE:3 [ screen#11 screen#14 screen#1 ]