mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-22 03:38:31 +00:00
Propagating live ranges backwards through calls to avoid coalescing variables in procedures with variables alive outside during the call.
This commit is contained in:
parent
9634741d76
commit
438bdc38b4
@ -44,11 +44,11 @@ public class ControlFlowGraphBaseVisitor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public T visitProcedureBegin(StatementProcedureBegin statement) {
|
||||
public T visitProcedureBegin(StatementProcedureBegin procedureBegin) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public T visitProcedureEnd(StatementProcedureEnd statement) {
|
||||
public T visitProcedureEnd(StatementProcedureEnd procedureEnd) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ public class ControlFlowGraphBaseVisitor<T> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public T visitCall(StatementCall callLValue) {
|
||||
public T visitCall(StatementCall call) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -157,10 +157,10 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatementCall visitCall(StatementCall callLValue) {
|
||||
LValue lValue = callLValue.getlValue();
|
||||
String procedureName = callLValue.getProcedureName();
|
||||
List<RValue> parameters = callLValue.getParameters();
|
||||
public StatementCall visitCall(StatementCall origCall) {
|
||||
LValue lValue = origCall.getlValue();
|
||||
String procedureName = origCall.getProcedureName();
|
||||
List<RValue> parameters = origCall.getParameters();
|
||||
return new StatementCall(lValue, procedureName, parameters);
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,21 @@ public class ProcedureRef extends SymbolRef {
|
||||
super(fullName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the label of the block where the procedure code starts
|
||||
* @return The label of the code block
|
||||
*/
|
||||
@JsonIgnore
|
||||
public LabelRef getLabelRef() {
|
||||
return new LabelRef(getFullName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the label of the block containing the final procedure return
|
||||
* @return The label of the code block
|
||||
*/
|
||||
@JsonIgnore
|
||||
public LabelRef getReturnBlock() {
|
||||
return new LabelRef(getFullName()+"::@return");
|
||||
}
|
||||
}
|
||||
|
@ -71,11 +71,11 @@ public class Pass2AssertBlocks extends Pass2SsaAssertion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCall(StatementCall callLValue) {
|
||||
ProcedureRef procedure = callLValue.getProcedure();
|
||||
public Void visitCall(StatementCall call) {
|
||||
ProcedureRef procedure = call.getProcedure();
|
||||
LabelRef procLabelRef = procedure.getLabelRef();
|
||||
assertBlock(procLabelRef);
|
||||
return super.visitCall(callLValue);
|
||||
return super.visitCall(call);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -20,9 +20,9 @@ public class Pass2AssertNoCallLvalues extends Pass2SsaAssertion {
|
||||
ControlFlowGraphBaseVisitor<Void> checkCalls = new ControlFlowGraphBaseVisitor<Void>() {
|
||||
|
||||
@Override
|
||||
public Void visitCall(StatementCall callLValue) {
|
||||
if(callLValue.getlValue()!=null) {
|
||||
throw new AssertionFailed("No call lValue allowed! "+callLValue);
|
||||
public Void visitCall(StatementCall call) {
|
||||
if(call.getlValue()!=null) {
|
||||
throw new AssertionFailed("No call lValue allowed! "+ call);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -18,10 +18,10 @@ public class Pass2AssertNoCallParameters extends Pass2SsaAssertion {
|
||||
ControlFlowGraphBaseVisitor<Void> checkCalls = new ControlFlowGraphBaseVisitor<Void>() {
|
||||
|
||||
@Override
|
||||
public Void visitCall(StatementCall callLValue) {
|
||||
List<RValue> parameters = callLValue.getParameters();
|
||||
public Void visitCall(StatementCall call) {
|
||||
List<RValue> parameters = call.getParameters();
|
||||
if(parameters!=null && parameters.size()>0) {
|
||||
throw new AssertionFailed("No call parameters allowed! "+callLValue);
|
||||
throw new AssertionFailed("No call parameters allowed! "+ call);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -15,13 +15,13 @@ public class Pass2AssertNoProcs extends Pass2SsaAssertion {
|
||||
ControlFlowGraphBaseVisitor<Void> checkCalls = new ControlFlowGraphBaseVisitor<Void>() {
|
||||
|
||||
@Override
|
||||
public Void visitProcedureBegin(StatementProcedureBegin statement) {
|
||||
throw new AssertionFailed("No proc statements allowed! "+statement);
|
||||
public Void visitProcedureBegin(StatementProcedureBegin procedureBegin) {
|
||||
throw new AssertionFailed("No proc statements allowed! "+ procedureBegin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitProcedureEnd(StatementProcedureEnd statement) {
|
||||
throw new AssertionFailed("No proc statements allowed! "+statement);
|
||||
public Void visitProcedureEnd(StatementProcedureEnd procedureEnd) {
|
||||
throw new AssertionFailed("No proc statements allowed! "+ procedureEnd);
|
||||
}
|
||||
};
|
||||
checkCalls.visitGraph(getGraph());
|
||||
|
@ -91,19 +91,19 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitProcedureBegin(StatementProcedureBegin statement) {
|
||||
ProcedureRef procedureRef = statement.getProcedure();
|
||||
public Void visitProcedureBegin(StatementProcedureBegin procedureBegin) {
|
||||
ProcedureRef procedureRef = procedureBegin.getProcedure();
|
||||
Procedure procedure = programScope.getProcedure(procedureRef);
|
||||
symbols.add(procedure);
|
||||
return super.visitProcedureBegin(statement);
|
||||
return super.visitProcedureBegin(procedureBegin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitProcedureEnd(StatementProcedureEnd statement) {
|
||||
ProcedureRef procedureRef = statement.getProcedure();
|
||||
public Void visitProcedureEnd(StatementProcedureEnd procedureEnd) {
|
||||
ProcedureRef procedureRef = procedureEnd.getProcedure();
|
||||
Procedure procedure = programScope.getProcedure(procedureRef);
|
||||
symbols.add(procedure);
|
||||
return super.visitProcedureEnd(statement);
|
||||
return super.visitProcedureEnd(procedureEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -141,15 +141,15 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCall(StatementCall callLValue) {
|
||||
addSymbol(callLValue.getlValue());
|
||||
addSymbol(callLValue.getProcedure());
|
||||
if(callLValue.getParameters()!=null) {
|
||||
for (RValue param : callLValue.getParameters()) {
|
||||
public Void visitCall(StatementCall call) {
|
||||
addSymbol(call.getlValue());
|
||||
addSymbol(call.getProcedure());
|
||||
if(call.getParameters()!=null) {
|
||||
for (RValue param : call.getParameters()) {
|
||||
addSymbol(param);
|
||||
}
|
||||
}
|
||||
return super.visitCall(callLValue);
|
||||
return super.visitCall(call);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -147,15 +147,15 @@ public class Pass3LiveRangesAnalysis {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCall(StatementCall callLValue) {
|
||||
if (callLValue.getlValue() instanceof PointerDereferenceIndexed) {
|
||||
addInitialLiveRange(((PointerDereferenceIndexed) callLValue.getlValue()).getPointer());
|
||||
addInitialLiveRange(((PointerDereferenceIndexed) callLValue.getlValue()).getIndex());
|
||||
} else if (callLValue.getlValue() instanceof PointerDereferenceSimple) {
|
||||
addInitialLiveRange(((PointerDereferenceSimple) callLValue.getlValue()).getPointer());
|
||||
public Void visitCall(StatementCall call) {
|
||||
if (call.getlValue() instanceof PointerDereferenceIndexed) {
|
||||
addInitialLiveRange(((PointerDereferenceIndexed) call.getlValue()).getPointer());
|
||||
addInitialLiveRange(((PointerDereferenceIndexed) call.getlValue()).getIndex());
|
||||
} else if (call.getlValue() instanceof PointerDereferenceSimple) {
|
||||
addInitialLiveRange(((PointerDereferenceSimple) call.getlValue()).getPointer());
|
||||
}
|
||||
if (callLValue.getParameters() != null) {
|
||||
for (RValue parameter : callLValue.getParameters()) {
|
||||
if (call.getParameters() != null) {
|
||||
for (RValue parameter : call.getParameters()) {
|
||||
addInitialLiveRange(parameter);
|
||||
}
|
||||
}
|
||||
@ -287,19 +287,41 @@ public class Pass3LiveRangesAnalysis {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the statement executed just before entering a specific block
|
||||
*
|
||||
* @param block The block to find the previous statement for
|
||||
* @return The statement executed just before entering the block.
|
||||
* If there are several predecessor blocks multiple statements are returned.
|
||||
*/
|
||||
private ArrayList<Statement> getPreviousStatements(ControlFlowBlock block) {
|
||||
ArrayList<Statement> statements = new ArrayList<>();
|
||||
List<ControlFlowBlock> predecessors = program.getGraph().getPredecessors(block);
|
||||
for (ControlFlowBlock predecessor : predecessors) {
|
||||
List<Statement> predecessorStatements = predecessor.getStatements();
|
||||
if (predecessorStatements.size() == 0) {
|
||||
// Predecessor has no statements - go further back!
|
||||
statements.addAll(getPreviousStatements(predecessor));
|
||||
} else {
|
||||
// Add last statement from predecessor
|
||||
Statement predecessorLastStatement = predecessorStatements.get(predecessorStatements.size() - 1);
|
||||
statements.add(predecessorLastStatement);
|
||||
}
|
||||
ArrayList<Statement> lastStatements = getLastStatements(predecessor);
|
||||
|
||||
|
||||
statements.addAll(lastStatements);
|
||||
}
|
||||
return statements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last statement executed in a specific block.
|
||||
* If the block is empty the last statement of the previous block is returned.
|
||||
* @param block The block to examine
|
||||
* @return The last statement of the block (or the last statement of previous blocks if the block is empty)
|
||||
*/
|
||||
private ArrayList<Statement> getLastStatements(ControlFlowBlock block) {
|
||||
ArrayList<Statement> statements = new ArrayList<>();
|
||||
List<Statement> blockStatements = block.getStatements();
|
||||
if (blockStatements.size() == 0) {
|
||||
// Block has no statements - go further back!
|
||||
statements.addAll(getPreviousStatements(block));
|
||||
} else {
|
||||
// Add last statement from block
|
||||
Statement predecessorLastStatement = blockStatements.get(blockStatements.size() - 1);
|
||||
statements.add(predecessorLastStatement);
|
||||
}
|
||||
return statements;
|
||||
}
|
||||
@ -315,47 +337,48 @@ public class Pass3LiveRangesAnalysis {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitCall(StatementCall callLValue) {
|
||||
if (callLValue.getlValue() != null) {
|
||||
propagate(callLValue, getPreviousStatements(), Arrays.asList(callLValue.getlValue()));
|
||||
}
|
||||
public Void visitCall(StatementCall call) {
|
||||
propagate(call, getPreviousStatements(), null);
|
||||
// Also propagate back through all statements of the procedure
|
||||
ProcedureRef procedure = call.getProcedure();
|
||||
LabelRef procedureReturnBlock = procedure.getReturnBlock();
|
||||
ControlFlowBlock returnBlock = program.getGraph().getBlock(procedureReturnBlock);
|
||||
propagate(call, getLastStatements(returnBlock), null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitAssignment(StatementAssignment assignment) {
|
||||
if (assignment.getlValue() != null) {
|
||||
propagate(assignment, getPreviousStatements(), Arrays.asList(assignment.getlValue()));
|
||||
}
|
||||
propagate(assignment, getPreviousStatements(), Arrays.asList(assignment.getlValue()));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitConditionalJump(StatementConditionalJump conditionalJump) {
|
||||
propagate(conditionalJump, getPreviousStatements(), new ArrayList<LValue>());
|
||||
propagate(conditionalJump, getPreviousStatements(), null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitJump(StatementJump jump) {
|
||||
propagate(jump, getPreviousStatements(), new ArrayList<LValue>());
|
||||
propagate(jump, getPreviousStatements(), null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitReturn(StatementReturn aReturn) {
|
||||
propagate(aReturn, getPreviousStatements(), new ArrayList<LValue>());
|
||||
propagate(aReturn, getPreviousStatements(), null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitProcedureBegin(StatementProcedureBegin statement) {
|
||||
throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + statement);
|
||||
public Void visitProcedureBegin(StatementProcedureBegin procedureBegin) {
|
||||
throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + procedureBegin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitProcedureEnd(StatementProcedureEnd statement) {
|
||||
throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + statement);
|
||||
public Void visitProcedureEnd(StatementProcedureEnd procedureEnd) {
|
||||
throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + procedureEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,6 +58,11 @@ public class TestCompilationOutput extends TestCase {
|
||||
tester.testFile("loopnest");
|
||||
}
|
||||
|
||||
public void testLoopNest2() throws IOException, URISyntaxException {
|
||||
TestCompilationOutput tester = new TestCompilationOutput();
|
||||
tester.testFile("loopnest2");
|
||||
}
|
||||
|
||||
|
||||
private void testFile(String fileName) throws IOException, URISyntaxException {
|
||||
String inputPath = testPath + fileName + ".kc";
|
||||
|
@ -3,31 +3,15 @@ byte* SCREEN = $0400;
|
||||
main();
|
||||
|
||||
void main() {
|
||||
byte i=100;
|
||||
do {
|
||||
byte j=100;
|
||||
do {
|
||||
nest1();
|
||||
} while (--j>0)
|
||||
} while (--i>0)
|
||||
byte i=100;
|
||||
do {
|
||||
nest();
|
||||
} while (--i>0)
|
||||
}
|
||||
|
||||
void nest1() {
|
||||
byte i=100;
|
||||
do {
|
||||
byte j=100;
|
||||
do {
|
||||
nest2();
|
||||
} while (--j>0)
|
||||
} while (--i>0)
|
||||
}
|
||||
|
||||
void nest2() {
|
||||
byte i=100;
|
||||
do {
|
||||
byte j=100;
|
||||
do {
|
||||
*SCREEN = j;
|
||||
} while (--j>0)
|
||||
} while (--i>0)
|
||||
void nest() {
|
||||
byte j=100;
|
||||
do {
|
||||
*SCREEN = j;
|
||||
} while (--j>0)
|
||||
}
|
||||
|
33
src/dk/camelot64/kickc/test/loopnest2.kc
Normal file
33
src/dk/camelot64/kickc/test/loopnest2.kc
Normal file
@ -0,0 +1,33 @@
|
||||
byte* SCREEN = $0400;
|
||||
|
||||
main();
|
||||
|
||||
void main() {
|
||||
byte i=100;
|
||||
do {
|
||||
byte j=100;
|
||||
do {
|
||||
nest1();
|
||||
} while (--j>0)
|
||||
} while (--i>0)
|
||||
}
|
||||
|
||||
void nest1() {
|
||||
byte i=100;
|
||||
do {
|
||||
byte j=100;
|
||||
do {
|
||||
nest2();
|
||||
} while (--j>0)
|
||||
} while (--i>0)
|
||||
}
|
||||
|
||||
void nest2() {
|
||||
byte i=100;
|
||||
do {
|
||||
byte j=100;
|
||||
do {
|
||||
*SCREEN = j;
|
||||
} while (--j>0)
|
||||
} while (--i>0)
|
||||
}
|
@ -7,63 +7,23 @@ main__B1_from_main:
|
||||
sta 2
|
||||
main__B1_from_B3:
|
||||
main__B1:
|
||||
main__B2_from_B1:
|
||||
lda #100
|
||||
sta 3
|
||||
main__B2_from_B5:
|
||||
main__B2:
|
||||
jsr nest1
|
||||
main__B5:
|
||||
dec 3
|
||||
lda 3
|
||||
bne main__B2_from_B5
|
||||
jsr nest
|
||||
main__B3:
|
||||
dec 2
|
||||
lda 2
|
||||
bne main__B1_from_B3
|
||||
main__Breturn:
|
||||
rts
|
||||
nest1:
|
||||
nest1__B1_from_nest1:
|
||||
lda #100
|
||||
sta 2
|
||||
nest1__B1_from_B3:
|
||||
nest1__B1:
|
||||
nest1__B2_from_B1:
|
||||
nest:
|
||||
nest__B1_from_nest:
|
||||
lda #100
|
||||
sta 3
|
||||
nest1__B2_from_B5:
|
||||
nest1__B2:
|
||||
jsr nest2
|
||||
nest1__B5:
|
||||
dec 3
|
||||
lda 3
|
||||
bne nest1__B2_from_B5
|
||||
nest1__B3:
|
||||
dec 2
|
||||
lda 2
|
||||
bne nest1__B1_from_B3
|
||||
nest1__Breturn:
|
||||
rts
|
||||
nest2:
|
||||
nest2__B1_from_nest2:
|
||||
lda #100
|
||||
sta 2
|
||||
nest2__B1_from_B3:
|
||||
nest2__B1:
|
||||
nest2__B2_from_B1:
|
||||
lda #100
|
||||
sta 3
|
||||
nest2__B2_from_B2:
|
||||
nest2__B2:
|
||||
nest__B1_from_B1:
|
||||
nest__B1:
|
||||
lda 3
|
||||
sta 1024
|
||||
dec 3
|
||||
lda 3
|
||||
bne nest2__B2_from_B2
|
||||
nest2__B3:
|
||||
dec 2
|
||||
lda 2
|
||||
bne nest2__B1_from_B3
|
||||
nest2__Breturn:
|
||||
bne nest__B1_from_B1
|
||||
nest__Breturn:
|
||||
rts
|
||||
|
@ -5,58 +5,24 @@
|
||||
main: from @BEGIN
|
||||
to:main::@1
|
||||
main::@1: from main main::@3
|
||||
[1] (byte) main::i#2 ← phi( main/(byte) 100 main::@3/(byte) main::i#1 ) [ ]
|
||||
to:main::@2
|
||||
main::@2: from main::@1 main::@5
|
||||
[2] (byte) main::j#2 ← phi( main::@1/(byte) 100 main::@5/(byte) main::j#1 ) [ ]
|
||||
[3] call nest1 param-assignment [ main::j#2 main::i#2 ]
|
||||
to:main::@5
|
||||
main::@5: from main::@2
|
||||
[4] (byte) main::j#1 ← -- (byte) main::j#2 [ main::j#1 main::i#2 ]
|
||||
[5] if((byte) main::j#1>(byte) 0) goto main::@2 [ main::j#1 main::i#2 ]
|
||||
[1] (byte) main::i#2 ← phi( main/(byte) 100 main::@3/(byte) main::i#1 ) [ main::i#2 ]
|
||||
[2] call nest param-assignment [ main::i#2 ]
|
||||
to:main::@3
|
||||
main::@3: from main::@5
|
||||
[6] (byte) main::i#1 ← -- (byte) main::i#2 [ main::i#1 ]
|
||||
[7] if((byte) main::i#1>(byte) 0) goto main::@1 [ main::i#1 ]
|
||||
main::@3: from main::@1
|
||||
[3] (byte) main::i#1 ← -- (byte) main::i#2 [ main::i#1 ]
|
||||
[4] if((byte) main::i#1>(byte) 0) goto main::@1 [ main::i#1 ]
|
||||
to:main::@return
|
||||
main::@return: from main::@3
|
||||
[8] return [ ]
|
||||
[5] return [ ]
|
||||
to:@RETURN
|
||||
nest1: from main::@2
|
||||
to:nest1::@1
|
||||
nest1::@1: from nest1 nest1::@3
|
||||
[9] (byte) nest1::i#2 ← phi( nest1/(byte) 100 nest1::@3/(byte) nest1::i#1 ) [ ]
|
||||
to:nest1::@2
|
||||
nest1::@2: from nest1::@1 nest1::@5
|
||||
[10] (byte) nest1::j#2 ← phi( nest1::@1/(byte) 100 nest1::@5/(byte) nest1::j#1 ) [ ]
|
||||
[11] call nest2 param-assignment [ nest1::j#2 nest1::i#2 ]
|
||||
to:nest1::@5
|
||||
nest1::@5: from nest1::@2
|
||||
[12] (byte) nest1::j#1 ← -- (byte) nest1::j#2 [ nest1::j#1 nest1::i#2 ]
|
||||
[13] if((byte) nest1::j#1>(byte) 0) goto nest1::@2 [ nest1::j#1 nest1::i#2 ]
|
||||
to:nest1::@3
|
||||
nest1::@3: from nest1::@5
|
||||
[14] (byte) nest1::i#1 ← -- (byte) nest1::i#2 [ nest1::i#1 ]
|
||||
[15] if((byte) nest1::i#1>(byte) 0) goto nest1::@1 [ nest1::i#1 ]
|
||||
to:nest1::@return
|
||||
nest1::@return: from nest1::@3
|
||||
[16] return [ ]
|
||||
to:@RETURN
|
||||
nest2: from nest1::@2
|
||||
to:nest2::@1
|
||||
nest2::@1: from nest2 nest2::@3
|
||||
[17] (byte) nest2::i#2 ← phi( nest2/(byte) 100 nest2::@3/(byte) nest2::i#1 ) [ nest2::i#2 ]
|
||||
to:nest2::@2
|
||||
nest2::@2: from nest2::@1 nest2::@2
|
||||
[18] (byte) nest2::j#2 ← phi( nest2::@1/(byte) 100 nest2::@2/(byte) nest2::j#1 ) [ nest2::j#2 nest2::i#2 ]
|
||||
[19] *((word) 1024) ← (byte) nest2::j#2 [ nest2::j#2 nest2::i#2 ]
|
||||
[20] (byte) nest2::j#1 ← -- (byte) nest2::j#2 [ nest2::j#1 nest2::i#2 ]
|
||||
[21] if((byte) nest2::j#1>(byte) 0) goto nest2::@2 [ nest2::j#1 nest2::i#2 ]
|
||||
to:nest2::@3
|
||||
nest2::@3: from nest2::@2
|
||||
[22] (byte) nest2::i#1 ← -- (byte) nest2::i#2 [ nest2::i#1 ]
|
||||
[23] if((byte) nest2::i#1>(byte) 0) goto nest2::@1 [ nest2::i#1 ]
|
||||
to:nest2::@return
|
||||
nest2::@return: from nest2::@3
|
||||
[24] return [ ]
|
||||
nest: from main::@1
|
||||
to:nest::@1
|
||||
nest::@1: from nest nest::@1
|
||||
[6] (byte) nest::j#2 ← phi( nest/(byte) 100 nest::@1/(byte) nest::j#1 ) [ main::i#2 nest::j#2 ]
|
||||
[7] *((word) 1024) ← (byte) nest::j#2 [ main::i#2 nest::j#2 ]
|
||||
[8] (byte) nest::j#1 ← -- (byte) nest::j#2 [ main::i#2 nest::j#1 ]
|
||||
[9] if((byte) nest::j#1>(byte) 0) goto nest::@1 [ main::i#2 nest::j#1 ]
|
||||
to:nest::@return
|
||||
nest::@return: from nest::@1
|
||||
[10] return [ main::i#2 ]
|
||||
to:@RETURN
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,42 +3,19 @@
|
||||
(byte*) SCREEN
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@5
|
||||
(label) main::@return
|
||||
(byte) main::i
|
||||
(byte) main::i#1 zp byte:2
|
||||
(byte) main::i#2 zp byte:2
|
||||
(byte) main::j
|
||||
(byte) main::j#1 zp byte:3
|
||||
(byte) main::j#2 zp byte:3
|
||||
|
||||
(void()) nest1()
|
||||
(label) nest1::@1
|
||||
(label) nest1::@2
|
||||
(label) nest1::@3
|
||||
(label) nest1::@5
|
||||
(label) nest1::@return
|
||||
(byte) nest1::i
|
||||
(byte) nest1::i#1 zp byte:2
|
||||
(byte) nest1::i#2 zp byte:2
|
||||
(byte) nest1::j
|
||||
(byte) nest1::j#1 zp byte:3
|
||||
(byte) nest1::j#2 zp byte:3
|
||||
|
||||
(void()) nest2()
|
||||
(label) nest2::@1
|
||||
(label) nest2::@2
|
||||
(label) nest2::@3
|
||||
(label) nest2::@return
|
||||
(byte) nest2::i
|
||||
(byte) nest2::i#1 zp byte:2
|
||||
(byte) nest2::i#2 zp byte:2
|
||||
(byte) nest2::j
|
||||
(byte) nest2::j#1 zp byte:3
|
||||
(byte) nest2::j#2 zp byte:3
|
||||
(void()) nest()
|
||||
(label) nest::@1
|
||||
(label) nest::@return
|
||||
(byte) nest::j
|
||||
(byte) nest::j#1 zp byte:3
|
||||
(byte) nest::j#2 zp byte:3
|
||||
|
||||
|
||||
zp byte:2 [ main::i#2 main::i#1 nest1::i#2 nest1::i#1 nest2::i#2 nest2::i#1 ]
|
||||
zp byte:3 [ main::j#2 main::j#1 nest1::j#2 nest1::j#1 nest2::j#2 nest2::j#1 ]
|
||||
zp byte:2 [ main::i#2 main::i#1 ]
|
||||
zp byte:3 [ nest::j#2 nest::j#1 ]
|
||||
|
69
src/dk/camelot64/kickc/test/ref/loopnest2.asm
Normal file
69
src/dk/camelot64/kickc/test/ref/loopnest2.asm
Normal file
@ -0,0 +1,69 @@
|
||||
BBEGIN:
|
||||
jsr main
|
||||
BEND:
|
||||
main:
|
||||
main__B1_from_main:
|
||||
lda #100
|
||||
sta 2
|
||||
main__B1_from_B3:
|
||||
main__B1:
|
||||
main__B2_from_B1:
|
||||
lda #100
|
||||
sta 3
|
||||
main__B2_from_B5:
|
||||
main__B2:
|
||||
jsr nest1
|
||||
main__B5:
|
||||
dec 3
|
||||
lda 3
|
||||
bne main__B2_from_B5
|
||||
main__B3:
|
||||
dec 2
|
||||
lda 2
|
||||
bne main__B1_from_B3
|
||||
main__Breturn:
|
||||
rts
|
||||
nest1:
|
||||
nest1__B1_from_nest1:
|
||||
lda #100
|
||||
sta 4
|
||||
nest1__B1_from_B3:
|
||||
nest1__B1:
|
||||
nest1__B2_from_B1:
|
||||
lda #100
|
||||
sta 5
|
||||
nest1__B2_from_B5:
|
||||
nest1__B2:
|
||||
jsr nest2
|
||||
nest1__B5:
|
||||
dec 5
|
||||
lda 5
|
||||
bne nest1__B2_from_B5
|
||||
nest1__B3:
|
||||
dec 4
|
||||
lda 4
|
||||
bne nest1__B1_from_B3
|
||||
nest1__Breturn:
|
||||
rts
|
||||
nest2:
|
||||
nest2__B1_from_nest2:
|
||||
lda #100
|
||||
sta 6
|
||||
nest2__B1_from_B3:
|
||||
nest2__B1:
|
||||
nest2__B2_from_B1:
|
||||
lda #100
|
||||
sta 7
|
||||
nest2__B2_from_B2:
|
||||
nest2__B2:
|
||||
lda 7
|
||||
sta 1024
|
||||
dec 7
|
||||
lda 7
|
||||
bne nest2__B2_from_B2
|
||||
nest2__B3:
|
||||
dec 6
|
||||
lda 6
|
||||
bne nest2__B1_from_B3
|
||||
nest2__Breturn:
|
||||
rts
|
62
src/dk/camelot64/kickc/test/ref/loopnest2.cfg
Normal file
62
src/dk/camelot64/kickc/test/ref/loopnest2.cfg
Normal file
@ -0,0 +1,62 @@
|
||||
@BEGIN: from
|
||||
[0] call main param-assignment [ ]
|
||||
to:@END
|
||||
@END: from @BEGIN
|
||||
main: from @BEGIN
|
||||
to:main::@1
|
||||
main::@1: from main main::@3
|
||||
[1] (byte) main::i#2 ← phi( main/(byte) 100 main::@3/(byte) main::i#1 ) [ main::i#2 ]
|
||||
to:main::@2
|
||||
main::@2: from main::@1 main::@5
|
||||
[2] (byte) main::j#2 ← phi( main::@1/(byte) 100 main::@5/(byte) main::j#1 ) [ main::j#2 main::i#2 ]
|
||||
[3] call nest1 param-assignment [ main::j#2 main::i#2 ]
|
||||
to:main::@5
|
||||
main::@5: from main::@2
|
||||
[4] (byte) main::j#1 ← -- (byte) main::j#2 [ main::j#1 main::i#2 ]
|
||||
[5] if((byte) main::j#1>(byte) 0) goto main::@2 [ main::j#1 main::i#2 ]
|
||||
to:main::@3
|
||||
main::@3: from main::@5
|
||||
[6] (byte) main::i#1 ← -- (byte) main::i#2 [ main::i#1 ]
|
||||
[7] if((byte) main::i#1>(byte) 0) goto main::@1 [ main::i#1 ]
|
||||
to:main::@return
|
||||
main::@return: from main::@3
|
||||
[8] return [ ]
|
||||
to:@RETURN
|
||||
nest1: from main::@2
|
||||
to:nest1::@1
|
||||
nest1::@1: from nest1 nest1::@3
|
||||
[9] (byte) nest1::i#2 ← phi( nest1/(byte) 100 nest1::@3/(byte) nest1::i#1 ) [ main::j#2 main::i#2 nest1::i#2 ]
|
||||
to:nest1::@2
|
||||
nest1::@2: from nest1::@1 nest1::@5
|
||||
[10] (byte) nest1::j#2 ← phi( nest1::@1/(byte) 100 nest1::@5/(byte) nest1::j#1 ) [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 ]
|
||||
[11] call nest2 param-assignment [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 ]
|
||||
to:nest1::@5
|
||||
nest1::@5: from nest1::@2
|
||||
[12] (byte) nest1::j#1 ← -- (byte) nest1::j#2 [ main::j#2 main::i#2 nest1::j#1 nest1::i#2 ]
|
||||
[13] if((byte) nest1::j#1>(byte) 0) goto nest1::@2 [ main::j#2 main::i#2 nest1::j#1 nest1::i#2 ]
|
||||
to:nest1::@3
|
||||
nest1::@3: from nest1::@5
|
||||
[14] (byte) nest1::i#1 ← -- (byte) nest1::i#2 [ main::j#2 main::i#2 nest1::i#1 ]
|
||||
[15] if((byte) nest1::i#1>(byte) 0) goto nest1::@1 [ main::j#2 main::i#2 nest1::i#1 ]
|
||||
to:nest1::@return
|
||||
nest1::@return: from nest1::@3
|
||||
[16] return [ main::j#2 main::i#2 ]
|
||||
to:@RETURN
|
||||
nest2: from nest1::@2
|
||||
to:nest2::@1
|
||||
nest2::@1: from nest2 nest2::@3
|
||||
[17] (byte) nest2::i#2 ← phi( nest2/(byte) 100 nest2::@3/(byte) nest2::i#1 ) [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::i#2 ]
|
||||
to:nest2::@2
|
||||
nest2::@2: from nest2::@1 nest2::@2
|
||||
[18] (byte) nest2::j#2 ← phi( nest2::@1/(byte) 100 nest2::@2/(byte) nest2::j#1 ) [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::j#2 nest2::i#2 ]
|
||||
[19] *((word) 1024) ← (byte) nest2::j#2 [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::j#2 nest2::i#2 ]
|
||||
[20] (byte) nest2::j#1 ← -- (byte) nest2::j#2 [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::j#1 nest2::i#2 ]
|
||||
[21] if((byte) nest2::j#1>(byte) 0) goto nest2::@2 [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::j#1 nest2::i#2 ]
|
||||
to:nest2::@3
|
||||
nest2::@3: from nest2::@2
|
||||
[22] (byte) nest2::i#1 ← -- (byte) nest2::i#2 [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::i#1 ]
|
||||
[23] if((byte) nest2::i#1>(byte) 0) goto nest2::@1 [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 nest2::i#1 ]
|
||||
to:nest2::@return
|
||||
nest2::@return: from nest2::@3
|
||||
[24] return [ main::j#2 main::i#2 nest1::j#2 nest1::i#2 ]
|
||||
to:@RETURN
|
2312
src/dk/camelot64/kickc/test/ref/loopnest2.log
Normal file
2312
src/dk/camelot64/kickc/test/ref/loopnest2.log
Normal file
File diff suppressed because it is too large
Load Diff
48
src/dk/camelot64/kickc/test/ref/loopnest2.sym
Normal file
48
src/dk/camelot64/kickc/test/ref/loopnest2.sym
Normal file
@ -0,0 +1,48 @@
|
||||
(label) @BEGIN
|
||||
(label) @END
|
||||
(byte*) SCREEN
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@5
|
||||
(label) main::@return
|
||||
(byte) main::i
|
||||
(byte) main::i#1 zp byte:2
|
||||
(byte) main::i#2 zp byte:2
|
||||
(byte) main::j
|
||||
(byte) main::j#1 zp byte:3
|
||||
(byte) main::j#2 zp byte:3
|
||||
|
||||
(void()) nest1()
|
||||
(label) nest1::@1
|
||||
(label) nest1::@2
|
||||
(label) nest1::@3
|
||||
(label) nest1::@5
|
||||
(label) nest1::@return
|
||||
(byte) nest1::i
|
||||
(byte) nest1::i#1 zp byte:4
|
||||
(byte) nest1::i#2 zp byte:4
|
||||
(byte) nest1::j
|
||||
(byte) nest1::j#1 zp byte:5
|
||||
(byte) nest1::j#2 zp byte:5
|
||||
|
||||
(void()) nest2()
|
||||
(label) nest2::@1
|
||||
(label) nest2::@2
|
||||
(label) nest2::@3
|
||||
(label) nest2::@return
|
||||
(byte) nest2::i
|
||||
(byte) nest2::i#1 zp byte:6
|
||||
(byte) nest2::i#2 zp byte:6
|
||||
(byte) nest2::j
|
||||
(byte) nest2::j#1 zp byte:7
|
||||
(byte) nest2::j#2 zp byte:7
|
||||
|
||||
|
||||
zp byte:2 [ main::i#2 main::i#1 ]
|
||||
zp byte:3 [ main::j#2 main::j#1 ]
|
||||
zp byte:4 [ nest1::i#2 nest1::i#1 ]
|
||||
zp byte:5 [ nest1::j#2 nest1::j#1 ]
|
||||
zp byte:6 [ nest2::i#2 nest2::i#1 ]
|
||||
zp byte:7 [ nest2::j#2 nest2::j#1 ]
|
Loading…
x
Reference in New Issue
Block a user