mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-08 17:54:40 +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() {
|
||||
ArrayList<Variable> parameters = new ArrayList<>();
|
||||
for (String name : parameterNames) {
|
||||
parameters.add(getScope().getVariable(name));
|
||||
parameters.add(this.getVariable(name));
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
@ -133,4 +133,24 @@ public class Procedure extends Scope {
|
||||
public ProcedureRef getRef() {
|
||||
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;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/** A reference to a procedure */
|
||||
public class ProcedureRef extends SymbolRef {
|
||||
|
||||
public ProcedureRef(String fullName) {
|
||||
@JsonCreator
|
||||
public ProcedureRef( @JsonProperty("fullName") String fullName) {
|
||||
super(fullName);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public LabelRef getLabelRef() {
|
||||
return new LabelRef(getFullName());
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
@JsonSubTypes.Type(value = StatementJump.class, name = "jump"),
|
||||
@JsonSubTypes.Type(value = StatementLabel.class, name = "label"),
|
||||
@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 = StatementProcedureEnd.class, name = "procend")
|
||||
})
|
||||
|
@ -1,5 +1,9 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -16,13 +20,28 @@ public class StatementCall implements StatementLValue {
|
||||
private List<RValue> parameters;
|
||||
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.procedureName = procedureName;
|
||||
this.parameters = parameters;
|
||||
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() {
|
||||
return lValue;
|
||||
}
|
||||
@ -51,6 +70,7 @@ public class StatementCall implements StatementLValue {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public int getNumParameters() {
|
||||
return parameters.size();
|
||||
}
|
||||
@ -124,4 +144,28 @@ public class StatementCall implements StatementLValue {
|
||||
}
|
||||
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;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* 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. */
|
||||
private RValue value;
|
||||
|
||||
public StatementReturn(RValue value) {
|
||||
@JsonCreator
|
||||
public StatementReturn( @JsonProperty("value") RValue value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@ -32,4 +36,19 @@ public class StatementReturn implements Statement {
|
||||
@Override
|
||||
public String 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) {
|
||||
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
||||
currentBlock.setDefaultSuccessor(new Label("@RETURN", scope, false).getRef());
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(currentBlockScope.addLabelIntermediate().getRef());
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate().getRef());
|
||||
blockStack.pop();
|
||||
ControlFlowBlock prevBlock = blockStack.pop();
|
||||
prevBlock.setDefaultSuccessor(nextBlock.getLabel());
|
||||
|
@ -39,19 +39,28 @@ public class TestCompilationOutput extends TestCase {
|
||||
tester.testFile("bresenham");
|
||||
}
|
||||
|
||||
public void testSumMin() throws IOException, URISyntaxException {
|
||||
TestCompilationOutput tester = new TestCompilationOutput();
|
||||
tester.testFile("summin");
|
||||
}
|
||||
|
||||
private void testFile(String fileName) throws IOException, URISyntaxException {
|
||||
String inputPath = testPath + fileName + ".kc";
|
||||
System.out.println("Testing output for "+inputPath);
|
||||
CharStream input = CharStreams.fromFileName(inputPath);
|
||||
Compiler compiler = new Compiler();
|
||||
Compiler.CompilationResult output = compiler.compile(input);
|
||||
assertOutput(fileName, ".asm", output.getAsmProgram().toString(false));
|
||||
assertOutput(fileName, ".sym", output.getSymbols().getSymbolTableContents());
|
||||
assertOutput(fileName, ".cfg", output.getGraph().getAsTypedString(output.getSymbols()));
|
||||
assertOutput(fileName, ".log", output.getLog().toString());
|
||||
boolean success = true;
|
||||
success &= testOutput(fileName, ".asm", output.getAsmProgram().toString(false));
|
||||
success &= testOutput(fileName, ".sym", output.getSymbols().getSymbolTableContents());
|
||||
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 extension,
|
||||
String outputString) throws IOException, URISyntaxException {
|
||||
@ -61,7 +70,8 @@ public class TestCompilationOutput extends TestCase {
|
||||
refLines = loadReferenceLines(fileName, extension);
|
||||
} catch (Exception e) {
|
||||
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
|
||||
List<String> outLines = getOutLines(outputString);
|
||||
@ -71,14 +81,16 @@ public class TestCompilationOutput extends TestCase {
|
||||
String refLine = refLines.get(i);
|
||||
if(!outLine.equals(refLine)) {
|
||||
writeOutputFile(fileName, extension, outputString);
|
||||
fail(
|
||||
System.out.println(
|
||||
"Output does not match reference on line "+i+"\n"+
|
||||
"Reference: "+refLine+"\n"+
|
||||
"Output: "+outLine
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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:
|
||||
ldx #25
|
||||
jmp main__B2
|
||||
main__B2_from_B12:
|
||||
main__B2_from_B11:
|
||||
ldx #25
|
||||
main__B2_from_B6:
|
||||
main__B2:
|
||||
@ -24,10 +24,10 @@ main__B6:
|
||||
bne main__B2_from_B6
|
||||
main__B7:
|
||||
jsr flip
|
||||
main__B11:
|
||||
main__B10:
|
||||
jsr plot
|
||||
main__B12:
|
||||
jmp main__B2_from_B12
|
||||
main__B11:
|
||||
jmp main__B2_from_B11
|
||||
main__Breturn:
|
||||
rts
|
||||
plot:
|
||||
|
@ -4,8 +4,8 @@
|
||||
main: from @BEGIN
|
||||
call prepare param-assignment
|
||||
to:main::@2
|
||||
main::@2: from main main::@12 main::@6
|
||||
(byte) main::c#2 ← phi( main/(byte) 25 main::@6/(byte) main::c#1 main::@12/(byte) 25 )
|
||||
main::@2: from main main::@11 main::@6
|
||||
(byte) main::c#2 ← phi( main/(byte) 25 main::@6/(byte) main::c#1 main::@11/(byte) 25 )
|
||||
to:main::@3
|
||||
main::@3: from main::@2 main::@3
|
||||
(byte~) main::$1 ← * (word) 53266
|
||||
@ -21,14 +21,14 @@ main::@6: from main::@4
|
||||
to:main::@7
|
||||
main::@7: from main::@6
|
||||
call flip param-assignment
|
||||
to:main::@11
|
||||
main::@11: from main::@7
|
||||
to:main::@10
|
||||
main::@10: from main::@7
|
||||
call plot param-assignment
|
||||
to:main::@12
|
||||
main::@12: from main::@11
|
||||
to:main::@11
|
||||
main::@11: from main::@10
|
||||
if(true) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: from main::@12
|
||||
main::@return: from main::@11
|
||||
return
|
||||
to:@RETURN
|
||||
prepare: from main
|
||||
@ -75,7 +75,7 @@ flip::@3: from flip::@3 flip::@4
|
||||
flip::@return: from flip::@3
|
||||
return
|
||||
to:@RETURN
|
||||
plot: from main::@11
|
||||
plot: from main::@10
|
||||
to:plot::@1
|
||||
plot::@1: from plot plot::@3
|
||||
(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()
|
||||
(byte~) main::$1 reg byte a
|
||||
(byte~) main::$3 reg byte a
|
||||
(label) main::@10
|
||||
(label) main::@11
|
||||
(label) main::@12
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(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…
Reference in New Issue
Block a user