mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-28 16:31:36 +00:00
Java no long does infinite recursion if the C-code does. #316
This commit is contained in:
parent
665b9adbfb
commit
bf9a414099
@ -0,0 +1,4 @@
|
||||
lda {z1}+1
|
||||
pha
|
||||
lda {z1}
|
||||
pha
|
7
src/main/fragment/mos6502-common/vwuz1=vwuz2_minus_2.asm
Normal file
7
src/main/fragment/mos6502-common/vwuz1=vwuz2_minus_2.asm
Normal file
@ -0,0 +1,7 @@
|
||||
lda {z2}
|
||||
sec
|
||||
sbc #2
|
||||
sta {z1}
|
||||
lda {z2}+1
|
||||
sbc #0
|
||||
sta {z1}+1
|
@ -21,7 +21,7 @@ public class Pass1AssertNoRecursion extends Pass1Base {
|
||||
Collection<Procedure> procedures = getScope().getAllProcedures(true);
|
||||
for(Procedure procedure : procedures) {
|
||||
Collection<ScopeRef> recursiveCalls = callGraph.getRecursiveCalls(procedure.getRef());
|
||||
if(recursiveCalls.contains(procedure.getRef())) {
|
||||
if(recursiveCalls.contains(procedure.getRef()) && !procedure.getCallingConvension().equals(Procedure.CallingConvension.STACK_CALL)) {
|
||||
throw new CompileError("ERROR! Recursion not allowed! Occurs in " + procedure.getRef());
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public class Pass1ModifiedVarsAnalysis extends Pass1Base {
|
||||
Map<ProcedureRef, Set<VariableRef>> modified = new LinkedHashMap<>();
|
||||
Collection<Procedure> allProcedures = getScope().getAllProcedures(true);
|
||||
for(Procedure procedure : allProcedures) {
|
||||
Set<VariableRef> modifiedVars = getModifiedVars(procedure);
|
||||
Set<VariableRef> modifiedVars = getModifiedVars(procedure, new HashSet<>());
|
||||
modified.put(procedure.getRef(), modifiedVars);
|
||||
}
|
||||
getProgram().setProcedureModifiedVars(new ProcedureModifiedVars(modified));
|
||||
@ -39,7 +39,12 @@ public class Pass1ModifiedVarsAnalysis extends Pass1Base {
|
||||
* @param procedure The procedure to examine
|
||||
* @return All variables declared outside the procedure modified inside the procedure.
|
||||
*/
|
||||
public Set<VariableRef> getModifiedVars(Procedure procedure) {
|
||||
private Set<VariableRef> getModifiedVars(Procedure procedure, Set<ProcedureRef> visited) {
|
||||
// Avoid recursion
|
||||
if(visited.contains(procedure.getRef()))
|
||||
return new LinkedHashSet<>();
|
||||
visited.add(procedure.getRef());
|
||||
|
||||
Set<VariableRef> modified = new LinkedHashSet<>();
|
||||
ScopeRef procScope = procedure.getRef();
|
||||
List<ControlFlowBlock> procBlocks = getProgram().getGraph().getScopeBlocks(procScope);
|
||||
@ -56,7 +61,7 @@ public class Pass1ModifiedVarsAnalysis extends Pass1Base {
|
||||
if(statement instanceof StatementCalling) {
|
||||
ProcedureRef called = ((StatementCalling) statement).getProcedure();
|
||||
Procedure calledProc = getScope().getProcedure(called);
|
||||
modified.addAll(getModifiedVars(calledProc));
|
||||
modified.addAll(getModifiedVars(calledProc, visited));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,12 +54,17 @@ public class Pass3LoopDepthAnalysis extends Pass2Base {
|
||||
}
|
||||
}
|
||||
// Find the scope blocks calling the current scope block - and the loop depth of the blocks where the call statement is
|
||||
int callingDepth = getCallingDepth(currentScope);
|
||||
int callingDepth = getCallingDepth(currentScope, new HashSet<>());
|
||||
findLoopDepth(currentScope, callingDepth);
|
||||
}
|
||||
}
|
||||
|
||||
private int getCallingDepth(ScopeRef currentScope) {
|
||||
private int getCallingDepth(ScopeRef currentScope, Set<ScopeRef> visited) {
|
||||
|
||||
if(visited.contains(currentScope))
|
||||
return 10;
|
||||
visited.add(currentScope);
|
||||
|
||||
int callingDepth = 1;
|
||||
Collection<ScopeRef> callingScopes = callGraph.getCallingBlocks(currentScope);
|
||||
for(ScopeRef callingScope : callingScopes) {
|
||||
@ -82,7 +87,7 @@ public class Pass3LoopDepthAnalysis extends Pass2Base {
|
||||
}
|
||||
}
|
||||
// Also look through all callers
|
||||
int superCallingDepth = getCallingDepth(callingScope);
|
||||
int superCallingDepth = getCallingDepth(callingScope, visited);
|
||||
if(superCallingDepth>callingDepth) {
|
||||
callingDepth= superCallingDepth;
|
||||
}
|
||||
|
@ -52,11 +52,16 @@ public class PassNCalcLiveRangesEffective extends PassNCalcBase<LiveRangeVariabl
|
||||
this.procedureCallPaths = new LinkedHashMap<>();
|
||||
Collection<Procedure> procedures = getProgram().getScope().getAllProcedures(true);
|
||||
for(Procedure procedure : procedures) {
|
||||
populateProcedureCallPaths(procedure);
|
||||
populateProcedureCallPaths(procedure, new HashSet<>());
|
||||
}
|
||||
}
|
||||
|
||||
private void populateProcedureCallPaths(Procedure procedure) {
|
||||
private void populateProcedureCallPaths(Procedure procedure, Set<ProcedureRef> visited) {
|
||||
// Avoid recursion
|
||||
if(visited.contains(procedure.getRef()))
|
||||
return;
|
||||
visited.add(procedure.getRef());
|
||||
|
||||
ProcedureRef procedureRef = procedure.getRef();
|
||||
LiveRangeVariablesEffective.CallPaths callPaths = procedureCallPaths.get(procedureRef);
|
||||
if(callPaths == null) {
|
||||
@ -84,11 +89,12 @@ public class PassNCalcLiveRangesEffective extends PassNCalcBase<LiveRangeVariabl
|
||||
// Found calling procedure!
|
||||
Procedure callerProcedure = (Procedure) callScope;
|
||||
// Make sure we have populated the call-paths of the calling procedure
|
||||
populateProcedureCallPaths(callerProcedure);
|
||||
populateProcedureCallPaths(callerProcedure, visited);
|
||||
// Find variables referenced in caller procedure
|
||||
Collection<VariableRef> referencedInCaller = referenceInfo.getReferencedVars(callerProcedure.getRef().getLabelRef());
|
||||
// For each caller path - create a new call-path
|
||||
LiveRangeVariablesEffective.CallPaths callerPaths = procedureCallPaths.get(callerProcedure.getRef());
|
||||
if(callerPaths!=null)
|
||||
for(LiveRangeVariablesEffective.CallPath callerPath : callerPaths.getCallPaths()) {
|
||||
ArrayList<CallGraph.CallBlock.Call> path = new ArrayList<>(callerPath.getPath());
|
||||
path.add(caller);
|
||||
|
@ -35,6 +35,13 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void testProcedureCallingConventionStack6() throws IOException, URISyntaxException {
|
||||
compileAndCompare("procedure-callingconvention-stack-6", log()); //, log().verboseCreateSsa().verboseParse().verboseStatementSequence());
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testProcedureCallingConventionStack5() throws IOException, URISyntaxException {
|
||||
compileAndCompare("procedure-callingconvention-stack-5"); //, log().verboseCreateSsa().verboseParse().verboseStatementSequence());
|
||||
|
15
src/test/kc/procedure-callingconvention-stack-6.kc
Normal file
15
src/test/kc/procedure-callingconvention-stack-6.kc
Normal file
@ -0,0 +1,15 @@
|
||||
// Test a procedure with calling convention stack
|
||||
// Recursive fibonacci
|
||||
|
||||
const char* SCREEN = 0x0400;
|
||||
|
||||
void main(void) {
|
||||
*SCREEN = fib(5);
|
||||
}
|
||||
|
||||
char __stackcall fib(char n) {
|
||||
if (n == 0 || n == 1)
|
||||
return n;
|
||||
else
|
||||
return (fib(n-1) + fib(n-2));
|
||||
}
|
Loading…
Reference in New Issue
Block a user