mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-11 04:29:53 +00:00
Better label naming when creating intermediate labels
This commit is contained in:
parent
88c7ed453a
commit
122cef4e30
@ -61,7 +61,7 @@ public class Procedure extends Scope {
|
|||||||
public List<Variable> getParameters() {
|
public List<Variable> getParameters() {
|
||||||
ArrayList<Variable> parameters = new ArrayList<>();
|
ArrayList<Variable> parameters = new ArrayList<>();
|
||||||
for (String name : parameterNames) {
|
for (String name : parameterNames) {
|
||||||
parameters.add(getScope().getVariable(name));
|
parameters.add(this.getVariable(name));
|
||||||
}
|
}
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
@ -133,4 +133,24 @@ public class Procedure extends Scope {
|
|||||||
public ProcedureRef getRef() {
|
public ProcedureRef getRef() {
|
||||||
return new ProcedureRef(this.getFullName());
|
return new ProcedureRef(this.getFullName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
Procedure procedure = (Procedure) o;
|
||||||
|
|
||||||
|
if (returnType != null ? !returnType.equals(procedure.returnType) : procedure.returnType != null) return false;
|
||||||
|
return parameterNames != null ? parameterNames.equals(procedure.parameterNames) : procedure.parameterNames == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + (returnType != null ? returnType.hashCode() : 0);
|
||||||
|
result = 31 * result + (parameterNames != null ? parameterNames.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
package dk.camelot64.kickc.icl;
|
package dk.camelot64.kickc.icl;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
/** A reference to a procedure */
|
/** A reference to a procedure */
|
||||||
public class ProcedureRef extends SymbolRef {
|
public class ProcedureRef extends SymbolRef {
|
||||||
|
|
||||||
public ProcedureRef(String fullName) {
|
@JsonCreator
|
||||||
|
public ProcedureRef( @JsonProperty("fullName") String fullName) {
|
||||||
super(fullName);
|
super(fullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
public LabelRef getLabelRef() {
|
public LabelRef getLabelRef() {
|
||||||
return new LabelRef(getFullName());
|
return new LabelRef(getFullName());
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|||||||
@JsonSubTypes.Type(value = StatementJump.class, name = "jump"),
|
@JsonSubTypes.Type(value = StatementJump.class, name = "jump"),
|
||||||
@JsonSubTypes.Type(value = StatementLabel.class, name = "label"),
|
@JsonSubTypes.Type(value = StatementLabel.class, name = "label"),
|
||||||
@JsonSubTypes.Type(value = StatementCall.class, name = "call"),
|
@JsonSubTypes.Type(value = StatementCall.class, name = "call"),
|
||||||
@JsonSubTypes.Type(value = StatementCall.class, name = "return"),
|
@JsonSubTypes.Type(value = StatementReturn.class, name = "return"),
|
||||||
@JsonSubTypes.Type(value = StatementProcedureBegin.class, name = "procbegin"),
|
@JsonSubTypes.Type(value = StatementProcedureBegin.class, name = "procbegin"),
|
||||||
@JsonSubTypes.Type(value = StatementProcedureEnd.class, name = "procend")
|
@JsonSubTypes.Type(value = StatementProcedureEnd.class, name = "procend")
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package dk.camelot64.kickc.icl;
|
package dk.camelot64.kickc.icl;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,13 +20,28 @@ public class StatementCall implements StatementLValue {
|
|||||||
private List<RValue> parameters;
|
private List<RValue> parameters;
|
||||||
private boolean parametersByAssignment;
|
private boolean parametersByAssignment;
|
||||||
|
|
||||||
public StatementCall(LValue lValue, String procedureName, List<RValue> parameters) {
|
public StatementCall(
|
||||||
|
LValue lValue, String procedureName, List<RValue> parameters) {
|
||||||
this.lValue = lValue;
|
this.lValue = lValue;
|
||||||
this.procedureName = procedureName;
|
this.procedureName = procedureName;
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
this.parametersByAssignment = false;
|
this.parametersByAssignment = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
StatementCall(
|
||||||
|
@JsonProperty("lValue") LValue lValue,
|
||||||
|
@JsonProperty("procedureName") String procedureName,
|
||||||
|
@JsonProperty("procedure") ProcedureRef procedure,
|
||||||
|
@JsonProperty("parameters") List<RValue> parameters,
|
||||||
|
@JsonProperty("parametersByAssignment") boolean parametersByAssignment) {
|
||||||
|
this.lValue = lValue;
|
||||||
|
this.procedureName = procedureName;
|
||||||
|
this.procedure = procedure;
|
||||||
|
this.parameters = parameters;
|
||||||
|
this.parametersByAssignment = parametersByAssignment;
|
||||||
|
}
|
||||||
|
|
||||||
public LValue getlValue() {
|
public LValue getlValue() {
|
||||||
return lValue;
|
return lValue;
|
||||||
}
|
}
|
||||||
@ -51,6 +70,7 @@ public class StatementCall implements StatementLValue {
|
|||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
public int getNumParameters() {
|
public int getNumParameters() {
|
||||||
return parameters.size();
|
return parameters.size();
|
||||||
}
|
}
|
||||||
@ -124,4 +144,28 @@ public class StatementCall implements StatementLValue {
|
|||||||
}
|
}
|
||||||
return res.toString();
|
return res.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
StatementCall that = (StatementCall) o;
|
||||||
|
|
||||||
|
if (parametersByAssignment != that.parametersByAssignment) return false;
|
||||||
|
if (lValue != null ? !lValue.equals(that.lValue) : that.lValue != null) return false;
|
||||||
|
if (!procedureName.equals(that.procedureName)) return false;
|
||||||
|
if (procedure != null ? !procedure.equals(that.procedure) : that.procedure != null) return false;
|
||||||
|
return parameters != null ? parameters.equals(that.parameters) : that.parameters == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = lValue != null ? lValue.hashCode() : 0;
|
||||||
|
result = 31 * result + procedureName.hashCode();
|
||||||
|
result = 31 * result + (procedure != null ? procedure.hashCode() : 0);
|
||||||
|
result = 31 * result + (parameters != null ? parameters.hashCode() : 0);
|
||||||
|
result = 31 * result + (parametersByAssignment ? 1 : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package dk.camelot64.kickc.icl;
|
package dk.camelot64.kickc.icl;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return Statement inside procedure in Single Static Assignment Form.
|
* Return Statement inside procedure in Single Static Assignment Form.
|
||||||
*/
|
*/
|
||||||
@ -8,7 +11,8 @@ public class StatementReturn implements Statement {
|
|||||||
/** Return value. May be null if not returning a value. */
|
/** Return value. May be null if not returning a value. */
|
||||||
private RValue value;
|
private RValue value;
|
||||||
|
|
||||||
public StatementReturn(RValue value) {
|
@JsonCreator
|
||||||
|
public StatementReturn( @JsonProperty("value") RValue value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,4 +36,19 @@ public class StatementReturn implements Statement {
|
|||||||
@Override
|
@Override
|
||||||
public String getAsString() {
|
public String getAsString() {
|
||||||
return "return "+(value==null?"":value.getAsString()); }
|
return "return "+(value==null?"":value.getAsString()); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
StatementReturn that = (StatementReturn) o;
|
||||||
|
|
||||||
|
return value != null ? value.equals(that.value) : that.value == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return value != null ? value.hashCode() : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ public class Pass1GenerateControlFlowGraph {
|
|||||||
} else if(statement instanceof StatementProcedureEnd) {
|
} else if(statement instanceof StatementProcedureEnd) {
|
||||||
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
||||||
currentBlock.setDefaultSuccessor(new Label("@RETURN", scope, false).getRef());
|
currentBlock.setDefaultSuccessor(new Label("@RETURN", scope, false).getRef());
|
||||||
ControlFlowBlock nextBlock = getOrCreateBlock(currentBlockScope.addLabelIntermediate().getRef());
|
ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate().getRef());
|
||||||
blockStack.pop();
|
blockStack.pop();
|
||||||
ControlFlowBlock prevBlock = blockStack.pop();
|
ControlFlowBlock prevBlock = blockStack.pop();
|
||||||
prevBlock.setDefaultSuccessor(nextBlock.getLabel());
|
prevBlock.setDefaultSuccessor(nextBlock.getLabel());
|
||||||
|
@ -39,19 +39,28 @@ public class TestCompilationOutput extends TestCase {
|
|||||||
tester.testFile("bresenham");
|
tester.testFile("bresenham");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSumMin() throws IOException, URISyntaxException {
|
||||||
|
TestCompilationOutput tester = new TestCompilationOutput();
|
||||||
|
tester.testFile("summin");
|
||||||
|
}
|
||||||
|
|
||||||
private void testFile(String fileName) throws IOException, URISyntaxException {
|
private void testFile(String fileName) throws IOException, URISyntaxException {
|
||||||
String inputPath = testPath + fileName + ".kc";
|
String inputPath = testPath + fileName + ".kc";
|
||||||
System.out.println("Testing output for "+inputPath);
|
System.out.println("Testing output for "+inputPath);
|
||||||
CharStream input = CharStreams.fromFileName(inputPath);
|
CharStream input = CharStreams.fromFileName(inputPath);
|
||||||
Compiler compiler = new Compiler();
|
Compiler compiler = new Compiler();
|
||||||
Compiler.CompilationResult output = compiler.compile(input);
|
Compiler.CompilationResult output = compiler.compile(input);
|
||||||
assertOutput(fileName, ".asm", output.getAsmProgram().toString(false));
|
boolean success = true;
|
||||||
assertOutput(fileName, ".sym", output.getSymbols().getSymbolTableContents());
|
success &= testOutput(fileName, ".asm", output.getAsmProgram().toString(false));
|
||||||
assertOutput(fileName, ".cfg", output.getGraph().getAsTypedString(output.getSymbols()));
|
success &= testOutput(fileName, ".sym", output.getSymbols().getSymbolTableContents());
|
||||||
assertOutput(fileName, ".log", output.getLog().toString());
|
success &= testOutput(fileName, ".cfg", output.getGraph().getAsTypedString(output.getSymbols()));
|
||||||
|
success &= testOutput(fileName, ".log", output.getLog().toString());
|
||||||
|
if(!success) {
|
||||||
|
fail("Output does not match reference!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertOutput(
|
private boolean testOutput(
|
||||||
String fileName,
|
String fileName,
|
||||||
String extension,
|
String extension,
|
||||||
String outputString) throws IOException, URISyntaxException {
|
String outputString) throws IOException, URISyntaxException {
|
||||||
@ -61,7 +70,8 @@ public class TestCompilationOutput extends TestCase {
|
|||||||
refLines = loadReferenceLines(fileName, extension);
|
refLines = loadReferenceLines(fileName, extension);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
writeOutputFile(fileName, extension, outputString);
|
writeOutputFile(fileName, extension, outputString);
|
||||||
fail("Error loading reference."+e.getMessage());
|
System.out.println("Reference file not found "+refPath+fileName+extension);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
// Split output into outLines
|
// Split output into outLines
|
||||||
List<String> outLines = getOutLines(outputString);
|
List<String> outLines = getOutLines(outputString);
|
||||||
@ -71,14 +81,16 @@ public class TestCompilationOutput extends TestCase {
|
|||||||
String refLine = refLines.get(i);
|
String refLine = refLines.get(i);
|
||||||
if(!outLine.equals(refLine)) {
|
if(!outLine.equals(refLine)) {
|
||||||
writeOutputFile(fileName, extension, outputString);
|
writeOutputFile(fileName, extension, outputString);
|
||||||
fail(
|
System.out.println(
|
||||||
"Output does not match reference on line "+i+"\n"+
|
"Output does not match reference on line "+i+"\n"+
|
||||||
"Reference: "+refLine+"\n"+
|
"Reference: "+refLine+"\n"+
|
||||||
"Output: "+outLine
|
"Output: "+outLine
|
||||||
);
|
);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getOutLines(String outputString) throws IOException {
|
private List<String> getOutLines(String outputString) throws IOException {
|
||||||
|
File diff suppressed because one or more lines are too long
@ -6,7 +6,7 @@ main:
|
|||||||
main__B2_from_main:
|
main__B2_from_main:
|
||||||
ldx #25
|
ldx #25
|
||||||
jmp main__B2
|
jmp main__B2
|
||||||
main__B2_from_B12:
|
main__B2_from_B11:
|
||||||
ldx #25
|
ldx #25
|
||||||
main__B2_from_B6:
|
main__B2_from_B6:
|
||||||
main__B2:
|
main__B2:
|
||||||
@ -24,10 +24,10 @@ main__B6:
|
|||||||
bne main__B2_from_B6
|
bne main__B2_from_B6
|
||||||
main__B7:
|
main__B7:
|
||||||
jsr flip
|
jsr flip
|
||||||
main__B11:
|
main__B10:
|
||||||
jsr plot
|
jsr plot
|
||||||
main__B12:
|
main__B11:
|
||||||
jmp main__B2_from_B12
|
jmp main__B2_from_B11
|
||||||
main__Breturn:
|
main__Breturn:
|
||||||
rts
|
rts
|
||||||
plot:
|
plot:
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
main: from @BEGIN
|
main: from @BEGIN
|
||||||
call prepare param-assignment
|
call prepare param-assignment
|
||||||
to:main::@2
|
to:main::@2
|
||||||
main::@2: from main main::@12 main::@6
|
main::@2: from main main::@11 main::@6
|
||||||
(byte) main::c#2 ← phi( main/(byte) 25 main::@6/(byte) main::c#1 main::@12/(byte) 25 )
|
(byte) main::c#2 ← phi( main/(byte) 25 main::@6/(byte) main::c#1 main::@11/(byte) 25 )
|
||||||
to:main::@3
|
to:main::@3
|
||||||
main::@3: from main::@2 main::@3
|
main::@3: from main::@2 main::@3
|
||||||
(byte~) main::$1 ← * (word) 53266
|
(byte~) main::$1 ← * (word) 53266
|
||||||
@ -21,14 +21,14 @@ main::@6: from main::@4
|
|||||||
to:main::@7
|
to:main::@7
|
||||||
main::@7: from main::@6
|
main::@7: from main::@6
|
||||||
call flip param-assignment
|
call flip param-assignment
|
||||||
to:main::@11
|
to:main::@10
|
||||||
main::@11: from main::@7
|
main::@10: from main::@7
|
||||||
call plot param-assignment
|
call plot param-assignment
|
||||||
to:main::@12
|
to:main::@11
|
||||||
main::@12: from main::@11
|
main::@11: from main::@10
|
||||||
if(true) goto main::@2
|
if(true) goto main::@2
|
||||||
to:main::@return
|
to:main::@return
|
||||||
main::@return: from main::@12
|
main::@return: from main::@11
|
||||||
return
|
return
|
||||||
to:@RETURN
|
to:@RETURN
|
||||||
prepare: from main
|
prepare: from main
|
||||||
@ -75,7 +75,7 @@ flip::@3: from flip::@3 flip::@4
|
|||||||
flip::@return: from flip::@3
|
flip::@return: from flip::@3
|
||||||
return
|
return
|
||||||
to:@RETURN
|
to:@RETURN
|
||||||
plot: from main::@11
|
plot: from main::@10
|
||||||
to:plot::@1
|
to:plot::@1
|
||||||
plot::@1: from plot plot::@3
|
plot::@1: from plot plot::@3
|
||||||
(byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 )
|
(byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 )
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -34,8 +34,8 @@
|
|||||||
(void()) main()
|
(void()) main()
|
||||||
(byte~) main::$1 reg byte a
|
(byte~) main::$1 reg byte a
|
||||||
(byte~) main::$3 reg byte a
|
(byte~) main::$3 reg byte a
|
||||||
|
(label) main::@10
|
||||||
(label) main::@11
|
(label) main::@11
|
||||||
(label) main::@12
|
|
||||||
(label) main::@2
|
(label) main::@2
|
||||||
(label) main::@3
|
(label) main::@3
|
||||||
(label) main::@4
|
(label) main::@4
|
||||||
|
22
src/dk/camelot64/kickc/test/ref/summin.asm
Normal file
22
src/dk/camelot64/kickc/test/ref/summin.asm
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
BBEGIN:
|
||||||
|
sum_from_BBEGIN:
|
||||||
|
lda #2
|
||||||
|
sta 3
|
||||||
|
lda #1
|
||||||
|
sta 2
|
||||||
|
jsr sum
|
||||||
|
B2:
|
||||||
|
sum_from_B2:
|
||||||
|
lda #13
|
||||||
|
sta 3
|
||||||
|
lda #9
|
||||||
|
sta 2
|
||||||
|
jsr sum
|
||||||
|
BEND:
|
||||||
|
sum:
|
||||||
|
lda 2
|
||||||
|
clc
|
||||||
|
adc 3
|
||||||
|
sta 4
|
||||||
|
sum__Breturn:
|
||||||
|
rts
|
15
src/dk/camelot64/kickc/test/ref/summin.cfg
Normal file
15
src/dk/camelot64/kickc/test/ref/summin.cfg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
@BEGIN: from
|
||||||
|
call sum param-assignment
|
||||||
|
to:@2
|
||||||
|
@2: from @BEGIN
|
||||||
|
call sum param-assignment
|
||||||
|
to:@END
|
||||||
|
sum: from @2 @BEGIN
|
||||||
|
(byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 )
|
||||||
|
(byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 )
|
||||||
|
(byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum
|
||||||
|
return (byte) s1#0
|
||||||
|
to:@RETURN
|
||||||
|
@END: from @2
|
440
src/dk/camelot64/kickc/test/ref/summin.log
Normal file
440
src/dk/camelot64/kickc/test/ref/summin.log
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
byte s1=sum(1,2);
|
||||||
|
byte s2=sum(9,13);
|
||||||
|
byte sum(byte a, byte b) {
|
||||||
|
return a+b;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROGRAM
|
||||||
|
(byte~) $0 ← call sum (byte) 1 (byte) 2
|
||||||
|
(byte) s1 ← (byte~) $0
|
||||||
|
(byte~) $1 ← call sum (byte) 9 (byte) 13
|
||||||
|
(byte) s2 ← (byte~) $1
|
||||||
|
proc (byte()) sum((byte) sum::a , (byte) sum::b)
|
||||||
|
(byte~) sum::$0 ← (byte) sum::a + (byte) sum::b
|
||||||
|
(byte) sum::return ← (byte~) sum::$0
|
||||||
|
goto sum::@return
|
||||||
|
sum::@return:
|
||||||
|
(byte) sum::return ← (byte) sum::return
|
||||||
|
return (byte) sum::return
|
||||||
|
endproc // sum()
|
||||||
|
|
||||||
|
SYMBOLS
|
||||||
|
(byte~) $0
|
||||||
|
(byte~) $1
|
||||||
|
(byte) s1
|
||||||
|
(byte) s2
|
||||||
|
(byte()) sum((byte) sum::a , (byte) sum::b)
|
||||||
|
(byte~) sum::$0
|
||||||
|
(label) sum::@return
|
||||||
|
(byte) sum::a
|
||||||
|
(byte) sum::b
|
||||||
|
(byte) sum::return
|
||||||
|
|
||||||
|
|
||||||
|
INITIAL CONTROL FLOW GRAPH
|
||||||
|
@BEGIN: from
|
||||||
|
(byte~) $0 ← call sum (byte) 1 (byte) 2
|
||||||
|
(byte) s1 ← (byte~) $0
|
||||||
|
(byte~) $1 ← call sum (byte) 9 (byte) 13
|
||||||
|
(byte) s2 ← (byte~) $1
|
||||||
|
to:@1
|
||||||
|
sum: from
|
||||||
|
(byte~) sum::$0 ← (byte) sum::a + (byte) sum::b
|
||||||
|
(byte) sum::return ← (byte~) sum::$0
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum sum::@1
|
||||||
|
(byte) sum::return ← (byte) sum::return
|
||||||
|
return (byte) sum::return
|
||||||
|
to:@RETURN
|
||||||
|
sum::@1: from
|
||||||
|
to:sum::@return
|
||||||
|
@1: from @BEGIN
|
||||||
|
to:@END
|
||||||
|
@END: from @1
|
||||||
|
|
||||||
|
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL
|
||||||
|
@BEGIN: from
|
||||||
|
(byte) sum::a ← (byte) 1
|
||||||
|
(byte) sum::b ← (byte) 2
|
||||||
|
(byte) sum::return ← call sum param-assignment
|
||||||
|
to:@2
|
||||||
|
@2: from @BEGIN
|
||||||
|
(byte~) $0 ← (byte) sum::return
|
||||||
|
(byte) s1 ← (byte~) $0
|
||||||
|
(byte) sum::a ← (byte) 9
|
||||||
|
(byte) sum::b ← (byte) 13
|
||||||
|
(byte) sum::return ← call sum param-assignment
|
||||||
|
to:@3
|
||||||
|
@3: from @2
|
||||||
|
(byte~) $1 ← (byte) sum::return
|
||||||
|
(byte) s2 ← (byte~) $1
|
||||||
|
to:@1
|
||||||
|
sum: from @2 @BEGIN
|
||||||
|
(byte~) sum::$0 ← (byte) sum::a + (byte) sum::b
|
||||||
|
(byte) sum::return ← (byte~) sum::$0
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum sum::@1
|
||||||
|
(byte) sum::return ← (byte) sum::return
|
||||||
|
return (byte) sum::return
|
||||||
|
to:@RETURN
|
||||||
|
sum::@1: from
|
||||||
|
to:sum::@return
|
||||||
|
@1: from @3
|
||||||
|
to:@END
|
||||||
|
@END: from @1
|
||||||
|
|
||||||
|
Completing Phi functions...
|
||||||
|
Completing Phi functions...
|
||||||
|
CONTROL FLOW GRAPH SSA
|
||||||
|
@BEGIN: from
|
||||||
|
(byte) sum::a#0 ← (byte) 1
|
||||||
|
(byte) sum::b#0 ← (byte) 2
|
||||||
|
(byte) sum::return#0 ← call sum param-assignment
|
||||||
|
to:@2
|
||||||
|
@2: from @BEGIN
|
||||||
|
(byte) sum::return#4 ← phi( @BEGIN/(byte) sum::return#0 )
|
||||||
|
(byte~) $0 ← (byte) sum::return#4
|
||||||
|
(byte) s1#0 ← (byte~) $0
|
||||||
|
(byte) sum::a#1 ← (byte) 9
|
||||||
|
(byte) sum::b#1 ← (byte) 13
|
||||||
|
(byte) sum::return#1 ← call sum param-assignment
|
||||||
|
to:@3
|
||||||
|
@3: from @2
|
||||||
|
(byte) sum::return#5 ← phi( @2/(byte) sum::return#1 )
|
||||||
|
(byte~) $1 ← (byte) sum::return#5
|
||||||
|
(byte) s2#0 ← (byte~) $1
|
||||||
|
to:@1
|
||||||
|
sum: from @2 @BEGIN
|
||||||
|
(byte) sum::b#2 ← phi( @2/(byte) sum::b#1 @BEGIN/(byte) sum::b#0 )
|
||||||
|
(byte) sum::a#2 ← phi( @2/(byte) sum::a#1 @BEGIN/(byte) sum::a#0 )
|
||||||
|
(byte~) sum::$0 ← (byte) sum::a#2 + (byte) sum::b#2
|
||||||
|
(byte) sum::return#2 ← (byte~) sum::$0
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum sum::@1
|
||||||
|
(byte) sum::return#6 ← phi( sum/(byte) sum::return#2 sum::@1/(byte) sum::return#7 )
|
||||||
|
(byte) sum::return#3 ← (byte) sum::return#6
|
||||||
|
return (byte) sum::return#3
|
||||||
|
to:@RETURN
|
||||||
|
sum::@1: from
|
||||||
|
(byte) sum::return#7 ← phi( )
|
||||||
|
to:sum::@return
|
||||||
|
@1: from @3
|
||||||
|
to:@END
|
||||||
|
@END: from @1
|
||||||
|
|
||||||
|
CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN
|
||||||
|
@BEGIN: from
|
||||||
|
(byte) sum::a#0 ← (byte) 1
|
||||||
|
(byte) sum::b#0 ← (byte) 2
|
||||||
|
call sum param-assignment
|
||||||
|
(byte) sum::return#0 ← (byte) sum::return#3
|
||||||
|
to:@2
|
||||||
|
@2: from @BEGIN
|
||||||
|
(byte) sum::return#4 ← phi( @BEGIN/(byte) sum::return#0 )
|
||||||
|
(byte~) $0 ← (byte) sum::return#4
|
||||||
|
(byte) s1#0 ← (byte~) $0
|
||||||
|
(byte) sum::a#1 ← (byte) 9
|
||||||
|
(byte) sum::b#1 ← (byte) 13
|
||||||
|
call sum param-assignment
|
||||||
|
(byte) sum::return#1 ← (byte) sum::return#3
|
||||||
|
to:@3
|
||||||
|
@3: from @2
|
||||||
|
(byte) sum::return#5 ← phi( @2/(byte) sum::return#1 )
|
||||||
|
(byte~) $1 ← (byte) sum::return#5
|
||||||
|
(byte) s2#0 ← (byte~) $1
|
||||||
|
to:@1
|
||||||
|
sum: from @2 @BEGIN
|
||||||
|
(byte) sum::b#2 ← phi( @2/(byte) sum::b#1 @BEGIN/(byte) sum::b#0 )
|
||||||
|
(byte) sum::a#2 ← phi( @2/(byte) sum::a#1 @BEGIN/(byte) sum::a#0 )
|
||||||
|
(byte~) sum::$0 ← (byte) sum::a#2 + (byte) sum::b#2
|
||||||
|
(byte) sum::return#2 ← (byte~) sum::$0
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum sum::@1
|
||||||
|
(byte) sum::return#6 ← phi( sum/(byte) sum::return#2 sum::@1/(byte) sum::return#7 )
|
||||||
|
(byte) sum::return#3 ← (byte) sum::return#6
|
||||||
|
return (byte) sum::return#3
|
||||||
|
to:@RETURN
|
||||||
|
sum::@1: from
|
||||||
|
(byte) sum::return#7 ← phi( )
|
||||||
|
to:sum::@return
|
||||||
|
@1: from @3
|
||||||
|
to:@END
|
||||||
|
@END: from @1
|
||||||
|
|
||||||
|
Culled Empty Block (label) @1
|
||||||
|
Succesful SSA optimization Pass2CullEmptyBlocks
|
||||||
|
CONTROL FLOW GRAPH
|
||||||
|
@BEGIN: from
|
||||||
|
(byte) sum::a#0 ← (byte) 1
|
||||||
|
(byte) sum::b#0 ← (byte) 2
|
||||||
|
call sum param-assignment
|
||||||
|
(byte) sum::return#0 ← (byte) sum::return#3
|
||||||
|
to:@2
|
||||||
|
@2: from @BEGIN
|
||||||
|
(byte) sum::return#4 ← phi( @BEGIN/(byte) sum::return#0 )
|
||||||
|
(byte~) $0 ← (byte) sum::return#4
|
||||||
|
(byte) s1#0 ← (byte~) $0
|
||||||
|
(byte) sum::a#1 ← (byte) 9
|
||||||
|
(byte) sum::b#1 ← (byte) 13
|
||||||
|
call sum param-assignment
|
||||||
|
(byte) sum::return#1 ← (byte) sum::return#3
|
||||||
|
to:@3
|
||||||
|
@3: from @2
|
||||||
|
(byte) sum::return#5 ← phi( @2/(byte) sum::return#1 )
|
||||||
|
(byte~) $1 ← (byte) sum::return#5
|
||||||
|
(byte) s2#0 ← (byte~) $1
|
||||||
|
to:@END
|
||||||
|
sum: from @2 @BEGIN
|
||||||
|
(byte) sum::b#2 ← phi( @2/(byte) sum::b#1 @BEGIN/(byte) sum::b#0 )
|
||||||
|
(byte) sum::a#2 ← phi( @2/(byte) sum::a#1 @BEGIN/(byte) sum::a#0 )
|
||||||
|
(byte~) sum::$0 ← (byte) sum::a#2 + (byte) sum::b#2
|
||||||
|
(byte) sum::return#2 ← (byte~) sum::$0
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum sum::@1
|
||||||
|
(byte) sum::return#6 ← phi( sum/(byte) sum::return#2 sum::@1/(byte) sum::return#7 )
|
||||||
|
(byte) sum::return#3 ← (byte) sum::return#6
|
||||||
|
return (byte) sum::return#3
|
||||||
|
to:@RETURN
|
||||||
|
sum::@1: from
|
||||||
|
(byte) sum::return#7 ← phi( )
|
||||||
|
to:sum::@return
|
||||||
|
@END: from @3
|
||||||
|
|
||||||
|
Constant (byte) sum::a#0 (byte) 1
|
||||||
|
Constant (byte) sum::b#0 (byte) 2
|
||||||
|
Constant (byte) sum::a#1 (byte) 9
|
||||||
|
Constant (byte) sum::b#1 (byte) 13
|
||||||
|
Succesful SSA optimization Pass2ConstantPropagation
|
||||||
|
CONTROL FLOW GRAPH
|
||||||
|
@BEGIN: from
|
||||||
|
call sum param-assignment
|
||||||
|
(byte) sum::return#0 ← (byte) sum::return#3
|
||||||
|
to:@2
|
||||||
|
@2: from @BEGIN
|
||||||
|
(byte) sum::return#4 ← phi( @BEGIN/(byte) sum::return#0 )
|
||||||
|
(byte~) $0 ← (byte) sum::return#4
|
||||||
|
(byte) s1#0 ← (byte~) $0
|
||||||
|
call sum param-assignment
|
||||||
|
(byte) sum::return#1 ← (byte) sum::return#3
|
||||||
|
to:@3
|
||||||
|
@3: from @2
|
||||||
|
(byte) sum::return#5 ← phi( @2/(byte) sum::return#1 )
|
||||||
|
(byte~) $1 ← (byte) sum::return#5
|
||||||
|
(byte) s2#0 ← (byte~) $1
|
||||||
|
to:@END
|
||||||
|
sum: from @2 @BEGIN
|
||||||
|
(byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 )
|
||||||
|
(byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 )
|
||||||
|
(byte~) sum::$0 ← (byte) sum::a#2 + (byte) sum::b#2
|
||||||
|
(byte) sum::return#2 ← (byte~) sum::$0
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum sum::@1
|
||||||
|
(byte) sum::return#6 ← phi( sum/(byte) sum::return#2 sum::@1/(byte) sum::return#7 )
|
||||||
|
(byte) sum::return#3 ← (byte) sum::return#6
|
||||||
|
return (byte) sum::return#3
|
||||||
|
to:@RETURN
|
||||||
|
sum::@1: from
|
||||||
|
(byte) sum::return#7 ← phi( )
|
||||||
|
to:sum::@return
|
||||||
|
@END: from @3
|
||||||
|
|
||||||
|
Alias (byte) s1#0 = (byte) sum::return#0 (byte) sum::return#3 (byte) sum::return#4 (byte~) $0 (byte) sum::return#1 (byte) sum::return#5 (byte~) $1 (byte) s2#0 (byte) sum::return#6
|
||||||
|
Alias (byte) sum::return#2 = (byte~) sum::$0
|
||||||
|
Succesful SSA optimization Pass2AliasElimination
|
||||||
|
CONTROL FLOW GRAPH
|
||||||
|
@BEGIN: from
|
||||||
|
call sum param-assignment
|
||||||
|
to:@2
|
||||||
|
@2: from @BEGIN
|
||||||
|
call sum param-assignment
|
||||||
|
to:@3
|
||||||
|
@3: from @2
|
||||||
|
to:@END
|
||||||
|
sum: from @2 @BEGIN
|
||||||
|
(byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 )
|
||||||
|
(byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 )
|
||||||
|
(byte) sum::return#2 ← (byte) sum::a#2 + (byte) sum::b#2
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum sum::@1
|
||||||
|
(byte) s1#0 ← phi( sum/(byte) sum::return#2 sum::@1/(byte) sum::return#7 )
|
||||||
|
return (byte) s1#0
|
||||||
|
to:@RETURN
|
||||||
|
sum::@1: from
|
||||||
|
(byte) sum::return#7 ← phi( )
|
||||||
|
to:sum::@return
|
||||||
|
@END: from @3
|
||||||
|
|
||||||
|
Redundant Phi (byte) sum::return#7 VOID
|
||||||
|
Succesful SSA optimization Pass2RedundantPhiElimination
|
||||||
|
CONTROL FLOW GRAPH
|
||||||
|
@BEGIN: from
|
||||||
|
call sum param-assignment
|
||||||
|
to:@2
|
||||||
|
@2: from @BEGIN
|
||||||
|
call sum param-assignment
|
||||||
|
to:@3
|
||||||
|
@3: from @2
|
||||||
|
to:@END
|
||||||
|
sum: from @2 @BEGIN
|
||||||
|
(byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 )
|
||||||
|
(byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 )
|
||||||
|
(byte) sum::return#2 ← (byte) sum::a#2 + (byte) sum::b#2
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum sum::@1
|
||||||
|
(byte) s1#0 ← phi( sum/(byte) sum::return#2 )
|
||||||
|
return (byte) s1#0
|
||||||
|
to:@RETURN
|
||||||
|
sum::@1: from
|
||||||
|
to:sum::@return
|
||||||
|
@END: from @3
|
||||||
|
|
||||||
|
Culled Empty Block (label) @3
|
||||||
|
Culled Empty Block (label) sum::@1
|
||||||
|
Succesful SSA optimization Pass2CullEmptyBlocks
|
||||||
|
CONTROL FLOW GRAPH
|
||||||
|
@BEGIN: from
|
||||||
|
call sum param-assignment
|
||||||
|
to:@2
|
||||||
|
@2: from @BEGIN
|
||||||
|
call sum param-assignment
|
||||||
|
to:@END
|
||||||
|
sum: from @2 @BEGIN
|
||||||
|
(byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 )
|
||||||
|
(byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 )
|
||||||
|
(byte) sum::return#2 ← (byte) sum::a#2 + (byte) sum::b#2
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum
|
||||||
|
(byte) s1#0 ← phi( sum/(byte) sum::return#2 )
|
||||||
|
return (byte) s1#0
|
||||||
|
to:@RETURN
|
||||||
|
@END: from @2
|
||||||
|
|
||||||
|
Alias (byte) s1#0 = (byte) sum::return#2
|
||||||
|
Succesful SSA optimization Pass2AliasElimination
|
||||||
|
CONTROL FLOW GRAPH
|
||||||
|
@BEGIN: from
|
||||||
|
call sum param-assignment
|
||||||
|
to:@2
|
||||||
|
@2: from @BEGIN
|
||||||
|
call sum param-assignment
|
||||||
|
to:@END
|
||||||
|
sum: from @2 @BEGIN
|
||||||
|
(byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 )
|
||||||
|
(byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 )
|
||||||
|
(byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2
|
||||||
|
to:sum::@return
|
||||||
|
sum::@return: from sum
|
||||||
|
return (byte) s1#0
|
||||||
|
to:@RETURN
|
||||||
|
@END: from @2
|
||||||
|
|
||||||
|
INITIAL ASM
|
||||||
|
BBEGIN:
|
||||||
|
sum_from_BBEGIN:
|
||||||
|
// (byte) sum::b#2 = (byte) 2 // zpby1=coby1
|
||||||
|
lda #2
|
||||||
|
sta 3
|
||||||
|
// (byte) sum::a#2 = (byte) 1 // zpby1=coby1
|
||||||
|
lda #1
|
||||||
|
sta 2
|
||||||
|
jsr sum
|
||||||
|
jmp B2
|
||||||
|
B2:
|
||||||
|
sum_from_B2:
|
||||||
|
// (byte) sum::b#2 = (byte) 13 // zpby1=coby1
|
||||||
|
lda #13
|
||||||
|
sta 3
|
||||||
|
// (byte) sum::a#2 = (byte) 9 // zpby1=coby1
|
||||||
|
lda #9
|
||||||
|
sta 2
|
||||||
|
jsr sum
|
||||||
|
jmp BEND
|
||||||
|
BEND:
|
||||||
|
sum:
|
||||||
|
// (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 // zpby1=zpby2_plus_zpby3
|
||||||
|
lda 2
|
||||||
|
clc
|
||||||
|
adc 3
|
||||||
|
sta 4
|
||||||
|
jmp sum__Breturn
|
||||||
|
sum__Breturn:
|
||||||
|
rts
|
||||||
|
|
||||||
|
Removing instruction jmp B2
|
||||||
|
Removing instruction jmp BEND
|
||||||
|
Removing instruction jmp sum__Breturn
|
||||||
|
Succesful ASM optimization Pass4NextJumpElimination
|
||||||
|
ASSEMBLER
|
||||||
|
BBEGIN:
|
||||||
|
sum_from_BBEGIN:
|
||||||
|
// (byte) sum::b#2 = (byte) 2 // zpby1=coby1
|
||||||
|
lda #2
|
||||||
|
sta 3
|
||||||
|
// (byte) sum::a#2 = (byte) 1 // zpby1=coby1
|
||||||
|
lda #1
|
||||||
|
sta 2
|
||||||
|
jsr sum
|
||||||
|
B2:
|
||||||
|
sum_from_B2:
|
||||||
|
// (byte) sum::b#2 = (byte) 13 // zpby1=coby1
|
||||||
|
lda #13
|
||||||
|
sta 3
|
||||||
|
// (byte) sum::a#2 = (byte) 9 // zpby1=coby1
|
||||||
|
lda #9
|
||||||
|
sta 2
|
||||||
|
jsr sum
|
||||||
|
BEND:
|
||||||
|
sum:
|
||||||
|
// (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 // zpby1=zpby2_plus_zpby3
|
||||||
|
lda 2
|
||||||
|
clc
|
||||||
|
adc 3
|
||||||
|
sta 4
|
||||||
|
sum__Breturn:
|
||||||
|
rts
|
||||||
|
|
||||||
|
FINAL SYMBOL TABLE
|
||||||
|
(label) @2
|
||||||
|
(label) @BEGIN
|
||||||
|
(label) @END
|
||||||
|
(byte) s1
|
||||||
|
(byte) s1#0 zp byte:4
|
||||||
|
(byte) s2
|
||||||
|
(byte()) sum((byte) sum::a , (byte) sum::b)
|
||||||
|
(label) sum::@return
|
||||||
|
(byte) sum::a
|
||||||
|
(byte) sum::a#2 zp byte:2
|
||||||
|
(byte) sum::b
|
||||||
|
(byte) sum::b#2 zp byte:3
|
||||||
|
(byte) sum::return
|
||||||
|
|
||||||
|
|
||||||
|
FINAL CODE
|
||||||
|
BBEGIN:
|
||||||
|
sum_from_BBEGIN:
|
||||||
|
// (byte) sum::b#2 = (byte) 2 // zpby1=coby1
|
||||||
|
lda #2
|
||||||
|
sta 3
|
||||||
|
// (byte) sum::a#2 = (byte) 1 // zpby1=coby1
|
||||||
|
lda #1
|
||||||
|
sta 2
|
||||||
|
jsr sum
|
||||||
|
B2:
|
||||||
|
sum_from_B2:
|
||||||
|
// (byte) sum::b#2 = (byte) 13 // zpby1=coby1
|
||||||
|
lda #13
|
||||||
|
sta 3
|
||||||
|
// (byte) sum::a#2 = (byte) 9 // zpby1=coby1
|
||||||
|
lda #9
|
||||||
|
sta 2
|
||||||
|
jsr sum
|
||||||
|
BEND:
|
||||||
|
sum:
|
||||||
|
// (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 // zpby1=zpby2_plus_zpby3
|
||||||
|
lda 2
|
||||||
|
clc
|
||||||
|
adc 3
|
||||||
|
sta 4
|
||||||
|
sum__Breturn:
|
||||||
|
rts
|
||||||
|
|
14
src/dk/camelot64/kickc/test/ref/summin.sym
Normal file
14
src/dk/camelot64/kickc/test/ref/summin.sym
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
(label) @2
|
||||||
|
(label) @BEGIN
|
||||||
|
(label) @END
|
||||||
|
(byte) s1
|
||||||
|
(byte) s1#0 zp byte:4
|
||||||
|
(byte) s2
|
||||||
|
(byte()) sum((byte) sum::a , (byte) sum::b)
|
||||||
|
(label) sum::@return
|
||||||
|
(byte) sum::a
|
||||||
|
(byte) sum::a#2 zp byte:2
|
||||||
|
(byte) sum::b
|
||||||
|
(byte) sum::b#2 zp byte:3
|
||||||
|
(byte) sum::return
|
||||||
|
|
5
src/dk/camelot64/kickc/test/summin.kc
Normal file
5
src/dk/camelot64/kickc/test/summin.kc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
byte s1=sum(1,2);
|
||||||
|
byte s2=sum(9,13);
|
||||||
|
byte sum(byte a, byte b) {
|
||||||
|
return a+b;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user